ข้ามไปยังเนื้อหาหลัก

รวมทุกอย่างเข้าด้วยกันกับ Qiskit Runtime

สรุป

Victoria Lipinska สรุปสิ่งที่เราได้เรียนรู้มาจนถึงตอนนี้

เอกสารอ้างอิง

บทความต่อไปนี้ถูกอ้างอิงในวิดีโอข้างต้น

VQE กับ Qiskit patterns

เรามีส่วนประกอบที่จำเป็นทั้งหมดสำหรับการคำนวณ VQE:

  • Hamiltonian
  • Ansatz
  • Classical optimizer

ตอนนี้เราแค่ต้องนำมันมารวมกันใน Qiskit patterns framework

ขั้นตอนที่ 1: แมป classical inputs ไปยังปัญหาควอนตัม

ตามที่กล่าวไว้ก่อนหน้า เราจะสมมติว่า Hamiltonian ที่มีรูปแบบเหมาะสมของปัญหาที่สนใจถูกสร้างมาแล้ว หากมีคำถามเกี่ยวกับเรื่องนั้น ดูบทเรียนเรื่อง Hamiltonians สำหรับคำแนะนำ บล็อกโค้ดด้านล่างตั้งค่าส่วนประกอบที่อธิบายในบทเรียนก่อนหน้า ที่นี่เราเลือกแบบจำลอง H2 เพราะ Hamiltonian ของมันกระชับพอที่จะเขียนออกมาได้

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime scipy
# General imports
import numpy as np
from qiskit.quantum_info import SparsePauliOp

# Hamiltonian obtained from a previous lesson

H = SparsePauliOp(
[
"IIII",
"IIIZ",
"IZII",
"IIZI",
"ZIII",
"IZIZ",
"IIZZ",
"ZIIZ",
"IZZI",
"ZZII",
"ZIZI",
"YYYY",
"XXYY",
"YYXX",
"XXXX",
],
coeffs=[
-0.09820182 + 0.0j,
-0.1740751 + 0.0j,
-0.1740751 + 0.0j,
0.2242933 + 0.0j,
0.2242933 + 0.0j,
0.16891402 + 0.0j,
0.1210099 + 0.0j,
0.16631441 + 0.0j,
0.16631441 + 0.0j,
0.1210099 + 0.0j,
0.17504456 + 0.0j,
0.04530451 + 0.0j,
0.04530451 + 0.0j,
0.04530451 + 0.0j,
0.04530451 + 0.0j,
],
)

nuclear_repulsion = 0.7199689944489797

เราเลือก circuit efficient_su2 และ optimizer COBYLA เป็นจุดเริ่มต้น

# Pre-defined ansatz circuit
from qiskit.circuit.library import efficient_su2

# SciPy minimizer routine
from scipy.optimize import minimize

# Plotting functions

# Random initial state and efficient_su2 ansatz
ansatz = efficient_su2(H.num_qubits, su2_gates=["rx"], entanglement="linear", reps=1)
x0 = 2 * np.pi * np.random.random(ansatz.num_parameters)
print(ansatz.decompose().depth())
ansatz.decompose().draw("mpl")
5

Output of the previous code cell

ตอนนี้เราสร้าง cost function ซึ่งเกี่ยวข้องกับ Hamiltonian อย่างชัดเจน แต่แตกต่างตรงที่ Hamiltonian คือ operator ส่วนเราต้องการฟังก์ชันที่คืนค่า expectation value ของ operator นั้น โดยใช้ Estimator แน่นอนว่ามันทำสิ่งนี้โดยใช้ ansatz และ variational parameters ดังนั้นทั้งหมดจึงปรากฏเป็นอาร์กิวเมนต์ ด้านล่าง เราสร้างเวอร์ชันที่ต่างกันเล็กน้อยสำหรับใช้บน hardware จริงหรือ simulator

def cost_func(params, ansatz, H, estimator):
pub = (ansatz, [H], [params])
result = estimator.run(pubs=[pub]).result()
energy = result[0].data.evs[0]
return energy

