Lewati ke konten utama

Metode kompilasi untuk sirkuit simulasi Hamiltonian

Estimasi penggunaan QPU: tidak ada eksekusi yang dilakukan dalam tutorial ini karena fokusnya pada proses transpilasi.

Latar belakang​

Kompilasi sirkuit kuantum adalah langkah krusial dalam alur kerja komputasi kuantum. Proses ini melibatkan transformasi algoritma kuantum tingkat tinggi menjadi sirkuit kuantum fisik yang memenuhi batasan perangkat keras kuantum target. Kompilasi yang efektif dapat berdampak signifikan pada kinerja algoritma kuantum dengan mengurangi kedalaman sirkuit, jumlah gate, dan waktu eksekusi. Tutorial ini mengeksplorasi tiga pendekatan berbeda untuk kompilasi sirkuit kuantum di Qiskit, menampilkan kekuatan dan aplikasinya melalui contoh-contoh praktis.

Tujuan tutorial ini adalah mengajarkan pengguna cara menerapkan dan mengevaluasi tiga metode kompilasi di Qiskit: Transpiler SABRE, Transpiler bertenaga AI, dan plugin Rustiq. Pengguna akan belajar cara menggunakan setiap metode secara efektif dan cara membandingkan kinerjanya di berbagai sirkuit kuantum. Di akhir tutorial ini, pengguna akan dapat memilih dan menyesuaikan strategi kompilasi berdasarkan tujuan optimasi tertentu seperti mengurangi kedalaman sirkuit, meminimalkan jumlah gate, atau meningkatkan waktu eksekusi.

Yang akan kamu pelajari​

  • Cara menggunakan Transpiler Qiskit dengan SABRE untuk optimasi layout dan routing.
  • Cara memanfaatkan Transpiler AI untuk optimasi sirkuit otomatis tingkat lanjut.
  • Cara menggunakan plugin Rustiq untuk sirkuit yang memerlukan sintesis operasi yang presisi, terutama dalam tugas simulasi Hamiltonian.

Tutorial ini menggunakan tiga contoh sirkuit mengikuti alur kerja Qiskit patterns untuk mengilustrasikan kinerja setiap metode kompilasi. Di akhir tutorial ini, pengguna akan siap memilih strategi kompilasi yang tepat berdasarkan kebutuhan dan batasan spesifik mereka.

Gambaran umum metode kompilasi​

1. Transpiler Qiskit dengan SABRE​

Transpiler Qiskit menggunakan algoritma SABRE (SWAP-based BidiREctional heuristic search) untuk mengoptimalkan layout dan routing sirkuit. SABRE berfokus pada minimalisasi gate SWAP dan dampaknya pada kedalaman sirkuit sambil mematuhi batasan konektivitas perangkat keras. Metode ini sangat serbaguna dan cocok untuk optimasi sirkuit serba guna, memberikan keseimbangan antara kinerja dan waktu komputasi. Untuk memanfaatkan peningkatan terbaru di SABRE, yang dirinci dalam [1], kamu bisa meningkatkan jumlah percobaan (misalnya, layout_trials=400, swap_trials=400). Untuk tujuan tutorial ini, kita akan menggunakan nilai default untuk jumlah percobaan agar bisa dibandingkan dengan Transpiler default Qiskit. Keunggulan dan eksplorasi parameter SABRE dibahas dalam tutorial mendalam terpisah.

2. Transpiler AI​

Transpiler bertenaga AI di Qiskit menggunakan machine learning untuk memprediksi strategi transpilasi optimal dengan menganalisis pola dalam struktur sirkuit dan batasan perangkat keras guna memilih urutan optimasi terbaik untuk input yang diberikan. Metode ini sangat efektif untuk sirkuit kuantum skala besar, menawarkan tingkat otomasi dan adaptabilitas yang tinggi terhadap berbagai jenis masalah. Selain optimasi sirkuit umum, Transpiler AI dapat digunakan dengan pass AIPauliNetworkSynthesis, yang menargetkan sirkuit jaringan Pauli β€” blok yang terdiri dari gate H, S, SX, CX, RX, RY, dan RZ β€” dan menerapkan pendekatan sintesis berbasis reinforcement learning. Untuk informasi lebih lanjut tentang Transpiler AI dan strategi sintesisnya, lihat [2] dan [3].

3. Plugin Rustiq​

Plugin Rustiq memperkenalkan teknik sintesis canggih khusus untuk operasi PauliEvolutionGate, yang merepresentasikan rotasi Pauli yang umum digunakan dalam dinamika Trotterisasi. Plugin ini berguna untuk sirkuit yang mengimplementasikan simulasi Hamiltonian, seperti yang digunakan dalam masalah kimia kuantum dan fisika, di mana rotasi Pauli yang akurat sangat penting untuk menyimulasikan Hamiltonian masalah secara efektif. Rustiq menawarkan sintesis sirkuit berkedalaman rendah yang presisi untuk operasi-operasi khusus ini. Untuk detail lebih lanjut tentang implementasi dan kinerja Rustiq, silakan lihat [4].

Dengan mengeksplorasi metode kompilasi ini secara mendalam, tutorial ini memberikan pengguna alat untuk meningkatkan kinerja sirkuit kuantum mereka, membuka jalan bagi komputasi kuantum yang lebih efisien dan praktis.

Persyaratan​

Sebelum memulai tutorial ini, pastikan kamu sudah menginstal yang berikut:

  • Qiskit SDK v1.3 atau lebih baru, dengan dukungan visualisasi
  • Qiskit Runtime v0.28 atau lebih baru (pip install qiskit-ibm-runtime)
  • Qiskit IBM Transpiler (pip install qiskit-ibm-transpiler)
  • Mode lokal Transpiler AI Qiskit (pip install qiskit_ibm_ai_local_transpiler)
  • Library graf Networkx (pip install networkx)

Pengaturan​

# Added by doQumentation β€” required packages for this notebook
!pip install -q IPython matplotlib numpy pandas qiskit qiskit-ibm-runtime qiskit-ibm-transpiler requests
from qiskit.circuit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.circuit.library import (
efficient_su2,
PauliEvolutionGate,
)
from qiskit_ibm_transpiler import generate_ai_pass_manager
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig
from collections import Counter
from IPython.display import display
import time
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import json
import requests
import logging

