דלג לתוכן הראשי

שיטות קומפילציה למעגלים של סימולציית המילטון

שימוש משוער ב-QPU: לא בוצעה הרצה במדריך זה כיוון שהוא מתמקד בתהליך הטרנספילציה.

רקע

קומפילציה של מעגלים קוונטיים היא שלב קריטי בזרימת העבודה של מחשוב קוונטי. היא כוללת המרה של אלגוריתם קוונטי ברמה גבוהה למעגל קוונטי פיזי המתאים למגבלות החומרה הקוונטית היעד. קומפילציה אפקטיבית יכולה להשפיע משמעותית על הביצועים של אלגוריתמים קוונטיים על ידי הפחתת עומק המעגל, מספר השערים וזמן ההרצה. מדריך זה חוקר שלוש גישות שונות לקומפילציה של מעגלים קוונטיים ב-Qiskit, ומציג את החוזקות והיישומים שלהן דרך דוגמאות מעשיות.

מטרת המדריך היא ללמד משתמשים כיצד ליישם ולהעריך שלוש שיטות קומפילציה ב-Qiskit: ה-transpiler של SABRE, ה-transpiler המונע AI, והתוסף Rustiq. משתמשים ילמדו כיצד להשתמש בכל שיטה באופן אפקטיבי וכיצד לבצע בנצ'מרק על הביצועים שלהן על פני מעגלים קוונטיים שונים. בסוף המדריך, משתמשים יוכלו לבחור ולהתאים אסטרטגיות קומפילציה על בסיס מטרות אופטימיזציה ספציפיות כגון הפחתת עומק המעגל, מזעור מספר השערים או שיפור זמן הריצה.

מה תלמדו

  • כיצד להשתמש ב-transpiler של Qiskit עם SABRE לאופטימיזציה של פריסה וניתוב.
  • כיצד למנף את ה-AI transpiler לאופטימיזציה מתקדמת ואוטומטית של מעגלים.
  • כיצד להשתמש בתוסף Rustiq עבור מעגלים הדורשים סינתזה מדויקת של פעולות, במיוחד במשימות סימולציית המילטון.

מדריך זה משתמש בשלושה מעגלי דוגמה העוקבים אחר זרימת העבודה של תבניות Qiskit כדי להמחיש את הביצועים של כל שיטת קומפילציה. בסוף המדריך, משתמשים יהיו מצוידים לבחור את אסטרטגיית הקומפילציה המתאימה על בסיס הדרישות והמגבלות הספציפיות שלהם.

סקירה כללית של שיטות קומפילציה

1. Qiskit transpiler עם SABRE

ה-transpiler של Qiskit משתמש באלגוריתם SABRE (SWAP-based BidiREctional heuristic search) לאופטימיזציה של פריסה וניתוב מעגל. SABRE מתמקד במזעור שערי SWAP והשפעתם על עומק המעגל תוך עמידה במגבלות קישוריות החומרה. שיטה זו היא רב-תכליתית ביותר ומתאימה לאופטימיזציה של מעגלים למטרה כללית, ומספקת איזון בין ביצועים לזמן חישוב. כדי לנצל את השיפורים האחרונים ב-SABRE, המפורטים ב-[1], ניתן להגדיל את מספר הניסויים (לדוגמה, layout_trials=400, swap_trials=400). למטרות מדריך זה, נשתמש בערכי ברירת המחדל למספר הניסויים כדי להשוות ל-transpiler ברירת המחדל של Qiskit. היתרונות וחקירת הפרמטרים של SABRE מכוסים ב-מדריך מעמיק נפרד.

2. AI transpiler

ה-transpiler המונע AI ב-Qiskit משתמש בלמידת מכונה כדי לחזות אסטרטגיות טרנספילציה אופטימליות על ידי ניתוח דפוסים במבנה המעגל ומגבלות החומרה כדי לבחור את רצף האופטימיזציות הטוב ביותר עבור קלט נתון. שיטה זו אפקטיבית במיוחד עבור מעגלים קוונטיים בקנה מידה גדול, ומציעה דרגה גבוהה של אוטומציה והסתגלות לסוגי בעיות מגוונים. בנוסף לאופטימיזציה כללית של מעגלים, ניתן להשתמש ב-AI transpiler עם ה-pass AIPauliNetworkSynthesis, המכוון למעגלי רשת Pauli — בלוקים המורכבים משערים H, S, SX, CX, RX, RY ו-RZ — ומיישם גישת סינתזה מבוססת למידה מחזקת. למידע נוסף על ה-AI transpiler ואסטרטגיות הסינתזה שלו, ראה [2] ו-[3].