# def cost_func_sim(params, ansatz, H, estimator):
# energy = estimator.run(ansatz, H, parameter_values=params).result().values[0]
# return energy

ขั้นตอนที่ 2: Optimize ปัญหาสำหรับการรันบนควอนตัม

เราต้องการให้โค้ดของเราทำงานอย่างมีประสิทธิภาพสูงสุดบน hardware ที่ใช้ ดังนั้นเราต้องเลือก backend เพื่อเริ่มขั้นตอนการ optimization โค้ดด้านล่างเลือก backend ที่ว่างที่สุดที่คุณสามารถเข้าถึงได้

# To run on hardware, select the backend with the fewest number of jobs in the queue
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService(channel="ibm_quantum_platform")
backend = service.least_busy(operational=True, simulator=False)
backend.name

การ optimize circuit สำหรับรันบน backend จริงเป็นหัวข้อที่มีความสำคัญมาก แต่ไม่ได้เฉพาะเจาะจงกับ VQE สำหรับตอนนี้ เราจะเพียงเตือนถึงสองคำสำคัญ:

  • optimization_level: อธิบายว่า circuit ถูกปรับให้เหมาะกับ layout ของ backend ที่เลือกมากน้อยเพียงใด ระดับ optimization ต่ำสุดทำเพียงขั้นต่ำที่จำเป็นเพื่อให้ circuit ทำงานบนอุปกรณ์ได้ โดยแมป circuit qubits ไปยัง device qubits และเพิ่ม swap gates เพื่อให้การดำเนินการสอง Qubit ทำงานได้ ระดับ optimization สูงสุดฉลาดกว่ามากและใช้เทคนิคหลายอย่างเพื่อลดจำนวน Gate ทั้งหมด เนื่องจาก multi-qubit gates มีอัตราข้อผิดพลาดสูงและ Qubit สูญสลายตามเวลา circuit ที่สั้นกว่าจึงควรให้ผลลัพธ์ที่ดีกว่า
  • Dynamical Decoupling: เราสามารถใช้ Gate sequence กับ Qubit ที่อยู่นิ่ง ซึ่งจะยกเลิกการโต้ตอบที่ไม่ต้องการกับสภาพแวดล้อมบางส่วน ดูเอกสารที่ลิงก์สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการ optimize circuits โค้ดด้านล่างสร้าง mass manager โดยใช้ preset pass managers จาก qiskit.transpiler
from qiskit.transpiler import PassManager
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.transpiler.passes import (
ALAPScheduleAnalysis,
PadDynamicalDecoupling,
ConstrainedReschedule,
)
from qiskit.circuit.library import XGate

target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
pm.scheduling = PassManager(
[
ALAPScheduleAnalysis(target=target),
ConstrainedReschedule(
acquire_alignment=target.acquire_alignment,
pulse_alignment=target.pulse_alignment,
target=target,
),
PadDynamicalDecoupling(
target=target,
dd_sequence=[XGate(), XGate()],
pulse_alignment=target.pulse_alignment,
),
]
)

# Use the pass manager and draw the resulting circuit
ansatz_isa = pm.run(ansatz)
ansatz_isa.draw(output="mpl", idle_wires=False, style="iqp")

Output of the previous code cell

เราต้องใช้คุณลักษณะ layout ของอุปกรณ์กับ Hamiltonian เช่นเดียวกัน

hamiltonian_isa = H.apply_layout(ansatz_isa.layout)
hamiltonian_isa
SparsePauliOp(['IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIZIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIIZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZIII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIZIZII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYYYII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIYYXXII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXYYII', 'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIXXXXII'],
coeffs=[-0.09820182+0.j, -0.1740751 +0.j, -0.1740751 +0.j, 0.2242933 +0.j,
0.2242933 +0.j, 0.16891402+0.j, 0.1210099 +0.j, 0.16631441+0.j,
0.16631441+0.j, 0.1210099 +0.j, 0.17504456+0.j, 0.04530451+0.j,
0.04530451+0.j, 0.04530451+0.j, 0.04530451+0.j])

