Lewati ke konten utama

Estimasi energi ground-state rantai Heisenberg dengan VQE

Perkiraan penggunaan: 37 menit pada prosesor Heron (CATATAN: Ini hanya perkiraan. Waktu eksekusi aktualmu bisa berbeda.)

Hasil belajar

Setelah menyelesaikan tutorial ini, kamu diharapkan dapat memahami informasi berikut:

  • Cara memodelkan rantai spin Heisenberg sebagai Hamiltonian kuantum menggunakan Qiskit
  • Cara menggunakan optimizer SPSA untuk mengestimasi energi ground-state suatu sistem kuantum
  • Cara mengeksekusi alur kerja variasional pada hardware kuantum IBM® menggunakan primitif dan sesi Qiskit Runtime

Prasyarat

Disarankan untuk terlebih dahulu mengenal topik-topik berikut:

Latar Belakang

Rantai spin Heisenberg adalah salah satu model yang paling banyak dipelajari dalam fisika materi terkondensasi dan kemagnetan kuantum. Model ini menggambarkan kisi satu dimensi dari spin kuantum yang saling berinteraksi, di mana spin-spin yang berdekatan saling terhubung melalui interaksi pertukaran. Hamiltonian untuk model Heisenberg isotropik dengan medan magnet eksternal diberikan oleh:

H=i,j(JxXiXj+JyYiYj+JzZiZj)+ihiZi,H = \sum_{\langle i,j \rangle} \left( J_x X_i X_j + J_y Y_i Y_j + J_z Z_i Z_j \right) + \sum_{i} h_i Z_i,

di mana XiX_i, YiY_i, dan ZiZ_i adalah operator Pauli yang bekerja pada situs ii, jumlah i,j\langle i,j \rangle berjalan atas pasangan tetangga terdekat, Jx=Jy=Jz=0.5J_x = J_y = J_z = 0.5 adalah konstanta kopling pertukaran (isotropik dalam tutorial ini), dan hih_i mewakili medan magnet eksternal yang bergantung pada situs. Dalam tutorial ini, nilai medan magnet diambil secara acak dari interval [1,1][-1, 1]. Perlu diperhatikan bahwa dalam implementasi di bawah ini, himpunan pasangan "tetangga terdekat" ditentukan oleh kopling native backend hardware di antara NN qubit pertama, yang mungkin tidak membentuk rantai linear yang ketat tergantung pada topologi perangkat.

Memahami energi ground-state dari Hamiltonian ini sangat penting dalam fisika. State dasar mengkodekan informasi tentang transisi fase kuantum, struktur keterikatan (entanglement), dan pemesanan magnetik. Secara klasik, menghitung energi ground-state yang tepat menjadi sulit dilakukan seiring bertambahnya jumlah spin, karena dimensi ruang Hilbert bertumbuh secara eksponensial sebagai 2N2^N untuk NN spin. Hal ini menjadikannya kandidat alami untuk simulasi kuantum.

Variational Quantum Eigensolver (VQE) adalah algoritma hibrida kuantum-klasik yang dirancang untuk mengestimasi energi ground-state dari suatu Hamiltonian. Algoritma ini bekerja dengan menyiapkan state kuantum berparameter ψ(θ)|\psi(\theta)\rangle (disebut ansatz) pada komputer kuantum dan mengukur nilai ekspektasi ψ(θ)Hψ(θ)\langle \psi(\theta) | H | \psi(\theta) \rangle. Optimizer klasik kemudian secara iteratif menyesuaikan parameter θ\theta untuk meminimalkan energi ini, memanfaatkan prinsip variasional yang menjamin bahwa energi yang terukur selalu merupakan batas atas dari energi ground-state yang sebenarnya.

Dalam tutorial ini, kita menggunakan ansatz efficient_su2 dari library sirkuit Qiskit, yang membangun lapisan-lapisan rotasi qubit tunggal dan gerbang entangling. Optimasi dilakukan menggunakan algoritma Simultaneous Perturbation Stochastic Approximation (SPSA), yang cocok untuk hardware kuantum yang berisik karena mengestimasi gradien hanya dengan dua evaluasi fungsi per iterasi terlepas dari jumlah parameter.