3. תוסף Rustiq

תוסף Rustiq מציג טכניקות סינתזה מתקדמות במיוחד עבור פעולות PauliEvolutionGate, המייצגות סיבובי Pauli המשמשים בדרך כלל בדינמיקה של Trotterization. תוסף זה הוא בעל ערך עבור מעגלים המיישמים סימולציית המילטון, כגון אלה המשמשים בבעיות כימיה קוונטית ופיזיקה, שבהן סיבובי Pauli מדויקים חיוניים לסימולציה אפקטיבית של המילטוניאנים של הבעיה. Rustiq מציע סינתזה מדויקת ובעומק נמוך של מעגלים עבור פעולות מיוחדות אלה. לפרטים נוספים על היישום והביצועים של Rustiq, עיין ב-[4].

על ידי חקירה לעומק של שיטות קומפילציה אלה, מדריך זה מספק למשתמשים כלים לשיפור הביצועים של המעגלים הקוונטיים שלהם, סולל את הדרך לחישובים קוונטיים יעילים ומעשיים יותר.

דרישות

לפני תחילת מדריך זה, ודא שיש לך את הדברים הבאים מותקנים:

  • Qiskit SDK v1.3 ומעלה, עם תמיכה ב-ויזואליזציה
  • Qiskit Runtime v0.28 ומעלה (pip install qiskit-ibm-runtime)
  • Qiskit IBM Transpiler (pip install qiskit-ibm-transpiler)
  • Qiskit AI Transpiler local mode (pip install qiskit_ibm_ai_local_transpiler)
  • ספריית גרפים Networkx (pip install networkx)

הגדרה

# 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

חלק 1: מעגל SU2 יעיל

שלב 1: מיפוי קלטים קלאסיים לבעיה קוונטית

בחלק זה, אנו חוקרים את מעגל efficient_su2, ansatz יעיל לחומרה המשמש בדרך כלל באלגוריתמים קוונטיים וריאציוניים (כגון VQE) ומשימות למידת מכונה קוונטיות. המעגל מורכב משכבות מתחלפות של סיבובים של qubit יחיד ושערי שזירה המסודרים בדפוס מעגלי, תוכננו לחקור את מרחב המצבים הקוונטיים באופן אפקטיבי תוך שמירה על עומק סביר.

נתחיל בבניית מעגל efficient_su2 אחד כדי להדגים כיצד להשוות שיטות קומפילציה שונות. לאחר חלק 1, נרחיב את הניתוח שלנו לסט גדול יותר של מעגלים, ונאפשר בנצ'מרק מקיף להערכת הביצועים של טכניקות קומפילציה שונות.

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

שלב 2: אופטימיזציה של הבעיה להרצה על חומרה קוונטית

שלב זה הוא המיקוד העיקרי של המדריך. כאן, המטרה שלנו היא לבצע אופטימיזציה של מעגלים קוונטיים להרצה יעילה על חומרה קוונטית אמיתית. המטרה העיקרית שלנו היא להפחית את עומק המעגל ומספר השערים, שהם גורמים מפתח בשיפור נאמנות ההרצה והפחתת רעש החומרה.

  • SABRE transpiler: משתמש ב-transpiler ברירת המחדל של Qiskit עם אלגוריתם הפריסה והניתוב של SABRE.
  • AI transpiler (מצב מקומי): ה-transpiler סטנדרטי המונע AI המשתמש בהיסק מקומי ובאסטרטגיית הסינתזה ברירת המחדל.
  • תוסף Rustiq: תוסף transpiler המיועד לקומפילציה בעומק נמוך המותאמת למשימות סימולציית המילטון.

