Zum Hauptinhalt springen

Kompilierungsmethoden für Hamiltonian-Simulations-Schaltkreise

Geschätzte QPU-Nutzung: In diesem Tutorial wurde keine Ausführung gemacht, weil's auf'n Transpilierungsprozess fokussiert ist.

Hintergrund

Die Kompilierung von Quantenschaltkreisen ist a entscheidender Schritt im Quantencomputing-Workflow. Dabei wird a High-Level-Quantenalgorithmus in an physischen Quantenschaltkreis umgewandelt, der die Einschränkungen der Ziel-Quantenhardware einhält. A effektive Kompilierung kann die Leistung von Quantenalgorithmen erheblich verbessern, indem sie die Schaltkreistiefe, die Anzahl der Gates und die Ausführungszeit reduziert. Dieses Tutorial erkundet drei verschiedene Ansätze zur Quantenschaltkreis-Kompilierung in Qiskit und zeigt ihre Stärken und Anwendungen anhand von praktischen Beispielen.

Das Ziel dieses Tutorials ist, dir beizubringen, wie du drei Kompilierungsmethoden in Qiskit anwendest und bewertest: den SABRE-Transpiler, den KI-gestützten Transpiler und das Rustiq-Plugin. Du lernst, wie du jede Methode effektiv einsetzt und wie du ihre Leistung über verschiedene Quantenschaltkreise hinweg benchmarkst. Am End des Tutorials wirst du in der Lage sein, Kompilierungsstrategien basierend auf bestimmten Optimierungszielen auszuwählen und anzupassen — sei's die Reduzierung der Schaltkreistiefe, die Minimierung der Gate-Anzahl oder die Verbesserung der Laufzeit.

Was du lernst

  • Wie du den Qiskit-Transpiler mit SABRE für Layout- und Routing-Optimierung verwendest.
  • Wie du den KI-Transpiler für fortgeschrittene, automatisierte Schaltkreis-Optimierung nutzt.
  • Wie du das Rustiq-Plugin für Schaltkreise einsetzt, die a präzise Synthese von Operationen erfordern, insbesondere bei Hamiltonian-Simulations-Aufgaben.

Dieses Tutorial verwendet drei Beispielschaltkreise nach dem Qiskit-Patterns-Workflow, um die Leistung jeder Kompilierungsmethode zu veranschaulichen. Am End des Tutorials wirst du gerüstet sein, die passende Kompilierungsstrategie basierend auf deinen spezifischen Anforderungen und Einschränkungen zu wählen.

Übersicht der Kompilierungsmethoden

1. Qiskit-Transpiler mit SABRE

Der Qiskit-Transpiler verwendet den SABRE-Algorithmus (SWAP-based BidiREctional heuristic search), um das Schaltkreis-Layout und Routing zu optimieren. SABRE fokussiert sich auf die Minimierung von SWAP-Gates und deren Auswirkungen auf die Schaltkreistiefe, während er die Hardware-Verbindungs-Constraints einhält. Diese Methode ist sehr vielseitig und eignet sich für allgemeine Schaltkreis-Optimierung — sie bietet a gute Balance zwischen Leistung und Rechenzeit. Um von den neuesten Verbesserungen in SABRE zu profitieren, die in [1] beschrieben werden, kannst du die Anzahl der Versuche erhöhen (zum Beispiel layout_trials=400, swap_trials=400). Für die Zwecke dieses Tutorials verwenden wir die Standardwerte für die Anzahl der Versuche, um a Vergleich mit Qiskits Standard-Transpiler zu ermöglichen. Die Vorteile und die Parameterexploration von SABRE werden in a separatem Deep-Dive-Tutorial behandelt.

2. KI-Transpiler

