Metode de compilare pentru circuite de simulare Hamiltoniană
Utilizare estimată QPU: nu s-a efectuat nicio execuție în acest tutorial, deoarece acesta este axat pe procesul de transpilare.
Context
Compilarea circuitelor cuantice este un pas esențial în fluxul de lucru al calculului cuantic. Aceasta implică transformarea unui algoritm cuantic de nivel înalt într-un circuit cuantic fizic care respectă constrângerile hardware-ului cuantic țintă. O compilare eficientă poate influența semnificativ performanța algoritmilor cuantici prin reducerea adâncimii circuitului, a numărului de porți și a timpului de execuție. Acest tutorial explorează trei abordări distincte pentru compilarea circuitelor cuantice în Qiskit, prezentând punctele forte și aplicațiile acestora prin exemple practice.
Scopul acestui tutorial este de a-i învăța pe utilizatori cum să aplice și să evalueze trei metode de compilare în Qiskit: transpilerul SABRE, transpilerul bazat pe inteligență artificială și pluginul Rustiq. Utilizatorii vor învăța cum să folosească fiecare metodă în mod eficient și cum să evalueze performanța acestora pe diferite circuite cuantice. La finalul tutorialului, vei fi capabil să alegi și să adaptezi strategii de compilare în funcție de obiective specifice de optimizare, cum ar fi reducerea adâncimii circuitului, minimizarea numărului de porți sau îmbunătățirea timpului de execuție.
Ce vei învăța
- Cum să folosești transpilerul Qiskit cu SABRE pentru optimizarea layout-ului și rutării.
- Cum să valorifici transpilerul AI pentru optimizarea avansată și automată a circuitelor.
- Cum să utilizezi pluginul Rustiq pentru circuite care necesită sinteza precisă a operațiilor, în special în sarcinile de simulare Hamiltoniană.
Acest tutorial folosește trei circuite exemplu urmând fluxul de lucru Qiskit patterns pentru a ilustra performanța fiecărei metode de compilare. La finalul tutorialului, vei fi echipat să alegi strategia de compilare potrivită în funcție de cerințele și constrângerile specifice.
Prezentare generală a metodelor de compilare
1. Transpilerul Qiskit cu SABRE
Transpilerul Qiskit folosește algoritmul SABRE (SWAP-based BidiREctional heuristic search) pentru a optimiza layout-ul și rutarea circuitelor. SABRE se concentrează pe minimizarea porților SWAP și a impactului lor asupra adâncimii circuitului, respectând în același timp constrângerile de conectivitate ale hardware-ului. Această metodă este foarte versatilă și potrivită pentru optimizarea circuitelor de uz general, oferind un echilibru între performanță și timpul de calcul. Pentru a profita de cele mai recente îmbunătățiri aduse SABRE, detaliate în [1], poți crește numărul de încercări (de exemplu, layout_trials=400, swap_trials=400). În scopul acestui tutorial, vom folosi valorile implicite pentru numărul de încercări, pentru a putea compara cu transpilerul implicit al Qiskit. Avantajele și explorarea parametrilor SABRE sunt abordate într-un tutorial dedicat.
2. Transpilerul AI
Transpilerul bazat pe inteligență artificială din Qiskit folosește machine learning pentru a prezice strategii optime de transpilare, analizând tipare în structura circuitelor și constrângerile hardware-ului, pentru a selecta cea mai bună secvență de optimizări pentru o intrare dată. Această metodă este deosebit de eficientă pentru circuite cuantice la scară largă, oferind un grad ridicat de automatizare și adaptabilitate la diverse tipuri de probleme. Pe lângă optimizarea generală a circuitelor, transpilerul AI poate fi utilizat cu pasul AIPauliNetworkSynthesis, care vizează circuitele de tip Pauli network — blocuri formate din porți H, S, SX, CX, RX, RY și RZ — și aplică o abordare de sinteză bazată pe reinforcement learning. Pentru mai multe informații despre transpilerul AI și strategiile sale de sinteză, consultă [2] și [3].
3. Pluginul Rustiq
Pluginul Rustiq introduce tehnici avansate de sinteză specifice pentru operațiile PauliEvolutionGate, care reprezintă rotații Pauli utilizate frecvent în dinamica Trotterizată. Acest plugin este valoros pentru circuitele care implementează simularea Hamiltoniană, cum ar fi cele folosite în chimia cuantică și problemele de fizică, unde rotațiile Pauli precise sunt esențiale pentru simularea eficientă a Hamiltonienelor problemei. Rustiq oferă o sinteză a circuitelor de mică adâncime, precisă, pentru aceste operații specializate. Pentru mai multe detalii despre implementarea și performanța Rustiq, consultă [4].
Prin explorarea aprofundată a acestor metode de compilare, tutorialul oferă utilizatorilor instrumentele necesare pentru a îmbunătăți performanța circuitelor lor cuantice, deschizând calea spre calcule cuantice mai eficiente și practice.
Cerințe
Înainte de a începe acest tutorial, asigură-te că ai instalate următoarele:
- Qiskit SDK v1.3 sau mai recent, cu suport pentru vizualizare
- Qiskit Runtime v0.28 sau mai recent (
pip install qiskit-ibm-runtime) - Qiskit IBM Transpiler (
pip install qiskit-ibm-transpiler) - Modul local al transpilerului AI Qiskit (
pip install qiskit_ibm_ai_local_transpiler) - Biblioteca de grafuri Networkx (
pip install networkx)
Configurare
# 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
Partea 1: Circuit Efficient SU2
Pasul 1: Maparea intrărilor clasice la o problemă cuantică
În această secțiune, explorăm circuitul efficient_su2, un ansatz eficient din punct de vedere hardware, utilizat frecvent în algoritmii cuantici variaționali (cum ar fi VQE) și în sarcinile de machine learning cuantic. Circuitul constă din straturi alternante de rotații pe un singur qubit și porți de entanglement aranjate într-un tipar circular, conceput pentru a explora eficient spațiul stărilor cuantice, menținând în același timp o adâncime gestionabilă.
Vom începe prin construirea unui circuit efficient_su2 pentru a demonstra cum se pot compara diferitele metode de compilare. După Partea 1, vom extinde analiza la un set mai mare de circuite, permițând un benchmark cuprinzător pentru evaluarea performanței diferitelor tehnici de compilare.
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")
Pasul 2: Optimizarea problemei pentru execuția pe hardware cuantic
Acest pas reprezintă focusul principal al tutorialului. Aici urmărim să optimizăm circuitele cuantice pentru execuția eficientă pe hardware cuantic real. Obiectivul nostru principal este reducerea adâncimii circuitului și a numărului de porți, factori cheie pentru îmbunătățirea fidelității execuției și atenuarea zgomotului hardware-ului.
- Transpilerul SABRE: Utilizează transpilerul implicit al Qiskit cu algoritmul de layout și rutare SABRE.
- Transpilerul AI (mod local): Transpilerul standard bazat pe AI, folosind inferența locală și strategia implicită de sinteză.
- Pluginul Rustiq: Un plugin de transpilare conceput pentru compilare de mică adâncime, adaptat sarcinilor de simulare Hamiltoniană.
Scopul acestui pas este de a compara rezultatele acestor metode în termeni de adâncime a circuitului transpilat și număr de porți. Un alt indicator important pe care îl luăm în considerare este timpul de rulare al transpilării. Prin analizarea acestor indicatori, putem evalua punctele forte relative ale fiecărei metode și determina care produce cel mai eficient circuit pentru execuția pe hardware-ul selectat.
Notă: Pentru exemplul inițial cu circuitul SU2, vom compara doar transpilerul SABRE cu transpilerul AI implicit. Totuși, în benchmark-ul ulterior cu circuite Hamlib, vom compara toate cele trei metode de transpilare.
# 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')>
Transpilerul Qiskit cu SABRE:
pm_sabre = generate_preset_pass_manager(
optimization_level=3, backend=backend, seed_transpiler=seed
)
Transpilerul 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
)
Pluginul 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,
)
Transpilare și capturarea indicatorilor
Pentru a compara performanța metodelor de compilare, definim o funcție care transpilează circuitul de intrare și captează indicatori relevanți într-un mod consistent. Aceasta include adâncimea totală a circuitului, numărul total de porți și timpul de transpilare.
Pe lângă acești indicatori standard, înregistrăm și adâncimea porților cu 2 qubiți, un indicator deosebit de important pentru evaluarea execuției pe hardware cuantic. Spre deosebire de adâncimea totală, care include toate porțile, adâncimea cu 2 qubiți reflectă mai precis durata reală de execuție a circuitului pe hardware. Aceasta deoarece porțile cu 2 qubiți domină de obicei bugetul de timp și erori în majoritatea dispozitivelor cuantice. Astfel, minimizarea adâncimii cu 2 qubiți este esențială pentru îmbunătățirea fidelității și reducerea efectelor de decoerență în timpul execuției.
Vom folosi această funcție pentru a analiza performanța diferitelor metode de compilare pe multiple circuite.
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.
Afișarea rezultatelor transpilate pentru unul dintre circuite.
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