# Suppress noisy loggers
logging.getLogger(
"qiskit_ibm_transpiler.wrappers.ai_local_synthesis"
).setLevel(logging.ERROR)

seed = 42 # Seed for reproducibility

Bagian 1: Sirkuit Efficient SU2​

Langkah 1: Petakan input klasik ke masalah kuantum​

Di bagian ini, kita mengeksplorasi sirkuit efficient_su2, sebuah ansatz yang efisien secara perangkat keras yang umum digunakan dalam algoritma kuantum variasional (seperti VQE) dan tugas machine learning kuantum. Sirkuit ini terdiri dari lapisan bergantian berupa rotasi qubit tunggal dan gate entanglement yang disusun dalam pola melingkar, dirancang untuk mengeksplorasi ruang keadaan kuantum secara efektif sambil menjaga kedalaman yang dapat dikelola.

Kita akan mulai dengan membangun satu sirkuit efficient_su2 untuk menunjukkan cara membandingkan metode kompilasi yang berbeda. Setelah Bagian 1, kita akan memperluas analisis ke sekumpulan sirkuit yang lebih besar, memungkinkan benchmark komprehensif untuk mengevaluasi kinerja berbagai teknik kompilasi.

qubit_size = list(range(10, 101, 10))
qc_su2_list = [
efficient_su2(n, entanglement="circular", reps=1)
.decompose()
.copy(name=f"SU2_{n}")
for n in qubit_size
]

# Draw the first circuit
qc_su2_list[0].draw(output="mpl")

Output of the previous code cell

Langkah 2: Optimasi masalah untuk eksekusi perangkat keras kuantum​

Langkah ini adalah fokus utama tutorial. Di sini, kita bertujuan mengoptimalkan sirkuit kuantum untuk eksekusi yang efisien pada perangkat keras kuantum nyata. Tujuan utama kita adalah mengurangi kedalaman sirkuit dan jumlah gate, yang merupakan faktor kunci dalam meningkatkan fidelitas eksekusi dan mengurangi noise perangkat keras.

  • Transpiler SABRE: Menggunakan Transpiler default Qiskit dengan algoritma layout dan routing SABRE.
  • Transpiler AI (mode lokal): Transpiler bertenaga AI standar menggunakan inferensi lokal dan strategi sintesis default.
  • Plugin Rustiq: Plugin Transpiler yang dirancang untuk kompilasi berkedalaman rendah yang disesuaikan untuk tugas simulasi Hamiltonian.

Tujuan langkah ini adalah membandingkan hasil metode-metode tersebut dalam hal kedalaman sirkuit yang ditranspilasi dan jumlah gate. Metrik penting lainnya yang kita pertimbangkan adalah waktu eksekusi transpilasi. Dengan menganalisis metrik-metrik ini, kita dapat mengevaluasi kekuatan relatif setiap metode dan menentukan mana yang menghasilkan sirkuit paling efisien untuk eksekusi pada perangkat keras yang dipilih.

Catatan: Untuk contoh sirkuit SU2 awal, kita hanya akan membandingkan Transpiler SABRE dengan Transpiler AI default. Namun, pada benchmark berikutnya menggunakan sirkuit Hamlib, kita akan membandingkan ketiga metode transpilasi.

# QiskitRuntimeService.save_account(channel="ibm_quantum_platform", token="<YOUR-API-KEY>", overwrite=True, set_as_default=True)
service = QiskitRuntimeService(channel="ibm_quantum_platform")
backend = service.backend("ibm_torino")
print(f"Using backend: {backend}")
qiskit_runtime_service._get_crn_from_instance_name:WARNING:2025-07-30 21:46:30,843: Multiple instances found. Using all matching instances.
Using backend: <IBMBackend('ibm_torino')>

Transpiler Qiskit dengan SABRE:

pm_sabre = generate_preset_pass_manager(
optimization_level=3, backend=backend, seed_transpiler=seed
)

Transpiler AI:

# Standard AI transpiler pass manager, using the local mode
pm_ai = generate_ai_pass_manager(
backend=backend, optimization_level=3, ai_optimization_level=3
)

Plugin Rustiq:

hls_config = HLSConfig(
PauliEvolution=[
(
"rustiq",
{
"nshuffles": 400,
"upto_phase": True,
"fix_clifford": True,
"preserve_order": False,
"metric": "depth",
},
)
]
)
pm_rustiq = generate_preset_pass_manager(
optimization_level=3,
backend=backend,
hls_config=hls_config,
seed_transpiler=seed,
)

Transpilasi dan tangkap metrik​

Untuk membandingkan kinerja metode kompilasi, kita mendefinisikan sebuah fungsi yang mentranspilasi sirkuit input dan menangkap metrik relevan secara konsisten. Ini mencakup kedalaman sirkuit total, jumlah gate keseluruhan, dan waktu transpilasi.

Selain metrik standar ini, kita juga merekam kedalaman gate 2-Qubit, yang merupakan metrik yang sangat penting untuk mengevaluasi eksekusi pada perangkat keras kuantum. Berbeda dengan kedalaman total yang mencakup semua gate, kedalaman 2-Qubit lebih akurat mencerminkan durasi eksekusi aktual sirkuit pada perangkat keras. Ini karena gate 2-Qubit biasanya mendominasi anggaran waktu dan error pada sebagian besar perangkat kuantum. Oleh karena itu, meminimalkan kedalaman 2-Qubit sangat penting untuk meningkatkan fidelitas dan mengurangi efek dekoheren selama eksekusi.

Kita akan menggunakan fungsi ini untuk menganalisis kinerja metode kompilasi yang berbeda di beberapa sirkuit.

def capture_transpilation_metrics(
results, pass_manager, circuits, method_name
):
"""
Capture transpilation metrics for a list of circuits and stores the results in a DataFrame.

Args:
results (pd.DataFrame): DataFrame to store the results.
pass_manager: Pass manager used for transpilation.
circuits (list): List of quantum circuits to transpile.
method_name (str): Name of the transpilation method.

Returns:
list: List of transpiled circuits.
"""
transpiled_circuits = []

for i, qc in enumerate(circuits):
# Transpile the circuit
start_time = time.time()
transpiled_qc = pass_manager.run(qc)
end_time = time.time()

# Needed for AI transpiler to be consistent with other methods
transpiled_qc = transpiled_qc.decompose(gates_to_decompose=["swap"])