מטרת השלב היא להשוות את התוצאות של שיטות אלה במונחים של עומק המעגל המטרנספל ומספר השערים. מדד חשוב נוסף שאנו מביאים בחשבון הוא זמן ריצת הטרנספילציה. על ידי ניתוח מדדים אלה, נוכל להעריך את החוזקות היחסיות של כל שיטה ולקבוע איזו מייצרת את המעגל היעיל ביותר להרצה על החומרה הנבחרת.

הערה: עבור דוגמת מעגל SU2 הראשונית, נשווה רק את ה-SABRE transpiler ל-AI transpiler ברירת המחדל. עם זאת, בבנצ'מרק הבא באמצעות מעגלי Hamlib, נשווה את כל שלוש שיטות הטרנספילציה.

# 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')>

Qiskit transpiler עם SABRE:

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

AI transpiler:

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

תוסף 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,
)

טרנספל ולכידת מדדים

כדי להשוות את הביצועים של שיטות הקומפילציה, אנו מגדירים פונקציה שמטרנספלת את מעגל הקלט ולוכדת מדדים רלוונטיים באופן עקבי. זה כולל את עומק המעגל הכולל, מספר השערים הכולל וזמן הטרנספילציה.

בנוסף למדדים סטנדרטיים אלה, אנו גם רושמים את עומק שער ה-2-qubit, שהוא מדד חשוב במיוחד להערכת הרצה על חומרה קוונטית. בניגוד לעומק כולל, הכולל את כל השערים, עומק ה-2-qubit משקף בצורה מדויקת יותר את משך ההרצה בפועל של המעגל על החומרה. הסיבה לכך היא ששערי 2-qubit בדרך כלל שולטים בתקציב הזמן והשגיאות ברוב המכשירים הקוונטיים. ככזה, מזעור עומק ה-2-qubit הוא קריטי לשיפור הנאמנות והפחתת השפעות הדה-קוהרנטיות במהלך ההרצה.

נשתמש בפונקציה זו כדי לנתח את הביצועים של שיטות הקומפילציה השונות על פני מספר מעגלים.

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.

הצגת תוצאות הטרנספילציה של אחד המעגלים.

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

טבלת תוצאות:

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

גרף תוצאות

כפי שאנו מגדירים פונקציה ללכידת מדדים באופן עקבי, נגדיר גם אחת לציור המדדים בגרף. כאן, נציג את עומק ה-2-qubit, מספר השערים וזמן הריצה עבור כל שיטת קומפילציה על פני המעגלים.

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

ניתוח תוצאות קומפילציה של מעגל SU2

בניסוי זה, אנו משווים שתי שיטות טרנספילציה — ה-SABRE transpiler של Qiskit וה-AI-powered transpiler — על סט של מעגלי efficient_su2. מכיוון שמעגלים אלה אינם כוללים פעולות PauliEvolutionGate, תוסף Rustiq אינו נכלל בהשוואה זו.

בממוצע, ה-AI transpiler מבצע טוב יותר במונחים של עומק המעגל, עם שיפור של יותר מ-10% על פני הטווח המלא של מעגלי SU2. עבור מספר השערים (גודל המעגל) וזמן ריצת הטרנספילציה, שתי השיטות מניבות תוצאות דומות באופן כללי.

עם זאת, בדיקת נקודות הנתונים הבודדות מגלה תובנה עמוקה יותר:

  • עבור רוב גדלי ה-qubit, גם SABRE וגם AI מייצרים תוצאות כמעט זהות, מה שמציע שבמקרים רבים, שתי השיטות מתכנסות לפתרונות יעילים באופן דומה.
  • עבור גדלי מעגל מסוימים, במיוחד ב-30, 50, 70 ו-90 qubits, ה-AI transpiler מוצא מעגלים רדודים משמעותית יותר מאשר SABRE. זה מצביע על כך שהגישה המבוססת למידה של AI מסוגלת לגלות פריסות אופטימליות יותר או נתיבי ניתוב במקרים שבהם ההיוריסטיקה של SABRE לא.

התנהגות זו מדגישה מסקנה חשובה:

