Grundzustandsenergie-Schätzung vonne Heisenberg-Kette mit VQE
Schätzung for de Nutzung: Zwee Minuten uffn Eagle r3 Prozessor (ANMERGUNG: Das is bloß ne Schätzung. De Laufzeit gann anners sein.)
Hintergrund
Das Tutorial zeigt, wie mr e Qiskit pattern baud, deployt un laufen lässt for de Simulation vonne Heisenberg-Kette un for de Schätzung vonne Grundzustandsenergie. Mehr Informationen über Qiskit patterns un wie Qiskit Serverless gebruucht werd, um se inde Wolge ze deployen for verwaldete Ausführung, findet ihr uff unsrer Doku-Seite über IBM Quantum® Platform.
Voraussetzungen
Bevor mr mit dem Tutorial anfange, stellt sescher, dassde das Folgende installiert habt:
- Qiskit SDK v1.2 oder neuer, mit Visualisierung Unnerstützung
- Qiskit Runtime v0.28 oder neuer (
pip install qiskit-ibm-runtime) - Qiskit Serverless (pip install qiskit_serverless)
- IBM Catalog (pip install qiskit-ibm-catalog)
Setup
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
Schritt 1: Glassische Eingabe uffn Quantenproblem mappen
- Eingabe: Anzahl vonne Spins
- Ausgabe: Ansatz un Hamiltonian for de Modellierung vonne Heisenberg-Kette
Baud en Ansatz un Hamiltonian, de ne 10-Spin Heisenberg-Kette modellieren. Zuerst importiern mr e paar generische Pakete un machen e paar Hilfsfunktionen.
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")

Schritt 2: Problem for Quantenhardware-Ausführung optimiern
- Eingabe: Abstrakter Schaltkreis, Observable
- Ausgabe: Target-Schaltkreis un Observable, optimiert for de ausgewählde QPU
Gebruucht de generate_preset_pass_manager Funktion aus Qiskit, um automatisch ne Optimierungsroutine for unsern Schaltkreis bezüglich der ausgewählden QPU zu generieren. Mr wähln optimization_level=3, was das höchste Level vonne Optimierung vonne Preset-Pass-Manager is. Mr schließn au ALAPScheduleAnalysis un PadDynamicalDecoupling Scheduling-Passes ei, um Dekohärenzfehler zu unnerdricken.
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)

Schritt 3: Mit Qiskit Primitives ausführn
- Eingabe: Target-Schaltkreis un Observable
- Ausgabe: Ergebnisse vonne Optimierung
Minimiert de geschätzte Grundzustandsenergie vomm System durch Optimierung vonne Schaltkreis-Parameter. Gebruucht de Estimator Primitive aus Qiskit Runtime, um de Kostenfunktion während der Optimierung zu evaluiern.
For das Demo laufn mr uffn QPU mit qiskit-ibm-runtime Primitives. Um mit qiskit statevector-basierten Primitives zu laufn, ersetze den Block vomm Code, der Qiskit IBM Runtime Primitives gebruucht, durch den kommentierten Block.
# 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)
Schritt 4: Nachbearbeitung un Ergebnis imm gewünschtn glassischen Format zurückgeben
- Eingabe: Grundzustandsenergie-Schätzungen während der Optimierung
- Ausgabe: Geschätzte Grundzustandsenergie
print(f'Estimated ground state energy: {res["fun"]}')
Das Qiskit-Muster inde Wolge deployen
Um das zu machen, verschiebd den Quellcode obm zu ner Datei, ./source/heisenberg.py, pack den Code inne Skript, das Eingabe entgegenimmt un de endgültige Lösung zurückgibt, un laad das dann uffn Remote-Cluster hoch mit der QiskitFunction Klasse aus qiskit-ibm-catalog. For Anleitungen über das Spezifizieren von externen Abhängigkeiten, das Übergeben von Eingabe-Argumenten un mehr, guckt inde Qiskit Serverless guides.
De Eingabe for das Pattern is de Anzahl vonne Spins inde Kette. De Ausgabe is ne Schätzung vonne Grundzustandsenergie vomm System.
# 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)
Das Qiskit-Muster als verwaldeten Service laufen lassn
Wenn mr das Pattern inde Wolge hochgeladn hamm, könn mr das einfach mittem QiskitServerless Client laufen lassn.
# 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())
Tutorial-Umfrage
Bitte macht de kurze Umfrage, um Feedback über das Tutorial zu geben. Eire Erkenntnisse helfn uns, unsre Inhaltsangebote un Benutzererfahrung zu verbessern.