# Collect metrics
transpilation_time = end_time - start_time
circuit_depth = transpiled_qc.depth(
lambda x: x.operation.num_qubits == 2
)
circuit_size = transpiled_qc.size()

# Append results to DataFrame
results.loc[len(results)] = {
"method": method_name,
"qc_name": qc.name,
"qc_index": i,
"num_qubits": qc.num_qubits,
"ops": transpiled_qc.count_ops(),
"depth": circuit_depth,
"size": circuit_size,
"runtime": transpilation_time,
}
transpiled_circuits.append(transpiled_qc)
print(
f"Transpiled circuit index {i} ({qc.name}) in {transpilation_time:.2f} seconds with method {method_name}, "
f"depth {circuit_depth}, and size {circuit_size}."
)

return transpiled_circuits
results_su2 = pd.DataFrame(
columns=[
"method",
"qc_name",
"qc_index",
"num_qubits",
"ops",
"depth",
"size",
"runtime",
]
)

tqc_sabre = capture_transpilation_metrics(
results_su2, pm_sabre, qc_su2_list, "sabre"
)
tqc_ai = capture_transpilation_metrics(results_su2, pm_ai, qc_su2_list, "ai")
Transpiled circuit index 0 (SU2_10) in 0.06 seconds with method sabre, depth 13, and size 167.
Transpiled circuit index 1 (SU2_20) in 0.24 seconds with method sabre, depth 20, and size 299.
Transpiled circuit index 2 (SU2_30) in 10.72 seconds with method sabre, depth 72, and size 627.
Transpiled circuit index 3 (SU2_40) in 16.16 seconds with method sabre, depth 40, and size 599.
Transpiled circuit index 4 (SU2_50) in 76.89 seconds with method sabre, depth 77, and size 855.
Transpiled circuit index 5 (SU2_60) in 86.12 seconds with method sabre, depth 60, and size 899.
Transpiled circuit index 6 (SU2_70) in 94.46 seconds with method sabre, depth 79, and size 1085.
Transpiled circuit index 7 (SU2_80) in 69.05 seconds with method sabre, depth 80, and size 1199.
Transpiled circuit index 8 (SU2_90) in 88.25 seconds with method sabre, depth 105, and size 1420.
Transpiled circuit index 9 (SU2_100) in 83.80 seconds with method sabre, depth 100, and size 1499.
Transpiled circuit index 0 (SU2_10) in 0.17 seconds with method ai, depth 10, and size 168.
Transpiled circuit index 1 (SU2_20) in 0.29 seconds with method ai, depth 20, and size 299.
Transpiled circuit index 2 (SU2_30) in 13.56 seconds with method ai, depth 36, and size 548.
Transpiled circuit index 3 (SU2_40) in 15.95 seconds with method ai, depth 40, and size 599.
Transpiled circuit index 4 (SU2_50) in 80.70 seconds with method ai, depth 54, and size 823.
Transpiled circuit index 5 (SU2_60) in 75.99 seconds with method ai, depth 60, and size 899.
Transpiled circuit index 6 (SU2_70) in 64.96 seconds with method ai, depth 74, and size 1087.
Transpiled circuit index 7 (SU2_80) in 68.25 seconds with method ai, depth 80, and size 1199.
Transpiled circuit index 8 (SU2_90) in 75.07 seconds with method ai, depth 90, and size 1404.
Transpiled circuit index 9 (SU2_100) in 63.97 seconds with method ai, depth 100, and size 1499.

Tampilkan hasil transpilasi dari salah satu sirkuit.

print("Sabre transpilation")
display(tqc_sabre[0].draw("mpl", fold=-1, idle_wires=False))
print("AI transpilation")
display(tqc_ai[0].draw("mpl", fold=-1, idle_wires=False))
Sabre transpilation

Output of the previous code cell

AI transpilation

Output of the previous code cell

Tabel hasil:

summary_su2 = (
results_su2.groupby("method")[["depth", "size", "runtime"]]
.mean()
.round(2)
)
print(summary_su2)

results_su2
depth   size  runtime
method
ai 56.4 852.5 45.89
sabre 64.6 864.9 52.57
method  qc_name  qc_index  num_qubits                                ops  \
0 sabre SU2_10 0 10 {'rz': 81, 'sx': 70, 'cz': 16}
1 sabre SU2_20 1 20 {'rz': 160, 'sx': 119, 'cz': 20}
2 sabre SU2_30 2 30 {'sx': 295, 'rz': 242, 'cz': 90}
3 sabre SU2_40 3 40 {'rz': 320, 'sx': 239, 'cz': 40}
4 sabre SU2_50 4 50 {'rz': 402, 'sx': 367, 'cz': 86}
5 sabre SU2_60 5 60 {'rz': 480, 'sx': 359, 'cz': 60}
6 sabre SU2_70 6 70 {'rz': 562, 'sx': 441, 'cz': 82}
7 sabre SU2_80 7 80 {'rz': 640, 'sx': 479, 'cz': 80}
8 sabre SU2_90 8 90 {'rz': 721, 'sx': 585, 'cz': 114}
9 sabre SU2_100 9 100 {'rz': 800, 'sx': 599, 'cz': 100}
10 ai SU2_10 0 10 {'rz': 81, 'sx': 71, 'cz': 16}
11 ai SU2_20 1 20 {'rz': 160, 'sx': 119, 'cz': 20}
12 ai SU2_30 2 30 {'sx': 243, 'rz': 242, 'cz': 63}
13 ai SU2_40 3 40 {'rz': 320, 'sx': 239, 'cz': 40}
14 ai SU2_50 4 50 {'rz': 403, 'sx': 346, 'cz': 74}
15 ai SU2_60 5 60 {'rz': 480, 'sx': 359, 'cz': 60}
16 ai SU2_70 6 70 {'rz': 563, 'sx': 442, 'cz': 82}
17 ai SU2_80 7 80 {'rz': 640, 'sx': 479, 'cz': 80}
18 ai SU2_90 8 90 {'rz': 721, 'sx': 575, 'cz': 108}
19 ai SU2_100 9 100 {'rz': 800, 'sx': 599, 'cz': 100}