ขั้นตอนที่ 3: รันโดยใช้ Qiskit Primitives

ก่อนรันบน hardware ที่เลือก เป็นความคิดที่ดีที่จะใช้ simulator สำหรับ debug เบื้องต้น และบางครั้งเพื่อประมาณข้อผิดพลาด ด้วยเหตุนี้ เราจึงแสดงวิธีรัน VQE บน simulator แบบสั้น ๆ แต่สิ่งสำคัญที่ต้องตระหนักคือ ไม่มีคอมพิวเตอร์คลาสสิก, simulator หรือ GPU ใดที่สามารถจำลอง functionality ของคอมพิวเตอร์ควอนตัม 127 Qubit ที่มี entanglement สูงได้อย่างแม่นยำ ในยุคปัจจุบันของ quantum utility, simulators จะมีประโยชน์จำกัด

ระลึกว่าสำหรับแต่ละการเลือกพารามิเตอร์ใน variational circuit จะต้องคำนวณ expectation value (เนื่องจากนั่นคือค่าที่ต้องการ minimize) อย่างที่คาดไว้ วิธีที่มีประสิทธิภาพที่สุดในการทำเช่นนั้นคือการใช้ Qiskit primitive นั่นก็คือ Estimator เราจะเริ่มด้วย local simulator ซึ่งต้องใช้เวอร์ชัน local ของ Estimator ที่เรียกว่า BackendEstimator

โดยคงไว้ซึ่ง real backend ที่ใช้สำหรับการ optimization เราสามารถ import model ของ noise behavior ของอุปกรณ์นั้นเพื่อใช้กับ local simulator ที่เลือก ที่นี่เราจะใช้ aer_simulator_statevector

# We will start by using a local simulator
from qiskit_aer import AerSimulator

# Import an estimator, this time from qiskit (we will import from Runtime for real hardware)
from qiskit.primitives import BackendEstimatorV2

# generate a simulator that mimics the real quantum system
backend_sim = AerSimulator.from_backend(backend)
estimator = BackendEstimatorV2(backend=backend_sim)

ถึงเวลาแล้วที่จะ implement VQE โดยการ minimize cost function โดยใช้ Hamiltonian, ansatz, classical optimizer และ BackendEstimator ที่เลือก ซึ่งอิงจาก real backend ที่เลือกสำหรับใช้ต่อไป สังเกตว่าที่นี่เราเลือกจำนวนการวนซ้ำสูงสุดที่ค่อนข้างน้อย เนื่องจากเราแค่ใช้ simulator เพื่อ debug ขั้นตอนการ optimize ของ VQE มักต้องการหลายร้อยการวนซ้ำจึงจะลู่เข้า

res = minimize(
cost_func,
x0,
args=(ansatz_isa, hamiltonian_isa, estimator),
method="cobyla",
options={"maxiter": 10, "disp": True},
)

print(getattr(res, "fun") - nuclear_repulsion)
print(res)
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 10 Least value of F = -0.11556938907226563
The corresponding X is:
[4.11796514 4.52126324 0.69570423 4.12781503 6.55507846 1.80713073
0.9645473 6.23812214]

-0.8355383835212453
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: -0.11556938907226563
x: [ 4.118e+00 4.521e+00 6.957e-01 4.128e+00 6.555e+00
1.807e+00 9.645e-01 6.238e+00]
nfev: 10
maxcv: 0.0

โค้ดนี้ทำงานถูกต้อง แม้ว่าจะไม่ลู่เข้าซึ่งเราคาดไว้ เราจะดำเนินการรันการคำนวณบน real hardware ต่อไป แล้วพูดถึงผลลัพธ์ สำหรับ real backends เราจะใช้ Qiskit Runtime Estimator เราจะ execute นี้ภายใน Qiskit Runtime session และโดยทั่วไปต้องการระบุ options สำหรับ session นั้น