AI transpilation

Tabel cu rezultate:
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
Graficul rezultatelor
Deoarece definim o funcție pentru a captura indicatorii în mod consistent, vom defini și una pentru reprezentarea grafică a acestora. Aici vom reprezenta adâncimea cu 2 qubiți, numărul de porți și timpul de rulare pentru fiecare metodă de compilare, pe toate circuitele.
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"
)

Analiza rezultatelor compilării circuitului SU2
În acest experiment, comparăm două metode de transpilare — transpilerul SABRE al Qiskit și transpilerul bazat pe AI — pe un set de circuite efficient_su2. Deoarece aceste circuite nu includ operații PauliEvolutionGate, pluginul Rustiq nu este inclus în această comparație.
În medie, transpilerul AI obține rezultate mai bune în ceea ce privește adâncimea circuitului, cu o îmbunătățire de peste 10% pe întreaga gamă de circuite SU2. Pentru numărul de porți (dimensiunea circuitului) și timpul de rulare al transpilării, ambele metode produc rezultate similare în ansamblu.
Totuși, examinând punctele de date individuale se relevă o perspectivă mai profundă:
- Pentru majoritatea dimensiunilor de qubiți, atât SABRE cât și AI produc rezultate aproape identice, sugerând că în multe cazuri ambele metode converg spre soluții la fel de eficiente.
- Pentru anumite dimensiuni de circuit, mai exact la 30, 50, 70 și 90 de qubiți, transpilerul AI găsește circuite semnificativ mai puțin adânci decât SABRE. Aceasta indică faptul că abordarea bazată pe învățare automată a AI este capabilă să descopere layout-uri sau căi de rutare mai optime în cazurile în care euristica SABRE nu reușește.
Acest comportament evidențiază o concluzie importantă:
Deși SABRE și AI produc adesea rezultate comparabile, transpilerul AI poate descoperi ocazional soluții mult mai bune, în special în termeni de adâncime, ceea ce poate duce la o performanță semnificativ îmbunătățită pe hardware.
Part 2: Hamiltonian simulation circuit
Pasul 1: Investigarea circuitelor cu PauliEvolutionGate
În această secțiune, investigăm circuitele cuantice construite cu PauliEvolutionGate, care permite simularea eficientă a Hamiltonienilor. Vom analiza cum diferite metode de compilare optimizează aceste circuite pentru diverși Hamiltonieni.
Hamiltonieni folosiți în benchmark
Hamiltonenii folosiți în acest benchmark descriu interacțiuni pereche între qubiți, incluzând termeni precum , și . Acești Hamiltonieni sunt frecvent utilizați în chimia cuantică, fizica materiei condensate și știința materialelor, unde modelează sisteme de particule în interacțiune.
Ca referință, utilizatorii pot explora un set mai larg de Hamiltonieni în această lucrare: Efficient Hamiltonian Simulation on Noisy Quantum Devices.
Sursa benchmark-ului: Hamlib și Benchpress
Circuitele folosite în acest benchmark provin din depozitul benchmark Hamlib, care conține sarcini de lucru realiste pentru simularea Hamiltonienilor.
Aceleași circuite au fost anterior evaluate folosind Benchpress, un cadru open-source pentru evaluarea performanței transpilării cuantice. Prin utilizarea acestui set standardizat de circuite, putem compara direct eficacitatea diferitelor strategii de compilare pe probleme de simulare reprezentative.
Simularea Hamiltoniană este o sarcină fundamentală în calculul cuantic, cu aplicații în simulări moleculare, probleme de optimizare și fizica cuantică a multor corpuri. Înțelegerea modului în care diferitele metode de compilare optimizează aceste circuite poate ajuta utilizatorii să îmbunătățească execuția practică a unor astfel de circuite pe dispozitive cuantice din generația actuală.
# 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
Pasul 2: Optimizarea problemei pentru execuție pe hardware cuantic
Ca și în exemplul anterior, vom folosi același Backend pentru a asigura consistența comparațiilor. Deoarece managerii de pași (pm_sabre, pm_ai și pm_rustiq) au fost deja inițializați, putem trece direct la transpilarea circuitelor Hamiltoniene folosind fiecare metodă.
Acest pas se concentrează exclusiv pe realizarea transpilării și înregistrarea metricilor de circuit rezultante, inclusiv adâncimea, numărul de porți și timpul de transpilare. Analizând aceste rezultate, ne propunem să determinăm eficiența fiecărei metode de transpilare pentru acest tip de circuit. Transpilare și capturare metrici:
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 de rezultate (vizualizarea este omisă deoarece circuitele de ieșire sunt foarte mari):
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]
Vizualizarea performanței în funcție de indexul circuitului:
plot_transpilation_metrics(
results_ham, "Transpilation Metrics for Hamiltonian Circuits"
)