depth size runtime
0 13 167 0.058845
1 20 299 0.238217
2 72 627 10.723922
3 40 599 16.159262
4 77 855 76.886604
5 60 899 86.118255
6 79 1085 94.458287
7 80 1199 69.048184
8 105 1420 88.254809
9 100 1499 83.795482
10 10 168 0.171532
11 20 299 0.291691
12 36 548 13.555931
13 40 599 15.952733
14 54 823 80.702141
15 60 899 75.993404
16 74 1087 64.960162
17 80 1199 68.253280
18 90 1404 75.072412
19 100 1499 63.967446

Grafik hasil​

Karena kita mendefinisikan fungsi untuk menangkap metrik secara konsisten, kita juga akan mendefinisikan satu lagi untuk membuat grafik metrik tersebut. Di sini, kita akan memplot kedalaman 2-Qubit, jumlah gate, dan waktu eksekusi untuk setiap metode kompilasi di seluruh sirkuit.

def plot_transpilation_metrics(results, overall_title, x_axis="qc_index"):
"""
Plots transpilation metrics (depth, size, runtime) for different transpilation methods.

Parameters:
results (DataFrame): Data containing columns ['num_qubits', 'method', 'depth', 'size', 'runtime']
overall_title (str): The title of the overall figure.
x_axis (str): The x-axis label, either 'num_qubits' or 'qc_index'.
"""

fig, axs = plt.subplots(1, 3, figsize=(24, 6))
metrics = ["depth", "size", "runtime"]
titles = ["Circuit Depth", "Circuit Size", "Transpilation Runtime"]
y_labels = ["Depth", "Size (Gate Count)", "Runtime (s)"]

methods = results["method"].unique()
colors = plt.colormaps["tab10"]
markers = ["o", "^", "s", "D", "P", "*", "X", "v"]
color_list = [colors(i % colors.N) for i in range(len(methods))]
color_map = {method: color_list[i] for i, method in enumerate(methods)}
marker_map = {
method: markers[i % len(markers)] for i, method in enumerate(methods)
}
jitter_factor = 0.1 # Small x-axis jitter for visibility
handles, labels = [], [] # Unique handles for legend

# Plot each metric
for i, metric in enumerate(metrics):
for method in methods:
method_data = results[results["method"] == method]

# Introduce slight jitter to avoid exact overlap
jitter = np.random.uniform(
-jitter_factor, jitter_factor, len(method_data)
)

scatter = axs[i].scatter(
method_data[x_axis] + jitter,
method_data[metric],
color=color_map[method],
label=method,
marker=marker_map[method],
alpha=0.7,
edgecolors="black",
s=80,
)

if method not in labels:
handles.append(scatter)
labels.append(method)

axs[i].set_title(titles[i])
axs[i].set_xlabel(x_axis)
axs[i].set_ylabel(y_labels[i])
axs[i].grid(axis="y", linestyle="--", alpha=0.7)
axs[i].tick_params(axis="x", rotation=45)
axs[i].set_xticks(sorted(results[x_axis].unique()))

fig.suptitle(overall_title, fontsize=16)
fig.legend(
handles=handles,
labels=labels,
loc="upper right",
bbox_to_anchor=(1.05, 1),
)

plt.tight_layout()
plt.show()
plot_transpilation_metrics(
results_su2, "Transpilation Metrics for SU2 Circuits", x_axis="num_qubits"
)

Output of the previous code cell

Analisis hasil kompilasi sirkuit SU2​

Dalam eksperimen ini, kita membandingkan dua metode transpilasi β€” Transpiler SABRE Qiskit dan Transpiler bertenaga AI β€” pada sekumpulan sirkuit efficient_su2. Karena sirkuit-sirkuit ini tidak menyertakan operasi PauliEvolutionGate apa pun, plugin Rustiq tidak diikutsertakan dalam perbandingan ini.

Rata-rata, Transpiler AI berkinerja lebih baik dalam hal kedalaman sirkuit, dengan peningkatan lebih dari 10% di seluruh rentang sirkuit SU2. Untuk jumlah gate (ukuran sirkuit) dan waktu eksekusi transpilasi, kedua metode menghasilkan hasil yang serupa secara keseluruhan.

Namun, memeriksa titik data individual mengungkapkan wawasan yang lebih dalam:

  • Untuk sebagian besar ukuran Qubit, SABRE dan AI menghasilkan hasil yang hampir identik, menunjukkan bahwa dalam banyak kasus, kedua metode berkumpul pada solusi yang sama efisiennya.
  • Untuk ukuran sirkuit tertentu, khususnya pada 30, 50, 70, dan 90 Qubit, Transpiler AI menemukan sirkuit yang jauh lebih dangkal dibanding SABRE. Ini menunjukkan bahwa pendekatan berbasis pembelajaran AI mampu menemukan layout atau jalur routing yang lebih optimal dalam kasus di mana heuristik SABRE tidak berhasil.

Perilaku ini menyoroti kesimpulan penting:

Meskipun SABRE dan AI sering menghasilkan hasil yang sebanding, Transpiler AI kadang-kadang dapat menemukan solusi yang jauh lebih baik, terutama dalam hal kedalaman, yang dapat menghasilkan peningkatan kinerja yang signifikan pada perangkat keras.

Bagian 2: Circuit simulasi Hamiltonian​

Langkah 1: Pelajari circuit dengan PauliEvolutionGate​

Di bagian ini, kita akan mempelajari circuit kuantum yang dibangun menggunakan PauliEvolutionGate, yang memungkinkan simulasi Hamiltonian secara efisien. Kita akan menganalisis bagaimana berbagai metode kompilasi mengoptimalkan circuit-circuit ini pada berbagai Hamiltonian.

Hamiltonian yang digunakan dalam benchmark​

Hamiltonian yang digunakan dalam benchmark ini mendeskripsikan interaksi berpasangan antara qubit, termasuk suku-suku seperti ZZZZ, XXXX, dan YYYY. Hamiltonian ini umum digunakan dalam kimia kuantum, fisika materi terkondensasi, dan ilmu material, di mana mereka memodelkan sistem partikel yang berinteraksi.

Sebagai referensi, pengguna dapat menjelajahi sekumpulan Hamiltonian yang lebih luas dalam paper ini: Efficient Hamiltonian Simulation on Noisy Quantum Devices.

Sumber benchmark: Hamlib dan Benchpress​

Circuit yang digunakan dalam benchmark ini diambil dari repositori benchmark Hamlib, yang berisi workload simulasi Hamiltonian yang realistis.

