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

การประมาณพลังงาน ground state ของ Heisenberg chain ด้วย VQE

ประมาณการใช้งาน: สองนาทีบนโปรเซสเซอร์ Eagle r3 (หมายเหตุ: นี่เป็นการประมาณเท่านั้น runtime ที่แท้จริงของคุณอาจแตกต่างออกไป)

พื้นหลัง

บทเรียนนี้แสดงวิธีสร้าง ติดตั้ง และรัน Qiskit pattern สำหรับการจำลอง Heisenberg chain และประมาณพลังงาน ground state สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Qiskit patterns และวิธีที่ Qiskit Serverless สามารถใช้เพื่อติดตั้งบน cloud สำหรับการรันแบบมีการจัดการ เยี่ยมชม หน้า docs บน IBM Quantum® Platform

ข้อกำหนด

ก่อนเริ่มบทเรียนนี้ ตรวจสอบให้แน่ใจว่าคุณได้ติดตั้งสิ่งต่อไปนี้:

  • Qiskit SDK v1.2 หรือใหม่กว่า พร้อมรองรับ visualization
  • Qiskit Runtime v0.28 หรือใหม่กว่า (pip install qiskit-ibm-runtime)
  • Qiskit Serverless (pip install qiskit_serverless)
  • IBM Catalog (pip install qiskit-ibm-catalog)

การตั้งค่า

# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit qiskit-ibm-catalog qiskit-ibm-runtime scipy
import numpy as np
import matplotlib.pyplot as plt

from scipy.optimize import minimize
from typing import Sequence

from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives.base import BaseEstimatorV2
from qiskit.circuit.library import XGate
from qiskit.circuit.library import efficient_su2
from qiskit.transpiler import PassManager
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.transpiler.passes.scheduling import (
ALAPScheduleAnalysis,
PadDynamicalDecoupling,
)

from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import Session, Estimator

from qiskit_ibm_catalog import QiskitServerless, QiskitFunction
def visualize_results(results):
plt.plot(results["cost_history"], lw=2)
plt.xlabel("Iteration")
plt.ylabel("Energy")
plt.show()

def build_callback(
ansatz: QuantumCircuit,
hamiltonian: SparsePauliOp,
estimator: BaseEstimatorV2,
callback_dict: dict,
):
def callback(current_vector):
# Keep track of the number of iterations
callback_dict["iters"] += 1
# Set the prev_vector to the latest one
callback_dict["prev_vector"] = current_vector
# Compute the value of the cost function at the current vector
current_cost = (
estimator.run([(ansatz, hamiltonian, [current_vector])])
.result()[0]
.data.evs[0]
)
callback_dict["cost_history"].append(current_cost)
# Print to screen on single line
print(
"Iters. done: {} [Current cost: {}]".format(
callback_dict["iters"], current_cost
),
end="\r",
flush=True,
)

return callback

ขั้นตอนที่ 1: แมปอินพุตคลาสสิกไปยังปัญหาควอนตัม

  • อินพุต: จำนวน spin
  • ผลลัพธ์: Ansatz และ Hamiltonian ที่สร้างแบบจำลอง Heisenberg chain

สร้าง ansatz และ Hamiltonian ที่สร้างแบบจำลอง Heisenberg chain ที่มี 10 spin ก่อนอื่น เรานำเข้าแพ็กเกจทั่วไปและสร้างฟังก์ชันช่วยเหลือสองสามอย่าง

num_spins = 10
ansatz = efficient_su2(num_qubits=num_spins, reps=3)

# Remember to insert your token in the QiskitRuntimeService constructor
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, min_num_qubits=num_spins, simulator=False
)

coupling = backend.target.build_coupling_map()
reduced_coupling = coupling.reduce(list(range(num_spins)))

edge_list = reduced_coupling.graph.edge_list()
ham_list = []

for edge in edge_list:
ham_list.append(("ZZ", edge, 0.5))
ham_list.append(("YY", edge, 0.5))
ham_list.append(("XX", edge, 0.5))

for qubit in reduced_coupling.physical_qubits:
ham_list.append(("Z", [qubit], np.random.random() * 2 - 1))

hamiltonian = SparsePauliOp.from_sparse_list(ham_list, num_qubits=num_spins)

ansatz.draw("mpl", style="iqp")

Output of the previous code cell

ขั้นตอนที่ 2: ปรับแต่งปัญหาสำหรับการรันบนฮาร์ดแวร์ควอนตัม

  • อินพุต: Abstract circuit, observable
  • ผลลัพธ์: Target circuit และ observable ที่ปรับแต่งสำหรับ QPU ที่เลือก

ใช้ฟังก์ชัน generate_preset_pass_manager จาก Qiskit เพื่อสร้างขั้นตอนการปรับแต่งสำหรับ Circuit ของเราโดยอัตโนมัติตาม QPU ที่เลือก เราเลือก optimization_level=3 ซึ่งให้ระดับการปรับแต่งสูงสุดของ preset pass manager นอกจากนี้เรายังเพิ่ม scheduling passes ALAPScheduleAnalysis และ PadDynamicalDecoupling เพื่อยับยั้งข้อผิดพลาด decoherence