Vizualizarea procentului de circuite pentru care fiecare metodă a obținut cel mai bun rezultat.
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)
Best-performing methods based on size:
sabre: 18 circuit(s)
rustiq: 14 circuit(s)
ai: 10 circuit(s)
Analiza rezultatelor compilării circuitelor Hamiltoniene
În această secțiune, evaluăm performanța a trei metode de transpilare — SABRE, transpilerul cu AI și Rustiq — pe circuite cuantice construite cu PauliEvolutionGate, utilizate frecvent în sarcini de simulare Hamiltoniană.
Rustiq a obținut cea mai bună performanță medie în ceea ce privește adâncimea circuitului**, atingând o adâncime cu aproximativ 20% mai mică decât SABRE. Acest lucru era de așteptat, deoarece Rustiq este conceput special pentru sinteza operațiunilor PauliEvolutionGate cu strategii de descompunere optimizate la adâncime redusă. Mai mult, graficul de adâncime arată că, pe măsură ce circuitele cresc în dimensiune și complexitate, Rustiq scalează cel mai eficient, menținând o adâncime semnificativ mai mică decât atât AI, cât și SABRE pe circuitele mai mari.
Transpilerul AI a demonstrat o performanță solidă și consistentă pentru adâncimea circuitului, depășind în mod constant SABRE pe majoritatea circuitelor. Cu toate acestea, a înregistrat cel mai mare timp de execuție, în special pe circuitele mai mari, ceea ce îi poate limita utilitatea practică în fluxuri de lucru sensibile la timp. Scalabilitatea sa în ceea ce privește timpul de execuție rămâne o limitare cheie, chiar dacă oferă îmbunătățiri solide ale adâncimii.
SABRE, deși produce cea mai mare adâncime medie, a obținut cel mai mic număr mediu de porți, urmat îndeaproape de transpilerul AI. Aceasta este în concordanță cu designul euristicii SABRE, care prioritizează direct minimizarea numărului de porți. Rustiq, în ciuda punctului său forte în reducerea adâncimii, a avut cel mai mare număr mediu de porți, un compromis important de luat în considerare în aplicațiile unde dimensiunea circuitului contează mai mult decât durata acestuia.
Sumar
Deși transpilerul AI oferă în general rezultate mai bune decât SABRE, în special în ceea ce privește adâncimea circuitului, concluzia nu ar trebui să fie pur și simplu „folosește întotdeauna transpilerul AI." Există nuanțe importante de luat în considerare:
-
Transpilerul AI este de obicei fiabil și produce circuite optimizate pentru adâncime, dar vine cu compromisuri în privința timpului de execuție și are și alte limitări, inclusiv hărțile de cuplare suportate și capacitățile de sinteză. Acestea sunt detaliate în documentația Qiskit Transpiler Service.
-
În unele cazuri, în special cu circuite foarte mari sau specifice hardware-ului, transpilerul AI poate să nu fie la fel de eficient. În aceste situații, transpilerul SABRE implicit rămâne extrem de fiabil și poate fi optimizat suplimentar prin ajustarea parametrilor săi (vezi tutorialul de optimizare SABRE).
-
Este, de asemenea, important să iei în considerare structura circuitului atunci când alegi o metodă. De exemplu,
rustiqeste construit special pentru circuitele care implicăPauliEvolutionGateși oferă adesea cea mai bună performanță pentru problemele de simulare Hamiltoniană.
Recomandare:
Nu există o strategie de transpilare universală. Utilizatorii sunt încurajați să înțeleagă structura circuitului lor și să testeze mai multe metode de transpilare — inclusiv AI, SABRE și instrumente specializate precum Rustiq — pentru a găsi soluția cea mai eficientă pentru problema și constrângerile hardware specifice.
Pasul 3: Execuție folosind primitivele Qiskit
Deoarece acest tutorial se concentrează pe transpilare, nu se execută experimente pe un dispozitiv cuantic. Scopul este de a valorifica optimizările din Pasul 2 pentru a obține un circuit transpilat cu adâncime și număr de porți reduse.
Pasul 4: Post-procesare și returnarea rezultatelor în formatul clasic dorit
Deoarece nu există execuție pentru acest notebook, nu există rezultate de post-procesat.
Referințe
[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