Circuit yang sama sebelumnya telah di-benchmark menggunakan Benchpress, sebuah framework open-source untuk mengevaluasi performa transpilasi kuantum. Dengan menggunakan kumpulan circuit yang terstandarisasi ini, kita dapat langsung membandingkan efektivitas berbagai strategi kompilasi pada masalah simulasi yang representatif.

Simulasi Hamiltonian adalah tugas fundamental dalam komputasi kuantum, dengan aplikasi dalam simulasi molekuler, masalah optimasi, dan fisika many-body kuantum. Memahami bagaimana berbagai metode kompilasi mengoptimalkan circuit-circuit ini dapat membantu pengguna meningkatkan eksekusi praktis circuit semacam itu pada perangkat kuantum near-term.

# Obtain the Hamiltonian JSON from the benchpress repository
url = "https://raw.githubusercontent.com/Qiskit/benchpress/e7b29ef7be4cc0d70237b8fdc03edbd698908eff/benchpress/hamiltonian/hamlib/100_representative.json"
response = requests.get(url)
response.raise_for_status() # Raise an error if download failed
ham_records = json.loads(response.text)
# Remove circuits that are too large for the backend
ham_records = [
h for h in ham_records if h["ham_qubits"] <= backend.num_qubits
]
# Remove the circuits that are large to save transpilation time
ham_records = sorted(ham_records, key=lambda x: x["ham_terms"])[:35]

qc_ham_list = []
for h in ham_records:
terms = h["ham_hamlib_hamiltonian_terms"]
coeff = h["ham_hamlib_hamiltonian_coefficients"]
num_qubits = h["ham_qubits"]
name = h["ham_problem"]

evo_gate = PauliEvolutionGate(SparsePauliOp(terms, coeff))

qc_ham = QuantumCircuit(num_qubits)
qc_ham.name = name

qc_ham.append(evo_gate, range(num_qubits))
qc_ham_list.append(qc_ham)
print(f"Number of Hamiltonian circuits: {len(qc_ham_list)}")

# Draw the first Hamiltonian circuit
qc_ham_list[0].draw("mpl", fold=-1)
Number of Hamiltonian circuits: 35

Output of the previous code cell

Langkah 2: Optimalkan masalah untuk eksekusi pada hardware kuantum​

Seperti pada contoh sebelumnya, kita akan menggunakan Backend yang sama untuk memastikan konsistensi dalam perbandingan. Karena pass manager (pm_sabre, pm_ai, dan pm_rustiq) sudah diinisialisasi, kita bisa langsung melanjutkan dengan mentranspilasi circuit Hamiltonian menggunakan setiap metode.

Langkah ini berfokus hanya pada melakukan transpilasi dan mencatat metrik circuit yang dihasilkan, termasuk depth, jumlah gate, dan waktu transpilasi. Dengan menganalisis hasilnya, kita bertujuan menentukan efisiensi setiap metode transpilasi untuk jenis circuit ini. Transpilasi dan catat metrik:

results_ham = pd.DataFrame(
columns=[
"method",
"qc_name",
"qc_index",
"num_qubits",
"ops",
"depth",
"size",
"runtime",
]
)