from qiskit_ibm_runtime import QiskitRuntimeService, Session
from qiskit_ibm_runtime import EstimatorV2 as Estimator
from qiskit_ibm_runtime.options import EstimatorOptions

ในบรรดาสิ่งอื่น ๆ การใช้ session หมายความว่างานของเราจะรอคิวเพียงครั้งเดียวเพื่อเริ่มต้น การวนซ้ำต่อมาของ classical optimizer จะไม่ถูกจัดคิว ใน session เราสามารถตั้งค่า resilience และ optimization levels เครื่องมือเหล่านี้มีความสำคัญเพียงพอที่เราจะทบทวนแต่ละอย่างสั้น ๆ และความสำคัญใน VQE พร้อมลิงก์เพื่อเรียนรู้เพิ่มเติม:

  • Runtime sessions: VQE มีลักษณะวนซ้ำโดยธรรมชาติ โดย classical optimizer เลือกพารามิเตอร์ variational ใหม่ และทำให้ Gate ใหม่ถูกใช้ในแต่ละการทดลองต่อมา หากไม่ใช้ sessions อาจส่งผลให้มีเวลารอคิวเพิ่มเติมระหว่างแต่ละ trial circuit การห่อการคำนวณ VQE ไว้ใน session ทำให้มีคิวเริ่มต้นเพียงครั้งเดียวก่อนงานจะเริ่ม แต่ไม่มีเวลารอคิวเพิ่มเติมระหว่างขั้นตอน variational กลยุทธ์นี้ถูกใช้แล้วในตัวอย่างบทเรียนก่อนหน้า แต่อาจมีบทบาทสำคัญกว่าเมื่อปรับ geometry สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ sessions ดู execution modes documentation
  • การ optimize ใน Estimator: ใน Estimator มี options ในตัวสำหรับการ optimize การคำนวณ ในหลายบริบท (รวมถึง Estimator) การตั้งค่าจำกัดที่ 0 และ 1 โดย 0 หมายถึงไม่มีการ optimize และ 1 (ค่าเริ่มต้น) หมายถึงการ optimize circuit ไปยัง hardware ที่เลือกบางส่วน บริบทอื่น ๆ อนุญาตการตั้งค่า 0, 1, 2 หรือ 3 สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่ใช้ในการตั้งค่าต่าง ๆ ดู documentation ที่นี่ เราจะตั้ง optimization เป็น 0 และใช้ 'skip_transpilation = true' เพราะเราได้ transpile circuit ของเราแล้วโดยใช้ pass manager ข้างต้นในส่วน optimization
  • Resilience ใน Estimator: เช่นเดียวกับ optimization Estimator มีการตั้งค่า resilience ในตัวเพื่อต่อต้านข้อผิดพลาด ซึ่งสอดคล้องกับแนวทางต่าง ๆ ในการ mitigate ข้อผิดพลาด สำหรับข้อมูลเกี่ยวกับการตั้งค่า resilience level ดู documentation

ควรสังเกตว่า error mitigation มีบทบาทที่ละเอียดอ่อนในการลู่เข้าของการคำนวณ VQE classical optimizer กำลังค้นหา parameter space เพื่อหาพารามิเตอร์ที่ minimize พลังงาน เมื่อคุณอยู่ห่างไกลจากพารามิเตอร์ที่ดีที่สุดมาก gradient ที่ชันอาจปรากฏให้ classical optimizer เห็นได้แม้จะมีข้อผิดพลาด แต่เมื่อการคำนวณลู่เข้าและคุณเข้าใกล้ค่าที่ดีที่สุด gradient จะเล็กลงและถูก wash out โดยข้อผิดพลาดได้ง่ายขึ้น คุณต้องการใช้ error mitigation มากน้อยเพียงใด? ในจุดใดของการลู่เข้า? เหล่านี้เป็นตัวเลือกที่คุณต้องทำสำหรับกรณีการใช้งานของคุณ