Der KI-gestützte Transpiler in Qiskit verwendet maschinelles Lernen, um optimale Transpilierungsstrategien vorherzusagen. Er analysiert Muster in der Schaltkreisstruktur und den Hardware-Constraints, um die beste Abfolge von Optimierungen für a gegebenen Input auszuwählen. Diese Methode ist besonders effektiv für groß angelegte Quantenschaltkreise und bietet a hohen Grad an Automatisierung und Anpassungsfähigkeit für verschiedene Problemtypen. Zusätzlich zur allgemeinen Schaltkreis-Optimierung kann der KI-Transpiler mit dem AIPauliNetworkSynthesis-Pass verwendet werden, der auf Pauli-Netzwerk-Schaltkreise abzielt — Blöcke aus H, S, SX, CX, RX, RY- und RZ-Gates — und a auf Reinforcement Learning basierenden Syntheseansatz anwendet. Für mehr Informationen zum KI-Transpiler und seinen Synthesestrategien, schau dir [2] und [3] an.

3. Rustiq-Plugin

Das Rustiq-Plugin führt fortgeschrittene Synthesetechniken speziell für PauliEvolutionGate-Operationen ein, die Pauli-Rotationen repräsentieren, die häufig in Trotterisierten Dynamiken verwendet werden. Dieses Plugin ist wertvoll für Schaltkreise, die Hamiltonian-Simulation implementieren, wie sie in der Quantenchemie und Physikproblemen verwendet werden, wo genaue Pauli-Rotationen essenziell san für die effektive Simulation von Problem-Hamiltonians. Rustiq bietet a präzise, tiefenoptimierte Schaltkreis-Synthese für diese spezialisierten Operationen. Für mehr Details zur Implementierung und Leistung von Rustiq, schau dir [4] an.

Durch das eingehende Erkunden dieser Kompilierungsmethoden gibt dir dieses Tutorial die Werkzeuge, um die Leistung deiner Quantenschaltkreise zu verbessern und den Weg für effizientere und praktischere Quantenberechnungen zu ebnen.

Voraussetzungen

Bevor du mit dem Tutorial anfangst, stell sicher, dass du Folgendes installiert hast:

  • Qiskit SDK v1.3 oder später, mit Visualisierungs-Support
  • Qiskit Runtime v0.28 oder später (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-Graphbibliothek (pip install networkx)

Setup

# Added by doQumentation — installs packages not in the Binder environment
!pip install -q qiskit-ibm-transpiler
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

Teil 1: Efficient-SU2-Schaltkreis

Schritt 1: Klassische Eingaben auf a Quantenproblem abbilden

In diesem Abschnitt erkunden wir den efficient_su2-Schaltkreis, a hardware-effizienter Ansatz, der häufig in variationellen Quantenalgorithmen (wie VQE) und Quantenmaschinenlernaufgaben verwendet wird. Der Schaltkreis besteht aus abwechselnden Schichten von Einzelqubit-Rotationen und Verschränkungs-Gates, die in a kreisförmigen Muster angeordnet san. Er ist darauf ausgelegt, den Quantenzustandsraum effektiv zu erkunden, während er a handhabbare Tiefe beibehält.

Wir beginnen damit, a efficient_su2-Schaltkreis zu konstruieren, um zu zeigen, wie man verschiedene Kompilierungsmethoden vergleicht. Nach Teil 1 erweitern wir unsere Analyse auf a größere Menge an Schaltkreisen, was a umfassendes Benchmark zur Bewertung der Leistung verschiedener Kompilierungstechniken ermöglicht.

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

Schritt 2: Problem für die Ausführung auf Quantenhardware optimieren

Dieser Schritt ist der Hauptfokus des Tutorials. Hier wollen wir Quantenschaltkreise für a effiziente Ausführung auf echter Quantenhardware optimieren. Unser primäres Ziel ist es, Schaltkreistiefe und Gate-Anzahl zu reduzieren, was Schlüsselfaktoren san, um die Ausführungsqualität zu verbessern und Hardware-Rauschen zu mindern.

  • SABRE-Transpiler: Verwendet Qiskits Standard-Transpiler mit dem SABRE-Layout- und Routing-Algorithmus.
  • KI-Transpiler (local mode): Der Standard-KI-gestützte Transpiler mit lokaler Inferenz und der Standard-Synthesestrategie.
  • Rustiq-Plugin: A Transpiler-Plugin, das für tiefenoptimierte Kompilierung für Hamiltonian-Simulations-Aufgaben entwickelt wurde.

Das Ziel dieses Schritts ist es, die Ergebnisse dieser Methoden in Bezug auf die Tiefe und die Gate-Anzahl des transpilierten Schaltkreises zu vergleichen. A weiterer wichtiger Aspekt, den wir berücksichtigen, ist die Transpilierungslaufzeit. Durch die Analyse dieser Metriken können wir die relativen Stärken jeder Methode bewerten und bestimmen, welche den effizientesten Schaltkreis für die Ausführung auf der ausgewählten Hardware produziert.

Hinweis: Für das anfängliche SU2-Schaltkreis-Beispiel vergleichen wir nur den SABRE-Transpiler mit dem Standard-KI-Transpiler. Im nachfolgenden Benchmark mit Hamlib-Schaltkreisen vergleichen wir jedoch alle drei Transpilierungsmethoden.

# 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 mit SABRE:

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

KI-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-Plugin:

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,
)