tqc_sabre = capture_transpilation_metrics(
results_ham, pm_sabre, qc_ham_list, "sabre"
)
tqc_ai = capture_transpilation_metrics(results_ham, pm_ai, qc_ham_list, "ai")
tqc_rustiq = capture_transpilation_metrics(
results_ham, pm_rustiq, qc_ham_list, "rustiq"
)
Transpiled circuit index 0 (all-vib-o3) in 0.02 seconds with method sabre, depth 6, and size 58.
Transpiled circuit index 1 (all-vib-c2h) in 1.10 seconds with method sabre, depth 2, and size 39.
Transpiled circuit index 2 (all-vib-bh) in 0.01 seconds with method sabre, depth 3, and size 30.
Transpiled circuit index 3 (all-vib-c2h) in 0.03 seconds with method sabre, depth 18, and size 115.
Transpiled circuit index 4 (graph-gnp_k-2) in 0.02 seconds with method sabre, depth 24, and size 129.
Transpiled circuit index 5 (all-vib-fccf) in 0.05 seconds with method sabre, depth 14, and size 134.
Transpiled circuit index 6 (all-vib-hno) in 8.39 seconds with method sabre, depth 6, and size 174.
Transpiled circuit index 7 (all-vib-bhf2) in 3.92 seconds with method sabre, depth 22, and size 220.
Transpiled circuit index 8 (LiH) in 0.03 seconds with method sabre, depth 67, and size 290.
Transpiled circuit index 9 (uf20-ham) in 0.04 seconds with method sabre, depth 50, and size 340.
Transpiled circuit index 10 (all-vib-fccf) in 0.62 seconds with method sabre, depth 30, and size 286.
Transpiled circuit index 11 (all-vib-fccf) in 0.04 seconds with method sabre, depth 67, and size 339.
Transpiled circuit index 12 (all-vib-ch2) in 0.04 seconds with method sabre, depth 87, and size 421.
Transpiled circuit index 13 (tfim) in 0.05 seconds with method sabre, depth 36, and size 222.
Transpiled circuit index 14 (all-vib-cyclo_propene) in 9.51 seconds with method sabre, depth 22, and size 345.
Transpiled circuit index 15 (graph-gnp_k-4) in 0.05 seconds with method sabre, depth 128, and size 704.
Transpiled circuit index 16 (all-vib-hc3h2cn) in 13.83 seconds with method sabre, depth 2, and size 242.
Transpiled circuit index 17 (TSP_Ncity-4) in 0.05 seconds with method sabre, depth 106, and size 609.
Transpiled circuit index 18 (tfim) in 0.29 seconds with method sabre, depth 73, and size 399.
Transpiled circuit index 19 (all-vib-h2co) in 21.97 seconds with method sabre, depth 30, and size 572.
Transpiled circuit index 20 (Be2) in 0.09 seconds with method sabre, depth 324, and size 1555.
Transpiled circuit index 21 (graph-complete_bipart) in 0.12 seconds with method sabre, depth 250, and size 1394.
Transpiled circuit index 22 (all-vib-f2) in 0.07 seconds with method sabre, depth 215, and size 1027.
Transpiled circuit index 23 (all-vib-cyclo_propene) in 41.22 seconds with method sabre, depth 30, and size 1144.
Transpiled circuit index 24 (TSP_Ncity-5) in 1.89 seconds with method sabre, depth 175, and size 1933.
Transpiled circuit index 25 (H2) in 0.32 seconds with method sabre, depth 1237, and size 5502.
Transpiled circuit index 26 (uuf100-ham) in 0.20 seconds with method sabre, depth 385, and size 4303.
Transpiled circuit index 27 (ham-graph-gnp_k-5) in 0.20 seconds with method sabre, depth 311, and size 3654.
Transpiled circuit index 28 (tfim) in 0.15 seconds with method sabre, depth 276, and size 3213.
Transpiled circuit index 29 (uuf100-ham) in 0.21 seconds with method sabre, depth 520, and size 5250.
Transpiled circuit index 30 (flat100-ham) in 0.15 seconds with method sabre, depth 131, and size 3157.
Transpiled circuit index 31 (uf100-ham) in 0.24 seconds with method sabre, depth 624, and size 7378.
Transpiled circuit index 32 (OH) in 0.88 seconds with method sabre, depth 2175, and size 9808.
Transpiled circuit index 33 (HF) in 0.66 seconds with method sabre, depth 2206, and size 9417.
Transpiled circuit index 34 (BH) in 0.89 seconds with method sabre, depth 2177, and size 9802.
Transpiled circuit index 0 (all-vib-o3) in 0.02 seconds with method ai, depth 6, and size 58.
Transpiled circuit index 1 (all-vib-c2h) in 1.11 seconds with method ai, depth 2, and size 39.
Transpiled circuit index 2 (all-vib-bh) in 0.01 seconds with method ai, depth 3, and size 30.
Transpiled circuit index 3 (all-vib-c2h) in 0.11 seconds with method ai, depth 18, and size 94.
Transpiled circuit index 4 (graph-gnp_k-2) in 0.11 seconds with method ai, depth 22, and size 129.
Transpiled circuit index 5 (all-vib-fccf) in 0.06 seconds with method ai, depth 22, and size 177.
Transpiled circuit index 6 (all-vib-hno) in 8.62 seconds with method ai, depth 10, and size 198.
Transpiled circuit index 7 (all-vib-bhf2) in 3.71 seconds with method ai, depth 18, and size 195.
Transpiled circuit index 8 (LiH) in 0.19 seconds with method ai, depth 62, and size 267.
Transpiled circuit index 9 (uf20-ham) in 0.22 seconds with method ai, depth 47, and size 321.
Transpiled circuit index 10 (all-vib-fccf) in 0.71 seconds with method ai, depth 38, and size 369.
Transpiled circuit index 11 (all-vib-fccf) in 0.24 seconds with method ai, depth 65, and size 315.
Transpiled circuit index 12 (all-vib-ch2) in 0.24 seconds with method ai, depth 91, and size 430.
Transpiled circuit index 13 (tfim) in 0.15 seconds with method ai, depth 12, and size 251.
Transpiled circuit index 14 (all-vib-cyclo_propene) in 8.50 seconds with method ai, depth 18, and size 311.
Transpiled circuit index 15 (graph-gnp_k-4) in 0.25 seconds with method ai, depth 117, and size 659.
Transpiled circuit index 16 (all-vib-hc3h2cn) in 16.11 seconds with method ai, depth 2, and size 242.
Transpiled circuit index 17 (TSP_Ncity-4) in 0.39 seconds with method ai, depth 98, and size 564.
Transpiled circuit index 18 (tfim) in 0.38 seconds with method ai, depth 23, and size 437.
Transpiled circuit index 19 (all-vib-h2co) in 24.97 seconds with method ai, depth 38, and size 707.
Transpiled circuit index 20 (Be2) in 1.07 seconds with method ai, depth 293, and size 1392.
Transpiled circuit index 21 (graph-complete_bipart) in 0.61 seconds with method ai, depth 229, and size 1437.
Transpiled circuit index 22 (all-vib-f2) in 0.57 seconds with method ai, depth 178, and size 964.
Transpiled circuit index 23 (all-vib-cyclo_propene) in 50.89 seconds with method ai, depth 34, and size 1425.
Transpiled circuit index 24 (TSP_Ncity-5) in 1.61 seconds with method ai, depth 171, and size 2020.
Transpiled circuit index 25 (H2) in 6.39 seconds with method ai, depth 1148, and size 5208.
Transpiled circuit index 26 (uuf100-ham) in 3.97 seconds with method ai, depth 376, and size 5048.
Transpiled circuit index 27 (ham-graph-gnp_k-5) in 3.54 seconds with method ai, depth 357, and size 4451.
Transpiled circuit index 28 (tfim) in 1.72 seconds with method ai, depth 216, and size 3026.
Transpiled circuit index 29 (uuf100-ham) in 4.45 seconds with method ai, depth 426, and size 5399.
Transpiled circuit index 30 (flat100-ham) in 7.02 seconds with method ai, depth 86, and size 3108.
Transpiled circuit index 31 (uf100-ham) in 12.85 seconds with method ai, depth 623, and size 8354.
Transpiled circuit index 32 (OH) in 15.19 seconds with method ai, depth 2084, and size 9543.
Transpiled circuit index 33 (HF) in 17.51 seconds with method ai, depth 2063, and size 9446.
Transpiled circuit index 34 (BH) in 15.33 seconds with method ai, depth 2094, and size 9730.
Transpiled circuit index 0 (all-vib-o3) in 0.02 seconds with method rustiq, depth 13, and size 83.
Transpiled circuit index 1 (all-vib-c2h) in 1.11 seconds with method rustiq, depth 2, and size 39.
Transpiled circuit index 2 (all-vib-bh) in 0.01 seconds with method rustiq, depth 3, and size 30.
Transpiled circuit index 3 (all-vib-c2h) in 0.01 seconds with method rustiq, depth 13, and size 79.
Transpiled circuit index 4 (graph-gnp_k-2) in 0.02 seconds with method rustiq, depth 31, and size 131.
Transpiled circuit index 5 (all-vib-fccf) in 0.04 seconds with method rustiq, depth 50, and size 306.
Transpiled circuit index 6 (all-vib-hno) in 14.03 seconds with method rustiq, depth 22, and size 276.
Transpiled circuit index 7 (all-vib-bhf2) in 3.15 seconds with method rustiq, depth 13, and size 155.
Transpiled circuit index 8 (LiH) in 0.03 seconds with method rustiq, depth 54, and size 270.
Transpiled circuit index 9 (uf20-ham) in 0.04 seconds with method rustiq, depth 65, and size 398.
Transpiled circuit index 10 (all-vib-fccf) in 0.16 seconds with method rustiq, depth 41, and size 516.
Transpiled circuit index 11 (all-vib-fccf) in 0.02 seconds with method rustiq, depth 34, and size 189.
Transpiled circuit index 12 (all-vib-ch2) in 0.03 seconds with method rustiq, depth 49, and size 240.
Transpiled circuit index 13 (tfim) in 0.05 seconds with method rustiq, depth 20, and size 366.
Transpiled circuit index 14 (all-vib-cyclo_propene) in 9.08 seconds with method rustiq, depth 16, and size 277.
Transpiled circuit index 15 (graph-gnp_k-4) in 0.04 seconds with method rustiq, depth 116, and size 612.
Transpiled circuit index 16 (all-vib-hc3h2cn) in 13.89 seconds with method rustiq, depth 2, and size 257.
Transpiled circuit index 17 (TSP_Ncity-4) in 0.05 seconds with method rustiq, depth 133, and size 737.
Transpiled circuit index 18 (tfim) in 0.11 seconds with method rustiq, depth 25, and size 680.
Transpiled circuit index 19 (all-vib-h2co) in 27.19 seconds with method rustiq, depth 66, and size 983.
Transpiled circuit index 20 (Be2) in 0.07 seconds with method rustiq, depth 215, and size 1030.
Transpiled circuit index 21 (graph-complete_bipart) in 0.14 seconds with method rustiq, depth 328, and size 1918.
Transpiled circuit index 22 (all-vib-f2) in 0.05 seconds with method rustiq, depth 114, and size 692.
Transpiled circuit index 23 (all-vib-cyclo_propene) in 62.25 seconds with method rustiq, depth 74, and size 2348.
Transpiled circuit index 24 (TSP_Ncity-5) in 0.20 seconds with method rustiq, depth 436, and size 3605.
Transpiled circuit index 25 (H2) in 0.21 seconds with method rustiq, depth 643, and size 3476.
Transpiled circuit index 26 (uuf100-ham) in 0.24 seconds with method rustiq, depth 678, and size 6120.
Transpiled circuit index 27 (ham-graph-gnp_k-5) in 0.22 seconds with method rustiq, depth 588, and size 5241.
Transpiled circuit index 28 (tfim) in 0.34 seconds with method rustiq, depth 340, and size 5901.
Transpiled circuit index 29 (uuf100-ham) in 0.33 seconds with method rustiq, depth 881, and size 7667.
Transpiled circuit index 30 (flat100-ham) in 0.31 seconds with method rustiq, depth 279, and size 4910.
Transpiled circuit index 31 (uf100-ham) in 0.38 seconds with method rustiq, depth 1138, and size 10607.
Transpiled circuit index 32 (OH) in 0.38 seconds with method rustiq, depth 1148, and size 6512.
Transpiled circuit index 33 (HF) in 0.37 seconds with method rustiq, depth 1090, and size 6256.
Transpiled circuit index 34 (BH) in 0.37 seconds with method rustiq, depth 1148, and size 6501.