สำหรับการรัน hardware ครั้งแรกนี้ เราตั้ง resilience เป็น 0 เพื่อให้การรันค่อนข้างรวดเร็ว สำหรับการใช้งานจริงจัง คุณจะต้องใช้ error mitigation สังเกตว่าในเซลล์ด้านล่างมีสอง set ของ options: (1) options สำหรับ Runtime session ซึ่งเราตั้งชื่อว่า "session_options" และ (2) options สำหรับ classical optimizer เรียกง่าย ๆ ว่า "options" ที่นี่

estimator_options = EstimatorOptions(resilience_level=0, default_shots=2000)
with Session(backend=backend) as session:
estimator = Estimator(mode=session, options=estimator_options)

res = minimize(
cost_func,
x0,
args=(ansatz_isa, hamiltonian_isa, estimator),
method="cobyla",
options={"maxiter": 10, "disp": True},
)
Return from COBYLA because the objective function has been evaluated MAXFUN times.
Number of function values = 10 Least value of F = -0.11691688904
The corresponding X is:
[5.11796514 5.52126324 0.69570423 5.12781503 6.55507846 1.80713073
1.9645473 6.23812214]

คุณสามารถดูความคืบหน้าของงานบน IBM Quantum® Platform ที่ Workloads

print(getattr(res, "fun") - nuclear_repulsion)
print(res)
-0.8368858834889796
message: Return from COBYLA because the objective function has been evaluated MAXFUN times.
success: False
status: 3
fun: -0.11691688904
x: [ 5.118e+00 5.521e+00 6.957e-01 5.128e+00 6.555e+00
1.807e+00 1.965e+00 6.238e+00]
nfev: 10
maxcv: 0.0

ขั้นตอนที่ 4: Post-process คืนผลลัพธ์ในรูปแบบ classical

มาทำความเข้าใจกับผลลัพธ์เหล่านี้ให้ชัดเจน ผลลัพธ์ "fun" คือค่าต่ำสุดที่เราได้จาก cost function (ไม่จำเป็นต้องเป็นค่าสุดท้ายที่คำนวณ) นี่คือพลังงานรวม รวมถึงพลังงานผลักดัน nuclear ที่เป็นบวก นั่นเป็นเหตุผลที่เราสร้าง electron_energy ไว้ด้วย

ในกรณีข้างต้น เรามีข้อความที่บอกว่าจำนวนการประเมิน function สูงสุดถูกเกิน และจำนวนการประเมิน function (nfev) คือ 10 ซึ่งหมายความว่าเกณฑ์อื่นสำหรับการลู่เข้าของการ optimization ไม่ถูกบรรลุ กล่าวอีกนัยหนึ่งคือไม่มีเหตุผลที่คิดว่าเราพบพลังงาน ground state แล้ว นี่ยังเป็นความหมายของ success ที่เป็น "False"

สุดท้าย เรามี x ซึ่งคือ vector ของพารามิเตอร์ variational เหล่านี้คือพารามิเตอร์ที่ใช้ในการคำนวณที่ให้ค่า cost function ต่ำสุด (expectation value ของพลังงาน) ค่าแปดค่านี้สอดคล้องกับ rotation angles แปดค่าใน Gate เหล่านั้นใน ansatz ที่รับ rotation angles เปลี่ยนแปลงได้

ยินดีด้วย! คุณได้รัน VQE calculation บน IBM Quantum QPU แล้ว!

ในบทเรียนถัดไป เราจะดูวิธีปรับ workstream นี้เพื่อรวมตัวแปรใน Hamiltonian ของคุณ ในบริบทของปัญหาเคมีควอนตัม อาจหมายถึงการปรับ geometry เพื่อกำหนดรูปร่างของโมเลกุลหรือบริเวณการจับ

import qiskit
import qiskit_ibm_runtime

print(qiskit.version.get_version_info())
print(qiskit_ibm_runtime.version.get_version_info())
2.1.0
0.40.1
Source: IBM Quantum docs — updated 27 เม.ย. 2569
English version on doQumentation — updated 7 พ.ค. 2569
This translation based on the English version of approx. 26 มี.ค. 2569