Persyaratan

Sebelum memulai tutorial ini, pastikan kamu sudah menginstal hal-hal berikut:

  • Qiskit SDK v2.0 atau lebih baru, dengan dukungan visualisasi
  • Qiskit Runtime v0.44 atau lebih baru (pip install qiskit-ibm-runtime)

Setup

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

from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.primitives 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, Session, EstimatorV2

def visualize_results(results):
plt.plot(results["cost_history"], lw=2)
plt.xlabel("Number of function evaluations")
plt.ylabel("Energy")
plt.show()

Contoh skala kecil

Dalam bagian ini, kita akan membahas setiap langkah dari pola Qiskit dalam skala kecil, menjelaskan komponen-komponen kunci saat kita membangun alur kerja tersebut.

Langkah 1: Memetakan input klasik ke masalah kuantum

  • Input: Jumlah spin
  • Output: Ansatz dan Hamiltonian yang memodelkan rantai Heisenberg

Buat ansatz dan Hamiltonian yang memodelkan rantai Heisenberg 10-spin. Dalam langkah ini, kita akan membangun Hamiltonian Heisenberg 10-spin berdasarkan peta kopling backend yang paling tidak sibuk dan menyiapkan ansatz efficient_su2.

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

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

Langkah 2: Mengoptimalkan masalah untuk eksekusi hardware kuantum

  • Input: Circuit abstrak, observable
  • Output: Target Circuit dan observable, dioptimalkan untuk QPU yang dipilih

Gunakan fungsi generate_preset_pass_manager dari Qiskit untuk secara otomatis menghasilkan rutinitas optimasi untuk Circuit kita terhadap QPU yang dipilih. Kita pilih optimization_level=3, yang memberikan tingkat optimasi tertinggi dari preset pass manager. Kita juga menyertakan scheduling pass ALAPScheduleAnalysis dan PadDynamicalDecoupling untuk menekan kesalahan dekoherensi.

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

Output of the previous code cell

Langkah 3: Eksekusi menggunakan primitif Qiskit

  • Input: Target Circuit dan observable
  • Output: Hasil optimasi

Minimalkan estimasi energi ground-state sistem dengan mengoptimalkan parameter Circuit. Gunakan primitif Estimator dari Qiskit Runtime untuk mengevaluasi fungsi cost selama optimasi.

Karena kita sudah mengoptimalkan Circuit untuk backend di Langkah 2, kita bisa menghindari transpilasi di server Runtime dengan mengatur skip_transpilation=True dan melewatkan Circuit yang sudah dioptimalkan. Untuk demo ini, kita akan menjalankan pada QPU menggunakan primitif qiskit-ibm-runtime. Untuk menjalankan dengan primitif berbasis statevector qiskit, ganti blok kode yang menggunakan primitif Qiskit Runtime dengan blok yang dikomentari.

Dalam tutorial ini kita menggunakan Simultaneous Perturbation Stochastic Approximation (SPSA), yang merupakan optimizer berbasis gradien. Berikut ini kita berikan pengenalan singkat tentangnya, dan menyediakan kode untuk mengimplementasikan SPSA menggunakan Qiskit v2.0.

Memperkenalkan SPSA

Simultaneous Perturbation Stochastic Approximation (SPSA) [1] adalah algoritma optimasi yang memperkirakan seluruh vektor gradien hanya menggunakan dua pemanggilan fungsi di setiap iterasi. Misalkan f:RpRf:\mathbb{R}^p\rightarrow \mathbb{R} adalah fungsi cost dengan pp parameter yang akan dioptimalkan, dan xiRpx_i\in \mathbb{R}^p adalah vektor parameter pada langkah iterasi ke-ii. Untuk menghitung gradien, dibuat vektor acak Δi\Delta_i berukuran pp, di mana setiap elemen Δij\Delta_{ij}, \forall j{1,2,...,p}j\in \{1,2,...,p\}, diambil secara seragam dari {1,1}\{-1, 1\}. Selanjutnya, setiap elemen vektor acak Δi\Delta_i dikalikan dengan nilai kecil cic_i untuk membuat perturbasi acak. Gradien kemudian diestimasi sebagai