Transpilieren und Metriken erfassen

Um die Leistung der Kompilierungsmethoden zu vergleichen, definieren wir a Funktion, die den Eingabeschaltkreis transpiliert und relevante Metriken auf a einheitliche Weise erfasst. Das umfasst die gesamte Schaltkreistiefe, die gesamte Gate-Anzahl und die Transpilierungszeit.

Zusätzlich zu diesen Standardmetriken erfassen wir auch die 2-Qubit-Gate-Tiefe, was a besonders wichtige Metrik für die Bewertung der Ausführung auf Quantenhardware ist. Im Unterschied zur gesamten Tiefe, die alle Gates umfasst, spiegelt die 2-Qubit-Tiefe die tatsächliche Ausführungsdauer auf Hardware genauer wider. Das liegt daran, dass 2-Qubit-Gates in den meisten Quantengeräten typischerweise das Zeit- und Fehlerbudget dominieren. Die Minimierung der 2-Qubit-Tiefe ist daher entscheidend für die Verbesserung der Qualität und die Reduzierung von Dekohärenzeffekten während der Ausführung.

Wir verwenden diese Funktion, um die Leistung der verschiedenen Kompilierungsmethoden über mehrere Schaltkreise hinweg zu analysieren.

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.

Anzeige der transpilierten Ergebnisse für an der Schaltkreise:

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

Ergebnistabelle:

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

Ergebnisgraph

Da wir a Funktion definiert haben, um Metriken einheitlich zu erfassen, definieren wir auch eine, um die Metriken grafisch darzustellen. Hier stellen wir die 2-Qubit-Tiefe, die Gate-Anzahl und die Laufzeit für jede Kompilierungsmethode über die Schaltkreise hinweg dar.

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

Analyse der SU2-Schaltkreis-Kompilierungsergebnisse

In diesem Experiment vergleichen wir zwei Transpilierungsmethoden — Qiskits SABRE-Transpiler und den KI-gestützten Transpiler — auf a Menge von efficient_su2-Schaltkreisen. Da diese Schaltkreise keine PauliEvolutionGate-Operationen enthalten, ist das Rustiq-Plugin in diesem Vergleich nicht enthalten.

Im Durchschnitt schneidet der KI-Transpiler besser in Bezug auf die Schaltkreistiefe ab, mit a Verbesserung von mehr als 10% über den gesamten Bereich der SU2-Schaltkreise. Für die Gate-Anzahl (Schaltkreisgröße) und die Transpilierungslaufzeit liefern beide Methoden insgesamt ähnliche Ergebnisse.

Wenn man sich jedoch die einzelnen Datenpunkte ansieht, ergibt sich a tiefere Erkenntnis:

  • Bei den meisten Qubit-Größen liefern sowohl SABRE als auch KI nahezu identische Ergebnisse, was darauf hindeutet, dass in vielen Fällen beide Methoden zu ähnlich effizienten Lösungen konvergieren.
  • Bei bestimmten Schaltkreisgrößen — insbesondere bei 30, 50, 70 und 90 Qubits — findet der KI-Transpiler deutlich flachere Schaltkreise als SABRE. Das zeigt, dass der lernbasierte Ansatz der KI in der Lage ist, optimalere Layouts oder Routing-Pfade in Fällen zu entdecken, wo die SABRE-Heuristik das nicht schafft.

Dieses Verhalten hebt a wichtige Erkenntnis hervor:

Während SABRE und KI oft vergleichbare Ergebnisse liefern, kann der KI-Transpiler gelegentlich viel bessere Lösungen entdecken, insbesondere in Bezug auf die Tiefe, was zu a erheblich verbesserten Leistung auf Hardware führen kann.

Teil 2: Hamiltonian-Simulations-Schaltkreis

Schritt 1: Schaltkreise mit PauliEvolutionGate untersuchen

In diesem Abschnitt untersuchen wir Quantenschaltkreise, die mit PauliEvolutionGate konstruiert wurden, was a effiziente Simulation von Hamiltonians ermöglicht. Wir analysieren, wie verschiedene Kompilierungsmethoden diese Schaltkreise über verschiedene Hamiltonians hinweg optimieren.

Verwendete Hamiltonians im Benchmark

Die in diesem Benchmark verwendeten Hamiltonians beschreiben paarweise Wechselwirkungen zwischen Qubits, einschließlich Terme wie ZZZZ, XXXX und YYYY. Diese Hamiltonians werden häufig in der Quantenchemie, der Physik kondensierter Materie und der Materialwissenschaft verwendet, wo sie Systeme interagierender Teilchen modellieren.

Als Referenz können Benutzer a breitere Menge von Hamiltonians in diesem Papier erkunden: Efficient Hamiltonian Simulation on Noisy Quantum Devices.

Benchmark-Quelle: Hamlib und Benchpress

Die in diesem Benchmark verwendeten Schaltkreise stammen aus dem Hamlib-Benchmark-Repository, das realistische Hamiltonian-Simulations-Workloads enthält.

Diese selben Schaltkreise wurden zuvor mit Benchpress gebencht, a Open-Source-Framework zur Bewertung der Quantentranspilierungsleistung. Durch die Verwendung dieses standardisierten Schaltkreissatzes können wir die Effektivität verschiedener Kompilierungsstrategien bei repräsentativen Simulationsproblemen direkt vergleichen.

Hamiltonian-Simulation ist a grundlegende Aufgabe im Quantencomputing, mit Anwendungen in molekularen Simulationen, Optimierungsproblemen und der Quantenphysik des Vielteilchensystems. Zu verstehen, wie verschiedene Kompilierungsmethoden diese Schaltkreise optimieren, hilft dir dabei, die praktische Ausführung solcher Schaltkreise auf Quantengeräten der nahen Zukunft zu verbessern.

# 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

Schritt 2: Problem für die Ausführung auf Quantenhardware optimieren

Wie im vorherigen Beispiel verwenden wir dasselbe Backend, um die Konsistenz unserer Vergleiche sicherzustellen. Da die Pass-Manager (pm_sabre, pm_ai und pm_rustiq) bereits initialisiert wurden, können wir direkt mit der Transpilierung der Hamiltonian-Schaltkreise mit jeder Methode fortfahren.

Dieser Schritt konzentriert sich ausschließlich auf die Durchführung der Transpilierung und die Aufzeichnung der daraus resultierenden Schaltkreismetriken, einschließlich Tiefe, Gate-Anzahl und Transpilierungslaufzeit. Durch die Analyse dieser Ergebnisse wollen wir die Effizienz jeder Transpilierungsmethode für diesen Schaltkreistyp bestimmen. Transpilieren und Metriken erfassen:

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.

Ergebnistabelle (ohne Visualisierung, da die Ausgabeschaltkreise sehr groß san):

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]

Leistung nach Schaltkreisindex visualisieren:

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

Output of the previous code cell

Den prozentualen Anteil der Schaltkreise visualisieren, bei denen jede Methode am besten abgeschnitten hat:

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

Analyse der Hamiltonian-Schaltkreis-Kompilierungsergebnisse

In diesem Abschnitt bewerten wir die Leistung von drei Transpilierungsmethoden — SABRE, dem KI-gestützten Transpiler und Rustiq — auf Quantenschaltkreisen, die mit PauliEvolutionGate konstruiert wurden. Diese Schaltkreise werden häufig in Hamiltonian-Simulations-Aufgaben verwendet.