בעוד SABRE ו-AI לעתים קרובות מייצרים תוצאות ניתנות להשוואה, ה-AI transpiler יכול מדי פעם לגלות פתרונות טובים בהרבה, במיוחד במונחים של עומק, מה שיכול להוביל לביצועים משופרים משמעותית על החומרה.

חלק 2: מעגל סימולציית המילטון

שלב 1: חקירת מעגלים עם PauliEvolutionGate

בחלק זה, אנו חוקרים מעגלים קוונטיים הבנויים באמצעות PauliEvolutionGate, המאפשר סימולציה יעילה של המילטוניאנים. ננתח כיצד שיטות קומפילציה שונות מבצעות אופטימיזציה למעגלים אלה על פני המילטוניאנים שונים.

המילטוניאנים המשמשים בבנצ'מרק

המילטוניאנים המשמשים בבנצ'מרק זה מתארים אינטראקציות זוגיות בין qubits, כולל מונחים כגון ZZZZ, XXXX ו-YYYY. המילטוניאנים אלה משמשים בדרך כלל בכימיה קוונטית, פיזיקת חומר מעובה ומדעי החומרים, שבהם הם מדגימים מערכות של חלקיקים מקיימי אינטראקציה.

לעיון, משתמשים יכולים לחקור סט רחב יותר של המילטוניאנים במאמר זה: Efficient Hamiltonian Simulation on Noisy Quantum Devices.

מקור הבנצ'מרק: Hamlib ו-Benchpress

המעגלים המשמשים בבנצ'מרק זה נלקחו מ-מאגר הבנצ'מרק Hamlib, המכיל עומסי עבודה ריאליסטיים של סימולציית המילטון.

אותם מעגלים עברו בעבר בנצ'מרק באמצעות Benchpress, מסגרת קוד פתוח להערכת ביצועי טרנספילציה קוונטיים. על ידי שימוש בסט סטנדרטי זה של מעגלים, נוכל להשוות ישירות את האפקטיביות של אסטרטגיות קומפילציה שונות על בעיות סימולציה מייצגות.

סימולציית המילטון היא משימה יסודית במחשוב קוונטי, עם יישומים בסימולציות מולקולריות, בעיות אופטימיזציה ופיזיקה של גופים רבים קוונטיים. הבנה כיצד שיטות קומפילציה שונות מבצעות אופטימיזציה למעגלים אלה יכולה לעזור למשתמשים לשפר את ההרצה המעשית של מעגלים כאלה על מכשירים קוונטיים בטווח הקרוב.

# 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

שלב 2: אופטימיזציה של הבעיה להרצה על חומרה קוונטית

כמו בדוגמה הקודמת, נשתמש באותו backend כדי להבטיח עקביות בהשוואות שלנו. מכיוון שמנהלי ה-pass (pm_sabre, pm_ai ו-pm_rustiq) כבר אותחלו, נוכל להמשיך ישירות עם טרנספילציה של מעגלי ההמילטון באמצעות כל שיטה.

שלב זה מתמקד אך ורק בביצוע הטרנספילציה ורישום מדדי המעגל המתקבלים, כולל עומק, מספר שערים וזמן ריצת הטרנספילציה. על ידי ניתוח תוצאות אלה, אנו שואפים לקבוע את היעילות של כל שיטת טרנספילציה עבור סוג זה של מעגל. טרנספל ולכוד מדדים:

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.

טבלת תוצאות (מדלגים על ויזואליזציה מכיוון שמעגלי הפלט גדולים מאוד):

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]

ויזואליזציה של ביצועים על בסיס אינדקס המעגל:

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

Output of the previous code cell

ויזואליזציה של האחוז מהמעגלים שעבורם כל שיטה הציגה את הביצועים הטובים ביותר.

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

ניתוח תוצאות קומפילציה של מעגלי המילטון

בחלק זה, אנו מעריכים את הביצועים של שלוש שיטות טרנספילציה — SABRE, ה-AI-powered transpiler ו-Rustiq — על מעגלים קוונטיים הבנויים עם PauliEvolutionGate, המשמשים בדרך כלל במשימות סימולציית המילטון.