[f(xi)]jf(xi+ciΔi)f(xiciΔi)2ciΔij.[\nabla f(x_i)]_j \approx \frac{f(x_i + c_i \Delta_i) - f(x_i - c_i \Delta_i)}{2c_i\Delta_{ij}}.

Secara intuitif, karena perturbasi acak diterapkan selama estimasi gradien, diharapkan bahwa deviasi kecil pada nilai eksak ff yang berasal dari noise dapat ditoleransi dan diperhitungkan. Bahkan, SPSA khususnya dikenal sangat tahan terhadap noise, dan hanya memerlukan dua pemanggilan hardware untuk setiap iterasi. Oleh karena itu, ini adalah salah satu optimizer yang sangat disukai untuk mengimplementasikan algoritma variasional.

Dalam tutorial ini, hyperparameter untuk iterasi ke-ii, aia_i dan cic_i, dihitung sebagai

ai=a(A+i+1)αandci=c(i+1)γ,a_i = \frac{a}{(A + i + 1)^\alpha} \quad \text{and} \quad c_i = \frac{c}{(i+1)^\gamma},

di mana nilai konstantanya adalah A=30A = 30, α=0.9\alpha = 0.9, a=0.3a = 0.3, c=0.1c = 0.1, dan γ=0.4\gamma = 0.4. Nilai-nilai ini dipilih dari [2]. Penyetelan hyperparameter yang tepat diperlukan untuk mendapatkan performa yang baik dari SPSA.

def spsa(
fun, x0, args=(), A=30, alpha=0.9, a=0.3, c=0.1, gamma=0.4, maxiter=100
):
nparams = len(x0)
x = np.copy(x0)

for i in range(maxiter):
a_i = a / (A + i + 1) ** alpha
c_i = c / (i + 1) ** gamma
delta_i = np.random.choice([-1, 1], nparams)

# two hardware calls
eval_1 = fun(x + c_i * delta_i, *args)
eval_2 = fun(x - c_i * delta_i, *args)

# compute the gradient and update the parameters
grad = (eval_1 - eval_2) / (2 * c_i) * np.reciprocal(delta_i)
x = x - a_i * grad

return x
def cost_func(
params: Sequence,
ansatz: QuantumCircuit,
hamiltonian: SparsePauliOp,
estimator: BaseEstimatorV2,
cost_history_dict: dict,
) -> float:
"""Ground state energy evaluation."""
energy = (
estimator.run([(ansatz, hamiltonian, [params])]).result()[0].data.evs
)

cost_history_dict["iters"] += 1
cost_history_dict["prev_vector"] = list(params)
cost_history_dict["cost_history"].append(float(energy[0]))

print(
f"Fx Iters. done: {cost_history_dict['iters']} [Current cost: {round(energy[0], 5)}]",
end="\r",
)

return energy

def solve(x0, isa_ansatz, isa_observable, maxiter=150):
cost_history_dict = {
"prev_vector": None,
"iters": 0,
"cost_history": [],
"y_min": None,
}

# Evaluate the problem using a QPU via Qiskit IBM Runtime
with Session(backend=backend) as session:
estimator = EstimatorV2(mode=session)
estimator.skip_transpilation = True
estimator.options.environment.job_tags = ["TUT_HSVQE"]
x_opt = spsa(
cost_func,
x0=x0,
args=(isa_ansatz, isa_observable, estimator, cost_history_dict),
maxiter=maxiter,
)

y_min = cost_func(
x_opt, isa_ansatz, isa_observable, estimator, cost_history_dict
)

return y_min, cost_history_dict
np.random.seed(42)
num_params = ansatz.num_parameters
params = 2 * np.pi * np.random.random(num_params)

Di sini kita mengatur maxiter = 50. Perlu diperhatikan bahwa karena setiap iterasi memerlukan dua pemanggilan fungsi untuk menghitung gradien, total jumlah pemanggilan fungsi akan menjadi 2×maxiter2 \times \text{maxiter}. Nilai maxiter bisa ditingkatkan ke nilai yang lebih tinggi untuk estimasi energi yang lebih baik.