Tabel hasil (visualisasi dilewati karena circuit output sangat besar):

summary_ham = (
results_ham.groupby("method")[["depth", "size", "runtime"]]
.mean()
.round(2)
)
print(summary_ham)

results_ham
depth     size  runtime
method
ai 316.86 2181.26 5.97
rustiq 281.94 2268.80 3.86
sabre 337.97 2120.14 3.07
method        qc_name  qc_index  num_qubits  \
0 sabre all-vib-o3 0 4
1 sabre all-vib-c2h 1 4
2 sabre all-vib-bh 2 2
3 sabre all-vib-c2h 3 3
4 sabre graph-gnp_k-2 4 4
.. ... ... ... ...
100 rustiq flat100-ham 30 90
101 rustiq uf100-ham 31 46
102 rustiq OH 32 10
103 rustiq HF 33 10
104 rustiq BH 34 10

ops depth size runtime
0 {'rz': 28, 'sx': 24, 'cz': 6} 6 58 0.016597
1 {'rz': 17, 'sx': 16, 'cz': 4, 'x': 2} 2 39 1.102089
2 {'sx': 14, 'rz': 13, 'cz': 3} 3 30 0.011042
3 {'sx': 46, 'rz': 45, 'cz': 18, 'x': 6} 18 115 0.025816
4 {'sx': 49, 'rz': 47, 'cz': 24, 'x': 9} 24 129 0.023077
.. ... ... ... ...
100 {'sx': 2709, 'cz': 1379, 'rz': 817, 'x': 5} 279 4910 0.309448
101 {'sx': 6180, 'cz': 3120, 'rz': 1303, 'x': 4} 1138 10607 0.380977
102 {'sx': 3330, 'cz': 1704, 'rz': 1455, 'x': 23} 1148 6512 0.383564
103 {'sx': 3213, 'cz': 1620, 'rz': 1406, 'x': 17} 1090 6256 0.368578
104 {'sx': 3331, 'cz': 1704, 'rz': 1447, 'x': 19} 1148 6501 0.374822

[105 rows x 8 columns]

Visualisasi performa berdasarkan indeks circuit:

plot_transpilation_metrics(
results_ham, "Transpilation Metrics for Hamiltonian Circuits"
)

Output of the previous code cell

Visualisasi persentase circuit di mana setiap metode tampil terbaik.

def analyze_and_plot_best_methods(results, metric):
"""
Analyze the best-performing methods for a given metric and plot a pie chart.

Parameters:
results (DataFrame): The input DataFrame containing method performance data.
metric (str): The metric to evaluate ("depth" or "size").
"""
method_counts = Counter()
for qc_idx, group in results.groupby("qc_index"):
min_value = group[metric].min()

# Find all methods that achieved this minimum value
best_methods = group[group[metric] == min_value]["method"]
# Update counts for all best methods (handling ties)
method_counts.update(best_methods)
best_method_counts = dict(
sorted(method_counts.items(), key=lambda x: x[1], reverse=True)
)

