Grundzustandsenergie-Schätzung vun der Heisenberg-Kette met VQE
Schätzung för de Nutzung: Zwei Menute op enem Eagle r3 Prozessor (ANMERKUNG: Dat es nur e Schätzung. Ding Laufzick künnt anders sinn.)
Hintergrund
Dat Tutorial zeigt, wi mr e Qiskit pattern baut, deployt un laufe lööt för de Simulation vun ener Heisenberg-Kette un för de Schätzung vun de Grundzustandsenergie. Mieh Informatione övver Qiskit patterns un wi Qiskit Serverless benutzt weed för se en de Wolke ze deploye för verwaltete Usföhrung finget ehr op unser Doku-Sigg övver IBM Quantum® Platform.
Vörussetzunge
Bevör mr met dämm Tutorial aanfange, stellt sescher, dat ihr dat Folgends installiert hätt:
- Qiskit SDK v1.2 oder neuer, met Visualisierung Ongerstö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: Klassische Eingabe op e Quanteproblem mappe
- Eingabe: Aanzahl vun Spins
- Ausgabe: Ansatz un Hamiltonian för de Modellierung vun der Heisenberg-Kette
Baut ene Ansatz un Hamiltonian, de en 10-Spin Heisenberg-Kette modelliere. Zuerst importiere mer nen paar generische Pakete un maache e paar Hilfsfunktione.
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 för Quantehardware-Usföhrung optimiere
- Eingabe: Abstrakte Schaltkreis, Observable
- Ausgabe: Target-Schaltkreis un Observable, optimiert för de usgewählte QPU
Benutzt de generate_preset_pass_manager Funktioun us Qiskit för automatisch en Optimierungsroutine för unse Schaltkreis em Bezoch op de usgewählte QPU ze generiere. Mer wähle optimization_level=3, wat de höchste Level vun Optimierung vun de Preset-Pass-Manager es. Mer inklodiere och ALAPScheduleAnalysis un PadDynamicalDecoupling Scheduling-Passes för Dekohärenzfehler ze ongerdröcke.
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: Met Qiskit Primitives usföhre
- Eingabe: Target-Schaltkreis un Observable
- Ausgabe: Ergebnisse vun der Optimierung
Minimiert de geschätzte Grundzustandsenergie vum System durch Optimierung vun de Schaltkreis-Parameter. Benutzt de Estimator Primitive us Qiskit Runtime för de Kostfunktioun während der Optimierung ze evaluiere.
För dat Demo laufe mer op enem QPU met qiskit-ibm-runtime Primitives. För met qiskit statevector-basierte Primitives ze laufe, ersetze der Block vum Code, dä Qiskit IBM Runtime Primitives benutzt, durch dä kommentierte 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: Nohbearbeitung un Ergäbnis em gewünschte klassische Format zeröckjevve
- Eingabe: Grundzustandsenergie-Schätzunge während der Optimierung
- Ausgabe: Geschätzte Grundzustandsenergie
print(f'Estimated ground state energy: {res["fun"]}')
Et Qiskit-Muster en de Wolke deploye
För dat ze maache, verschüvt dä Source-Code ovve noh ener Datei, ./source/heisenberg.py, packe der Code en e Skript, dat Eingabe entjejennemmp un de endgültige Lösung zeröckgitt, un laddet et schließlich op ene Remote-Cluster huh met der QiskitFunction Klass us qiskit-ibm-catalog. För Anleitunge övver et Spezifiziere vun externe Abhängigkeite, et Üvverjevve vun Eingabe-Argumente un mieh, luurt en de Qiskit Serverless guides.
De Eingabe för et Pattern es de Aanzahl vun Spins en der Kette. De Ausgabe es en Schätzung vun der Grundzustandsenergie vum 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)
Et Qiskit-Muster als verwaltete Service laufe lasse
Wenn mer et Pattern en de Wolke huhjelade han, künne mer et einfach met dem QiskitServerless Client laufe lasse.
# 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-Ömfrog
Bitte maacht dä kötte Ömfrog för Feedback övver dat Tutorial ze jevve. Ding Erkenntnisse hälpe uns, uns Inhaltsangebote un Benutzererfahrung ze verbessere.