target = backend.target
pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
pm.scheduling = PassManager(
[
ALAPScheduleAnalysis(durations=target.durations()),
PadDynamicalDecoupling(
durations=target.durations(),
dd_sequence=[XGate(), XGate()],
pulse_alignment=target.pulse_alignment,
),
]
)
ansatz_ibm = pm.run(ansatz)
observable_ibm = hamiltonian.apply_layout(ansatz_ibm.layout)
ansatz_ibm.draw("mpl", scale=0.6, style="iqp", fold=-1, idle_wires=False)

Output of the previous code cell

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

  • อินพุต: Target circuit และ observable
  • ผลลัพธ์: ผลลัพธ์ของการปรับแต่ง

ลดพลังงาน ground state โดยประมาณของระบบโดยปรับพารามิเตอร์ Circuit ใช้ Estimator primitive จาก Qiskit Runtime เพื่อประเมิน cost function ระหว่างการปรับแต่ง

สำหรับการสาธิตนี้ เราจะรันบน QPU โดยใช้ primitives จาก qiskit-ibm-runtime หากต้องการรันด้วย qiskit primitives ที่ใช้ statevector ให้แทนที่บล็อกโค้ดที่ใช้ Qiskit IBM Runtime primitives ด้วยบล็อกที่ comment ไว้

# SciPy minimizer routine
def cost_func(
params: Sequence,
ansatz: QuantumCircuit,
hamiltonian: SparsePauliOp,
estimator: BaseEstimatorV2,
) -> float:
"""Ground state energy evaluation."""
return (
estimator.run([(ansatz, hamiltonian, [params])])
.result()[0]
.data.evs[0]
)

num_params = ansatz_ibm.num_parameters
params = 2 * np.pi * np.random.random(num_params)

callback_dict = {
"prev_vector": None,
"iters": 0,
"cost_history": [],
}

# Evaluate the problem on a QPU by using Qiskit IBM Runtime
with Session(backend=backend) as session:
estimator = Estimator()
callback = build_callback(
ansatz_ibm, observable_ibm, estimator, callback_dict
)
res = minimize(
cost_func,
x0=params,
args=(ansatz_ibm, observable_ibm, estimator),
callback=callback,
method="cobyla",
options={"maxiter": 100},
)

visualize_results(callback_dict)

ขั้นตอนที่ 4: ประมวลผลและคืนผลลัพธ์ในรูปแบบคลาสสิกที่ต้องการ

  • อินพุต: การประมาณพลังงาน ground state ระหว่างการปรับแต่ง
  • ผลลัพธ์: พลังงาน ground state โดยประมาณ
print(f'Estimated ground state energy: {res["fun"]}')

ติดตั้ง Qiskit pattern บน cloud

ในการทำเช่นนี้ ย้ายซอร์สโค้ดข้างต้นไปยังไฟล์ ./source/heisenberg.py ห่อโค้ดในสคริปต์ที่รับอินพุตและคืนผลลัพธ์สุดท้าย และสุดท้ายอัปโหลดไปยัง remote cluster โดยใช้คลาส QiskitFunction จาก qiskit-ibm-catalog สำหรับคำแนะนำในการระบุ external dependencies การส่ง input arguments และอื่น ๆ ดู คู่มือ Qiskit Serverless

อินพุตของ Pattern คือจำนวน spin ในสาย ผลลัพธ์คือการประมาณพลังงาน ground state ของระบบ

# Authenticate to the remote cluster and submit the pattern for remote execution
serverless = QiskitServerless()
heisenberg_function = QiskitFunction(
title="ibm_heisenberg",
entrypoint="heisenberg.py",
working_dir="./source/",
)
serverless.upload(heisenberg_function)

รัน Qiskit pattern เป็น managed service

เมื่ออัปโหลด pattern ไปยัง cloud แล้ว เราสามารถรันได้อย่างง่ายดายโดยใช้ QiskitServerless client

# Run the pattern on the remote cluster

ibm_heisenberg = serverless.load("ibm_heisenberg")
job = serverless.run(ibm_heisenberg)
solution = job.result()

print(solution)
print(job.logs())

แบบสำรวจบทเรียน

กรุณาทำแบบสำรวจสั้น ๆ นี้เพื่อให้ข้อเสนอแนะเกี่ยวกับบทเรียนนี้ ข้อมูลเชิงลึกของคุณจะช่วยให้เราปรับปรุงเนื้อหาและประสบการณ์ผู้ใช้

ลิงก์ไปยังแบบสำรวจ

Note: This survey is provided by IBM Quantum and relates to the original English content. To give feedback on doQumentation's website, translations, or code execution, please open a GitHub issue.

Source: IBM Quantum docs — updated 2 เม.ย. 2569
English version on doQumentation — updated 7 พ.ค. 2569
This translation based on the English version of 9 เม.ย. 2569