Rustiq hat im Durchschnitt am besten in Bezug auf die Schaltkreistiefe abgeschnitten und eine ca. 20% niedrigere Tiefe als SABRE erreicht. Das ist zu erwarten, da Rustiq speziell dafür entwickelt wurde, PauliEvolutionGate-Operationen mit optimierten, tiefenreduzierten Dekompositionsstrategien zu synthetisieren. Außerdem zeigt der Tiefenplot, dass Rustiq, wenn die Schaltkreise an Größe und Komplexität zunehmen, am effektivsten skaliert und bei größeren Schaltkreisen eine deutlich niedrigere Tiefe als sowohl KI als auch SABRE beibehält.

Der KI-Transpiler hat a starke und konsistente Leistung in Bezug auf die Schaltkreistiefe gezeigt und übertrifft SABRE konsistent bei den meisten Schaltkreisen. Er hat jedoch die höchste Laufzeit verursacht, insbesondere bei größeren Schaltkreisen, was seine Praktikabilität in zeitkritischen Workloads einschränken kann. Seine Skalierbarkeit in der Laufzeit bleibt a wesentliche Einschränkung, auch wenn er solide Verbesserungen in der Tiefe bietet.

SABRE erzielte zwar die höchste durchschnittliche Tiefe, erreichte jedoch die niedrigste durchschnittliche Gate-Anzahl, dicht gefolgt vom KI-Transpiler. Das stimmt mit dem Design von SABREs Heuristik überein, das direkt auf die Minimierung der Gate-Anzahl abzielt. Rustiq hat trotz seiner Stärke bei der Tiefenreduzierung die höchste durchschnittliche Gate-Anzahl, was a bedeutenden Trade-off ist, den man in Anwendungen beachten sollte, wo die Schaltkreisgröße wichtiger ist als die Schaltkreisdauer.

Zusammenfassung

Während der KI-Transpiler im Allgemeinen bessere Ergebnisse als SABRE liefert, insbesondere in Bezug auf die Schaltkreistiefe, sollte die Schlussfolgerung nicht einfach sein: "Verwende immer den KI-Transpiler." Es gibt wichtige Nuancen zu beachten:

  • KI-Transpiler ist typischerweise zuverlässig und liefert tiefenoptimierte Schaltkreise, bringt aber Trade-offs in der Laufzeit mit sich und hat auch andere Einschränkungen, darunter unterstützte Coupling-Maps und Synthesefähigkeiten. Diese sind in der Qiskit-Transpiler-Service-Dokumentation beschrieben.

  • In manchen Fällen, insbesondere bei sehr großen oder hardware-spezifischen Schaltkreisen, ist der KI-Transpiler möglicherweise nicht so effektiv. In diesen Fällen bleibt der Standard-SABRE-Transpiler extrem zuverlässig und kann durch Anpassung seiner Parameter weiter optimiert werden (sieh dir das SABRE-Optimierungs-Tutorial an).

  • Es ist auch wichtig, die Schaltkreisstruktur bei der Wahl einer Methode zu berücksichtigen. rustiq ist zum Beispiel speziell für Schaltkreise mit PauliEvolutionGate entwickelt worden und liefert oft die beste Leistung für Hamiltonian-Simulationsprobleme.

Empfehlung:

Es gibt keine universelle Transpilierungsstrategie. Du bist aufgefordert, die Struktur deines Schaltkreises zu verstehen und mehrere Transpilierungsmethoden zu testen — darunter KI, SABRE und spezialisierte Tools wie Rustiq — um die effizienteste Lösung für dein spezifisches Problem und deine Hardware-Constraints zu finden.

Schritt 3: Mit Qiskit-Primitiven ausführen

Da dieses Tutorial auf die Transpilierung fokussiert ist, werden keine Experimente auf einem Quantengerät ausgeführt. Das Ziel ist es, die Optimierungen aus Schritt 2 zu nutzen, um a transpilierten Schaltkreis mit reduzierter Tiefe und Gate-Anzahl zu erhalten.

Schritt 4: Nachverarbeiten und Ergebnis im gewünschten klassischen Format zurückgeben

Da es für dieses Notebook keine Ausführung gibt, gibt's auch keine Ergebnisse zur Nachverarbeitung.

Referenzen

[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