# Print summary
print(f"Best-performing methods based on {metric}:")
for method, count in best_method_counts.items():
print(f" {method}: {count} circuit(s)")

# Plot pie chart
num_methods = len(best_method_counts)
colors = plt.cm.viridis_r(range(0, 256, 256 // num_methods))
plt.figure(figsize=(5, 5))
plt.pie(
best_method_counts.values(),
labels=best_method_counts.keys(),
autopct="%1.1f%%",
startangle=140,
wedgeprops={"edgecolor": "black"},
textprops={"fontsize": 10},
colors=colors,
)
plt.title(
f"Percentage of Circuits Method Performed Best for {metric.capitalize()}",
fontsize=12,
fontweight="bold",
)
plt.show()

analyze_and_plot_best_methods(results_ham, "depth")
analyze_and_plot_best_methods(results_ham, "size")
Best-performing methods based on depth:
ai: 16 circuit(s)
rustiq: 16 circuit(s)
sabre: 10 circuit(s)

Output of the previous code cell

Best-performing methods based on size:
sabre: 18 circuit(s)
rustiq: 14 circuit(s)
ai: 10 circuit(s)

Output of the previous code cell

Analisis hasil kompilasi circuit Hamiltonian​

Di bagian ini, kita mengevaluasi performa tiga metode transpilasi β€” SABRE, Transpiler bertenaga AI, dan Rustiq β€” pada circuit kuantum yang dibangun dengan PauliEvolutionGate, yang umum digunakan dalam tugas simulasi Hamiltonian.

Rustiq tampil terbaik secara rata-rata dalam hal kedalaman circuit (depth)**, mencapai depth sekitar 20% lebih rendah dibandingkan SABRE. Hal ini sesuai ekspektasi, karena Rustiq memang dirancang khusus untuk mensintesis operasi PauliEvolutionGate dengan strategi dekomposisi yang dioptimalkan dan berkedalaman rendah. Selain itu, plot depth menunjukkan bahwa seiring circuit bertambah besar dan kompleks, Rustiq paling efektif dalam scaling, mempertahankan depth yang jauh lebih rendah dari AI maupun SABRE pada circuit yang lebih besar.

Transpiler AI menunjukkan performa yang kuat dan konsisten untuk kedalaman circuit, secara konsisten mengungguli SABRE di sebagian besar circuit. Namun, ia memiliki waktu eksekusi tertinggi, terutama pada circuit yang lebih besar, yang dapat membatasi kepraktisannya dalam workload yang sensitif terhadap waktu. Skalabilitas runtime-nya tetap menjadi keterbatasan utama, meski ia menawarkan peningkatan depth yang solid.

SABRE, meski menghasilkan rata-rata depth tertinggi, mencapai rata-rata jumlah gate terendah, diikuti ketat oleh Transpiler AI. Ini selaras dengan desain heuristik SABRE yang memprioritaskan minimisasi jumlah gate secara langsung. Rustiq, meski kuat dalam menurunkan depth, memiliki rata-rata jumlah gate tertinggi, yang merupakan trade-off penting untuk diperhatikan dalam aplikasi di mana ukuran circuit lebih penting daripada durasi circuit.

Ringkasan​

Meskipun Transpiler AI umumnya memberikan hasil yang lebih baik dari SABRE, terutama dalam hal kedalaman circuit, kesimpulannya bukan sekadar "selalu gunakan Transpiler AI." Ada nuansa penting yang perlu dipertimbangkan:

  • Transpiler AI biasanya andal dan menghasilkan circuit yang dioptimalkan secara depth, namun ada trade-off dalam runtime, dan juga memiliki keterbatasan lain, termasuk coupling map yang didukung dan kemampuan sintesis. Detail selengkapnya ada di dokumentasi Qiskit Transpiler Service.

  • Dalam beberapa kasus, terutama dengan circuit yang sangat besar atau spesifik terhadap hardware, Transpiler AI mungkin tidak seefektif itu. Dalam kasus ini, Transpiler SABRE default tetap sangat andal dan bisa dioptimalkan lebih lanjut dengan menyesuaikan parameternya (lihat tutorial optimasi SABRE).

  • Penting juga untuk mempertimbangkan struktur circuit saat memilih metode. Misalnya, rustiq dirancang khusus untuk circuit yang melibatkan PauliEvolutionGate dan sering menghasilkan performa terbaik untuk masalah simulasi Hamiltonian.

Rekomendasi:

Tidak ada strategi transpilasi yang cocok untuk semua kasus. Pengguna dianjurkan untuk memahami struktur circuit mereka dan mencoba beberapa metode transpilasi β€” termasuk AI, SABRE, dan alat khusus seperti Rustiq β€” untuk menemukan solusi paling efisien bagi masalah dan kendala hardware spesifik mereka.

Langkah 3: Eksekusi menggunakan Qiskit primitives​

Karena tutorial ini berfokus pada transpilasi, tidak ada eksperimen yang dieksekusi pada perangkat kuantum. Tujuannya adalah memanfaatkan optimasi dari Langkah 2 untuk mendapatkan circuit yang sudah ditranspilasi dengan depth dan jumlah gate yang lebih kecil.

Langkah 4: Pasca-proses dan kembalikan hasil dalam format klasik yang diinginkan​

Karena tidak ada eksekusi pada notebook ini, tidak ada hasil yang perlu diproses.

Referensi​

[1] "LightSABRE: A Lightweight and Enhanced SABRE Algorithm". H. Zou, M. Treinish, K. Hartman, A. Ivrii, J. Lishman et al. https://arxiv.org/abs/2409.08368

[2] "Practical and efficient quantum circuit synthesis and transpiling with Reinforcement Learning". D. Kremer, V. Villar, H. Paik, I. Duran, I. Faro, J. Cruz-Benito et al. https://arxiv.org/abs/2405.13196

[3] "Pauli Network Circuit Synthesis with Reinforcement Learning". A. Dubal, D. Kremer, S. Martiel, V. Villar, D. Wang, J. Cruz-Benito et al. https://arxiv.org/abs/2503.14448

[4] "Faster and shorter synthesis of Hamiltonian simulation circuits". T. Goubault de Brugière, S. Martiel et al. https://arxiv.org/abs/2404.03280

Source: IBM Quantum docs β€” updated 27 Jan 2026
English version on doQumentation β€” updated 7 Mei 2026
This translation based on the English version of 9 Apr 2026