กราฟ PES การแยกพันธะด้วย Qunova HiVQE
Qiskit Functions เป็นฟีเจอร์ทดลองที่ใช้ได้เฉพาะผู้ใช้แผน IBM Quantum® Premium Plan, Flex Plan และ On-Prem (ผ่าน IBM Quantum Platform API) เท่านั้น อยู่ในสถานะ preview release และอาจมีการเปลี่ยนแปลง
ประมาณการการใช้งาน (หมายเหตุ: นี่เป็นเพียงการประมาณเท่านั้น เวลาจริงอาจแตกต่างออกไป)
- Li2S: ใช้เวลา QPU ประมาณห้านาทีบนโปรเซสเซอร์ Heron r2
- FeP-NO: ใช้เวลา QPU ประมาณห้านาทีบนโปรเซสเซอร์ Heron r2
พื้นหลัง
การคำนวณพลังงานของปฏิกิริยาเคมีอย่างแม่นยำมีความสำคัญอย่างยิ่งต่อความก้า วหน้าทางวิทยาศาสตร์ในด้านวัสดุศาสตร์ วิศวกรรมเคมี การค้นพบยา และสาขาอื่น ๆ ในบรรดาระบบเคมีต่าง ๆ ระบบ Li-S ได้รับความสนใจอย่างมากในการทำความเข้าใจและพัฒนาองค์ประกอบของแบตเตอรี่ใหม่ บทเรียนนี้ให้ประสบการณ์จริงในการคำนวณ potential energy surface (PES) การแยกพันธะ Li-S ของระบบ โดยการกำจัดอะตอมลิเทียมหนึ่งอะตอมโดยใช้การคำนวณ HiVQE สามารถเปรียบเทียบผลลัพธ์กับการคำนวณอ้าง อิง (CASCI) รวมถึงวิธีการแบบ classical อย่าง Hartree-Fock (HF) สำหรับปัญหา 20 Qubit
สิ่งที่ต้องการ
ติดตั้ง dependency ต่อไปนี้เพื่อรันโค้ดในบทเรียนนี้
!pip install --upgrade pip
!pip install -U qiskit-ibm-catalog "qiskit_ibm_runtime<0.42.0" pyscf numpy matplotlib typing_extensions
การตั้งค่า
ในการรันบทเรียนนี้ ให้ import ฟังก์ชัน qunova/hivqe-chemistry ผ่าน QiskitFunctionCatalog คุณต้องมีบัญชี IBM Quantum Premium Plan, Flex Plan หรือ On-Prem (IBM Quantum Platform API) Plan พร้อมใบอนุญาตจาก Qunova เพื่อรันฟังก์ชันนี้
from qiskit_ibm_catalog import QiskitFunctionsCatalog
from pyscf import gto, scf, mcscf
import matplotlib.pyplot as plt
import pprint
catalog = QiskitFunctionsCatalog(
channel="ibm_quantum_platform",
instance="INSTANCE_CRN",
token="YOUR_API_KEY", # Use the 44-character API_KEY you created and saved from the IBM Quantum Platform Home dashboard
)
hivqe = catalog.load("qunova/hivqe-chemistry")
ส่วนที่ 1: Li2S (20Q)
ขั้นตอนที่ 1: แปลงข้อมูล input แบบ classical เป็นปัญหาควอนตัม
กำหนดรูปทรงเรขาคณิตของ ในรูปแบบ dictionary สำหรับระยะห่างพันธะ Li-S ที่แตกต่างกัน เพื่อคำนวณกราฟ PES รูปทรงเหล่านี้ได้รับการ optimize โดยใช้การคำนวณ B3LYP/631g
str_geometries = {
"1.51": "S -1.239044 0.671232 -0.030374; Li -1.506327 0.432403 -1.498949; Li -0.899996 0.973348 1.826768",
"1.91": "S -1.215858 0.692272 0.099232; Li -1.553305 0.390283 -1.758043; Li -0.876205 0.994426 1.956257",
"2.40": "S -1.741432 0.680397 0.346702; Li -0.529307 0.488006 -1.729343; Li -1.284307 0.989409 2.177209",
"3.10": "S -2.347450 0.657089 0.566194; Li -0.199353 0.527517 -1.665148; Li -1.008243 0.973206 1.893522",
"3.80": "S -2.707255 0.674298 0.909161; Li 0.079218 0.552012 -1.671656; Li -0.927010 0.931502 1.557063",
"4.50": "S -2.913363 0.709175 1.276987; Li 0.368656 0.559989 -1.798088; Li -1.010340 0.888647 1.315670",
}
str_geometries
{'1.51': 'S -1.239044 0.671232 -0.030374; Li -1.506327 0.432403 -1.498949; Li -0.899996 0.973348 1.826768',
'1.91': 'S -1.215858 0.692272 0.099232; Li -1.553305 0.390283 -1.758043; Li -0.876205 0.994426 1.956257',
'2.40': 'S -1.741432 0.680397 0.346702; Li -0.529307 0.488006 -1.729343; Li -1.284307 0.989409 2.177209',
'3.10': 'S -2.347450 0.657089 0.566194; Li -0.199353 0.527517 -1.665148; Li -1.008243 0.973206 1.893522',
'3.80': 'S -2.707255 0.674298 0.909161; Li 0.079218 0.552012 -1.671656; Li -0.927010 0.931502 1.557063',
'4.50': 'S -2.913363 0.709175 1.276987; Li 0.368656 0.559989 -1.798088; Li -1.010340 0.888647 1.315670'}
การคำนวณ HiVQE จะดำเนินการด้วยตัวเลือกที่กำหนดด้านล่าง โดยใช้ basis sto3g สำหรับ มี 19 spatial orbital กับ 22 อิเล็กตรอน เพื่อรันกรณี (10o,10e) ด้วยการคำนวณ HiVQE สามารถกำหนด 10 active orbital และ 6 frozen orbital ในแต่ละ iteration จะใช้ 100 shots เพื่อ sample การกำหนด electron configuration ที่สร้างโดย Circuit ExcitationPreserving (epa) ที่มี entanglement แบบ circular และสอง repetition (reps) จำนวน iteration สูงสุดกำหนดไว้ที่ 30 เพื่อให้มั่นใจว่า iteration จะสิ้นสุดเมื่อพลังงานมีการ converge
molecule_options = {
"basis": "sto3g",
"active_orbitals": list(range(5, 15)),
"frozen_orbitals": list(range(5)),
}
hivqe_options = {
"shots": 100,
"max_iter": 30,
"ansatz": "epa",
"ansatz_entanglement": "circular",
"ansatz_reps": 2,
}
ขั้นตอนที่ 2 และ 3: Optimize ปัญหาสำหรับการรันบน quantum hardware และดำเนินการโดยใช้ฟังก์ชัน HiVQE Chemistry
ตั้งค่า for loop เพื่อรันการคำนวณ HiVQE กับรูปทรงเรขาคณิตตามตัวเลือกที่กำหนดด้านล่าง Job จะถูก submit ใน for loop ในบทเรียนนี้จะ submit รูปทรงเรขาคณิต 6 แบบและดึงผลลัพธ์เมื่อทั้งหมดเสร็จสิ้น ในการรันฟังก์ชันหลักต้องกำหนด max_states แล ะ max_expansion_states เพื่อควบคุมขนาดสูงสุดของ subspace matrix และควบคุมว่าจะสร้าง state ได้กี่ state โดยใช้วิธี classical CI expansion ต่อ iteration ID ของ function job จะถูกเก็บใน dictionary พร้อม label ของแต่ละรูปทรงเรขาคณิตเพื่อติดตามและประมวลผล output
info_jobid = {}
for dis, geom in str_geometries.items():
hivqe_run = hivqe.run(
geometry=geom,
backend_name="",
max_states=40000,
max_expansion_states=100,
molecule_options=molecule_options,
hivqe_options=hivqe_options,
)
status = hivqe_run.status()
info_jobid[dis] = hivqe_run.job_id
print(info_jobid)
{'1.51': 'de3b8818-c9db-4fa3-a3c2-d51551c2dfaf', '1.91': '55d9467a-fc85-49a8-9bc6-8f6990e421e5', '2.40': '415112b3-69ff-4d53-8b10-cb4e3be68c9e', '3.10': 'ef67b600-3887-4225-b872-e354dfdf8454', '3.80': 'b16d3502-a9e4-4560-9775-852e9d07e70f', '4.50': '0c0bffc7-af77-4a56-a656-2a2610c991d6'}
มาดูกันว่า job ทั้งหมดยังคง running หรือเสร็จสิ้นแล้ว
completed_jobs_num = 0
running_jobs_num = 0
completed_jobs = {}
for i, info in enumerate(info_jobid.items()):
dis, job_id = info
submitted_job = catalog.get_job_by_id(job_id)
stat = submitted_job.status()
print(dis, submitted_job.job_id, stat)
if stat == "DONE":
completed_jobs_num += 1
completed_jobs[dis] = submitted_job
if (stat == "RUNNING") or (stat == "QUEUED"):
running_jobs_num += 1
print(
f"Completed {completed_jobs_num} job, Running or Queued {running_jobs_num} job"
)
1.51 de3b8818-c9db-4fa3-a3c2-d51551c2dfaf DONE
1.91 55d9467a-fc85-49a8-9bc6-8f6990e421e5 DONE
2.40 415112b3-69ff-4d53-8b10-cb4e3be68c9e DONE
3.10 ef67b600-3887-4225-b872-e354dfdf8454 DONE
3.80 b16d3502-a9e4-4560-9775-852e9d07e70f DONE
4.50 0c0bffc7-af77-4a56-a656-2a2610c991d6 DONE
Completed 6 job, Running or Queued 0 job
เมื่อ job ทั้งหมดเสร็จสิ้นแล้ว มาดึงผลลัพธ์การคำนวณทั้งหมด
hivqe_result = {}
if len(info_jobid) == completed_jobs_num:
print("All jobs are completed")
for i, job in enumerate(completed_jobs.items()):
dis, cal = job
print(dis, cal.result()["energy"])
hivqe_result[str(dis)] = cal.result()["energy"]
All jobs are completed
1.51 -407.8944801731773
1.91 -407.9800570932916
2.40 -407.9372992999806
3.10 -407.86278336000134
3.80 -407.83092972296157
4.50 -407.82971011225766
pprint.pprint(hivqe_result)
{'1.51': -407.8944801731773,
'1.91': -407.9800570932916,
'2.40': -407.9372992999806,
'3.10': -407.86278336000134,
'3.80': -407.83092972296157,
'4.50': -407.82971011225766}
สามารถติดตามเวลา runtime QPU ทั้งหมดที่ใช้ใน job ได้โดยการ login เข้า IBM Quantum Platform และดู job ที่ submit ด้วย tag qunova-chemistry-hivqe
ขั้นตอนที่ 4: Post-process และเปรียบเทียบกับวิธีการแบบ classical
การคำนวณอ้างอิงแบบ classical (CASCI) สามารถทำได้สำหรับ (10o,10e) เพื่อยืนยันผลลัพธ์ HiVQE
str_geometries = {
"1.31": "S -1.250686 0.660708 -0.095168; Li -1.482812 0.453464 -1.369406; Li -0.911870 0.962810 1.762020",
"1.41": "S -1.244856 0.665971 -0.062773; Li -1.494574 0.442933 -1.434177; Li -0.905937 0.968078 1.794395",
"1.51": "S -1.239044 0.671232 -0.030374; Li -1.506327 0.432403 -1.498949; Li -0.899996 0.973348 1.826768",
"1.61": "S -1.233245 0.676492 0.002027; Li -1.518073 0.421873 -1.563722; Li -0.894049 0.978617 1.859141",
"1.71": "S -1.227453 0.681752 0.034429; Li -1.529816 0.411343 -1.628496; Li -0.888099 0.983887 1.891513",
"1.81": "S -1.221659 0.687012 0.066831; Li -1.541558 0.400813 -1.693270; Li -0.882150 0.989157 1.923885",
"1.91": "S -1.215858 0.692272 0.099232; Li -1.553305 0.390283 -1.758043; Li -0.876205 0.994426 1.956257",
"2.01": "S -1.209887 0.697544 0.131599; Li -1.565136 0.379748 -1.822800; Li -0.870344 0.999691 1.988646",
"2.11": "S -1.203945 0.702813 0.163973; Li -1.576953 0.369214 -1.887560; Li -0.864469 1.004956 2.021033",
"2.21": "S -1.198023 0.708081 0.196350; Li -1.588760 0.358680 -1.952322; Li -0.858584 1.010221 2.053417",
"2.30": "S -1.365426 0.717714 0.367060; Li -0.689401 0.458925 -1.828368; Li -1.500219 0.981173 2.255876",
"2.31": "S -1.192118 0.713348 0.228731; Li -1.600559 0.348146 -2.017085; Li -0.852690 1.015488 2.085800",
"2.40": "S -1.741432 0.680397 0.346702; Li -0.529307 0.488006 -1.729343; Li -1.284307 0.989409 2.177209",
"2.50": "S -1.885961 0.669986 0.365815; Li -0.461563 0.499084 -1.695846; Li -1.207523 0.988741 2.124599",
"2.60": "S -1.977163 0.665155 0.389784; Li -0.416654 0.504966 -1.683655; Li -1.161229 0.987690 2.088439",
"2.70": "S -2.063642 0.661518 0.418977; Li -0.367600 0.510505 -1.676408; Li -1.123804 0.985788 2.051998",
"2.80": "S -2.141072 0.659218 0.451663; Li -0.323153 0.515056 -1.673046; Li -1.090821 0.983538 2.015951",
"2.90": "S -2.212097 0.657968 0.487535; Li -0.281989 0.518909 -1.672407; Li -1.060960 0.980935 1.979440",
"3.00": "S -2.281477 0.657123 0.525155; Li -0.239607 0.523326 -1.668669; Li -1.033963 0.977363 1.938081",
"3.10": "S -2.347450 0.657089 0.566194; Li -0.199353 0.527517 -1.665148; Li -1.008243 0.973206 1.893522",
"3.20": "S -2.410882 0.657532 0.608912; Li -0.157788 0.532069 -1.659971; Li -0.986376 0.968211 1.845627",
"3.30": "S -2.470306 0.658818 0.654893; Li -0.118007 0.536237 -1.656311; Li -0.966733 0.962757 1.795986",
"3.40": "S -2.525776 0.660762 0.702910; Li -0.078312 0.540189 -1.654076; Li -0.950958 0.956861 1.745734",
"3.50": "S -2.576885 0.663376 0.752788; Li -0.039076 0.543706 -1.654536; Li -0.939085 0.950730 1.696316",
"3.60": "S -2.623930 0.666534 0.803853; Li 0.000274 0.546839 -1.657697; Li -0.931390 0.944439 1.648412",
"3.70": "S -2.667364 0.670217 0.856250; Li 0.039572 0.549616 -1.663265; Li -0.927254 0.937980 1.601583",
"3.80": "S -2.707255 0.674298 0.909161; Li 0.079218 0.552012 -1.671656; Li -0.927010 0.931502 1.557063",
"3.90": "S -2.744005 0.678718 0.962425; Li 0.119268 0.554073 -1.682595; Li -0.930310 0.925021 1.514738",
"4.00": "S -2.777891 0.683415 1.015798; Li 0.159751 0.555810 -1.696024; Li -0.936907 0.918587 1.474794",
"4.10": "S -2.809179 0.688333 1.069057; Li 0.200678 0.557234 -1.711873; Li -0.946546 0.912245 1.437385",
"4.20": "S -2.838194 0.693443 1.122205; Li 0.242066 0.558401 -1.729770; Li -0.958918 0.905968 1.402134",
"4.30": "S -2.864984 0.698619 1.174415; Li 0.283858 0.559186 -1.750539; Li -0.973920 0.900007 1.370693",
"4.40": "S -2.889984 0.703887 1.226140; Li 0.326068 0.559728 -1.773231; Li -0.991131 0.894196 1.341660",
"4.50": "S -2.913363 0.709175 1.276987; Li 0.368656 0.559989 -1.798088; Li -1.010340 0.888647 1.315670",
}
rhf_result = {}
casci_result = {}
cas_list = molecule_options["active_orbitals"]
distance_ref = []
for dis, geom in str_geometries.items():
distance_ref.append(dis)
mole = gto.M(atom=geom, basis=molecule_options["basis"])
mole.verbose = 0
# RHF energy
mf = scf.RHF(mole).run()
mo_occ = mf.mo_occ
num_elecs_as = int(sum([mo_occ[idx] for idx in cas_list]))
rhf_result[str(dis)] = mf.e_tot
# CASCI energy
casci_solver = mcscf.CASCI(mf, len(cas_list), num_elecs_as)
orbs = mcscf.addons.sort_mo(casci_solver, mf.mo_coeff, cas_list, base=0)
casci_solver.kernel(orbs)
casci_result[str(dis)] = casci_solver.e_tot
print(
f"d={dis:4.3} RHF Energy: {mf.e_tot:14.10}, CASCI Energy: {casci_solver.e_tot:14.10}"
)
d=1.3 RHF Energy: -407.7137006, CASCI Energy: -407.7193917
d=1.4 RHF Energy: -407.8183196, CASCI Energy: -407.8245211
d=1.5 RHF Energy: -407.8878013, CASCI Energy: -407.8944802
d=1.6 RHF Energy: -407.9315356, CASCI Energy: -407.9385663
d=1.7 RHF Energy: -407.9569034, CASCI Energy: -407.9641258
d=1.8 RHF Energy: -407.9693681, CASCI Energy: -407.9766313
d=1.9 RHF Energy: -407.9728592, CASCI Energy: -407.9800572
d=2.0 RHF Energy: -407.9701684, CASCI Energy: -407.9772549
d=2.1 RHF Energy: -407.9632701, CASCI Energy: -407.9702381
d=2.2 RHF Energy: -407.9535584, CASCI Energy: -407.9604007
d=2.3 RHF Energy: -407.9420173, CASCI Energy: -407.9487043
d=2.3 RHF Energy: -407.9420156, CASCI Energy: -407.9487024
d=2.4 RHF Energy: -407.9297216, CASCI Energy: -407.9372993
d=2.5 RHF Energy: -407.9172, CASCI Energy: -407.9261859
d=2.6 RHF Energy: -407.9061139, CASCI Energy: -407.915961
d=2.7 RHF Energy: -407.8937118, CASCI Energy: -407.904259
d=2.8 RHF Energy: -407.8816389, CASCI Energy: -407.8928292
d=2.9 RHF Energy: -407.8700448, CASCI Energy: -407.8819574
d=3.0 RHF Energy: -407.859054, CASCI Energy: -407.8719092
d=3.1 RHF Energy: -407.8487619, CASCI Energy: -407.8628304
d=3.2 RHF Energy: -407.8392304, CASCI Energy: -407.8548482
d=3.3 RHF Energy: -407.8304842, CASCI Energy: -407.8480217
d=3.4 RHF Energy: -407.8225124, CASCI Energy: -407.8423743
d=3.5 RHF Energy: -407.8152758, CASCI Energy: -407.8378892
d=3.6 RHF Energy: -407.8087161, CASCI Energy: -407.8345331
d=3.7 RHF Energy: -407.802764, CASCI Energy: -407.8322563
d=3.8 RHF Energy: -407.7973458, CASCI Energy: -407.83093
d=3.9 RHF Energy: -407.7923883, CASCI Energy: -407.8303555
d=4.0 RHF Energy: -407.7878216, CASCI Energy: -407.83025
d=4.1 RHF Energy: -407.783582, CASCI Energy: -407.8303243
d=4.2 RHF Energy: -407.7796124, CASCI Energy: -407.8303791
d=4.3 RHF Energy: -407.7758633, CASCI Energy: -407.8302885
d=4.4 RHF Energy: -407.7722923, CASCI Energy: -407.8300614
d=4.5 RHF Energy: -407.7688641, CASCI Energy: -407.829711
การ plot กราฟการแยกพันธ ะของ Li_2S
มา plot และเปรียบเทียบผลลัพธ์ HiVQE กับ HF และ CASCI สังเกตได้ว่าการคำนวณ HiVQE ทั้งหมดสอดคล้องกับผลลัพธ์อ้างอิงแบบ classical (CASCI) อย่างดี
fig, ax = plt.subplots(1, 1)
hf_energy = [v for key, v in rhf_result.items()]
casci_energy = [v for key, v in casci_result.items()]
hivqe_energy = [v for key, v in hivqe_result.items()]
distance_ref = [float(key) for key, v in rhf_result.items()]
distance = [float(key) for key, v in hivqe_result.items()]
ax.plot(distance_ref, hf_energy, "-o", label="RHF", c="blue")
ax.plot(distance_ref, casci_energy, "-o", label="CASCI", c="green")
ax.plot(distance, hivqe_energy, "x", label="HiVQE", c="red", markersize=20)
ax.legend(fontsize=20)
ax.tick_params("both", labelsize=16)
ax.set_xlabel("Bond distance (angstrom)", size=20)
ax.set_ylabel("Energy (Ha)", size=20)
ax.set_title("Li2S PES curve", size=20)
fig.set_size_inches(14, 8)