maxiter = 50
spsa_min, spsa_history = solve(
params, isa_ansatz, isa_observable, maxiter=maxiter
)
Fx Iters. done: 101 [Current cost: -3.03843]

Langkah 4: Post-process dan kembalikan hasil dalam format klasik yang diinginkan

  • Input: Estimasi energi ground-state selama optimasi
  • Output: Estimasi energi ground-state
print(f"Estimated ground state energy: {spsa_min}")
Estimated ground state energy: [-3.03842968]
results = {
"spsa": spsa_history,
}

visualize_results(spsa_history)

Output of the previous code cell

Contoh hardware skala besar

Contoh hardware skala besar tidak disertakan dalam tutorial ini. Seiring bertambahnya jumlah qubit, VQE menghadapi tantangan besar akibat fenomena barren plateau: gradien dari fungsi cost menghilang secara eksponensial seiring ukuran sistem, sehingga optimasi menjadi tidak layak secara praktis untuk sirkuit besar. Ditambah dengan noise hardware, ini berarti menskalakan VQE ke rantai spin yang lebih besar tidak menghasilkan hasil yang dapat direproduksi secara andal. Untuk pendekatan yang mengatasi keterbatasan ini, lihat bagian Langkah Berikutnya di bawah.

Tantangan

Sekarang kamu sudah memiliki implementasi VQE yang berfungsi untuk rantai Heisenberg, coba hal-hal berikut:

  1. Bereksperimen dengan kedalaman ansatz: Ubah parameter reps dalam efficient_su2 (misalnya, coba reps=1 dan reps=3). Bagaimana kedalaman ansatz memengaruhi estimasi energi ground-state dan kecepatan konvergensi? Pada titik mana kamu mulai mengamati hasil yang menurun atau ketidakstabilan?
  2. Menyetel hyperparameter SPSA: Sesuaikan parameter jadwal learning rate (a, c, alpha, gamma, A) dan amati bagaimana pengaruhnya terhadap konvergensi. Bisakah kamu menemukan konfigurasi yang konvergen lebih cepat dari nilai default yang digunakan di sini?
  3. Membandingkan topologi kopling: Alih-alih menggunakan peta kopling native backend, coba bangun rantai linear tetangga terdekat yang sederhana dan bandingkan hasilnya. Bagaimana konektivitas hardware fisik memengaruhi kedalaman sirkuit yang ditranspilasi dan estimasi energi akhir?

Referensi

[1] Spall, J. C. (2002). Implementation of the simultaneous perturbation algorithm for stochastic optimization. IEEE Transactions on Aerospace and Electronic Systems, 34(3), 817-823.

[2] Sahin, M. Emre, et al. (2025). Qiskit Machine Learning: an open-source library for quantum machine learning tasks at scale on quantum hardware and classical simulators. arXiv:2505.17756.

Langkah Berikutnya

Rekomendasi

Jika kamu menemukan pekerjaan ini menarik, kamu mungkin tertarik dengan materi berikut:

  • Coba Sample-based Quantum Diagonalization (SQD): Seperti yang ditunjukkan dalam tutorial ini, VQE menghadapi tantangan pada skala besar akibat barren plateau dan overhead pengukuran yang tinggi. IBM telah mengembangkan Sample-based Quantum Diagonalization (SQD) sebagai alternatif yang lebih skalabel. Tidak seperti VQE, SQD sepenuhnya menghindari optimasi variasional; sebaliknya, komputer kuantum menghasilkan sampel dan komputer klasik memproyeksikan Hamiltonian ke subruang yang direntang oleh sampel-sampel tersebut lalu mendiagonalisasikannya. Ini memberikan batas atas untuk energi ground-state dengan jauh lebih sedikit pengukuran dan tanpa kerentanan terhadap barren plateau. Ikuti tutorial SQD untuk melihat pendekatan ini beraksi.
  • Jelajahi kursus Quantum Diagonalization Algorithms: Perdalam pemahamanmu tentang VQE dan SQD, termasuk trade-off keduanya, dalam kursus Quantum diagonalization algorithms di IBM Quantum Learning.