Rustiq הציג את הביצועים הטובים ביותר בממוצע במונחים של עומק המעגל, והשיג עומק נמוך יותר בכ-20% מאשר SABRE. זה צפוי, מכיוון ש-Rustiq מיועד במיוחד לסנתז פעולות PauliEvolutionGate עם אסטרטגיות פירוק מותאמות ובעומק נמוך. יתרה מכך, תרשים העומק מראה שככל שהמעגלים עולים בגודל ובמורכבות, Rustiq מתרחב בצורה היעילה ביותר, ושומר על עומק נמוך משמעותית מ-AI ו-SABRE כאחד במעגלים גדולים יותר.

AI transpiler הראה ביצועים חזקים ועקביים עבור עומק המעגל, עם ביצועים עדיפים באופן עקבי על SABRE על פני רוב המעגלים. עם זאת, הוא ספג את זמן הריצה הגבוה ביותר, במיוחד במעגלים גדולים יותר, מה שעלול להגביל את המעשיות שלו בעומסי עבודה רגישים לזמן. הסקלביליות שלו בזמן ריצה נותרת מגבלה מרכזית, למרות שהוא מציע שיפורים מוצקים בעומק.

SABRE, בעוד ייצר את העומק הממוצע הגבוה ביותר, השיג את מספר השערים הממוצע הנמוך ביותר, ואחריו בצמוד ה-AI transpiler. זה תואם את העיצוב של ההיוריסטיקה של SABRE, שנותנת עדיפות למזעור מספר השערים באופן ישיר. Rustiq, למרות החוזקה שלו בהורדת העומק, היה בעל מספר השערים הממוצע הגבוה ביותר, שהוא פשרה ראויה לציון לשקול ביישומים שבהם גודל המעגל חשוב יותר ממשך המעגל.

סיכום

בעוד ה-AI transpiler בדרך כלל מספק תוצאות טובות יותר מאשר SABRE, במיוחד בעומק המעגל, המסקנה לא צריכה להיות פשוט "תמיד השתמש ב-AI transpiler". יש ניואנסים חשובים לקחת בחשבון:

  • AI transpiler בדרך כלל אמין ומספק מעגלים מותאמים לעומק, אך הוא בא עם פשרות בזמן ריצה, ויש לו גם מגבלות אחרות, כולל מפות צימוד נתמכות ויכולות סינתזה. אלה מפורטות ב-תיעוד Qiskit Transpiler Service.

  • במקרים מסוימים, במיוחד עם מעגלים גדולים מאוד או ספציפיים לחומרה, ה-AI transpiler עלול להיות לא יעיל. במקרים אלה, ה-SABRE transpiler ברירת המחדל נותר אמין ביותר וניתן לבצע אופטימיזציה נוספת שלו על ידי התאמת הפרמטרים שלו (ראה את ה-מדריך אופטימיזציה של SABRE).

  • חשוב גם לשקול את מבנה המעגל בעת בחירת שיטה. לדוגמה, rustiq בנוי במיוחד עבור מעגלים המערבים PauliEvolutionGate ולעתים קרובות מניב את הביצועים הטובים ביותר עבור בעיות סימולציית המילטון.

המלצה:

אין אסטרטגיית טרנספילציה אחת המתאימה לכולם. משתמשים מעודדים להבין את המבנה של המעגל שלהם ולבדוק מספר שיטות טרנספילציה — כולל AI, SABRE וכלים מיוחדים כמו Rustiq — כדי למצוא את הפתרון היעיל ביותר עבור הבעיה ומגבלות החומרה הספציפיות שלהם.

שלב 3: הרצה באמצעות primitives של Qiskit

מכיוון שמדריך זה מתמקד בטרנספילציה, לא מבוצעים ניסויים במכשיר קוונטי. המטרה היא למנף את האופטימיזציות משלב 2 כדי לקבל מעגל מטרנספל עם עומק ומספר שערים מופחתים.

שלב 4: עיבוד לאחר והחזרת תוצאה בפורמט קלאסי הרצוי

מכיוון שאין הרצה עבור מחברת זו, אין תוצאות לעיבוד לאחר.

מקורות

[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