Introduction au Transpiler Qiskit alimenté par l'IA
Estimation d'utilisation : 5 minutes sur IBM Heron (REMARQUE : il s'agit d'une estimation uniquement. Ta durée d'exécution peut varier.)
Objectifs d'apprentissage
Après avoir suivi ce tutoriel, les utilisateurs devraient comprendre :
- Comment utiliser le Transpiler alimenté par l'IA (
generate_ai_pass_manager) comme remplacement direct du Transpiler standard - Comment le Transpiler alimenté par l'IA se compare au Transpiler par défaut en termes de profondeur à deux qubits, de nombre de portes et de temps de transpilation
- Comment utiliser les circuits miroirs pour évaluer la qualité de la transpilation via l'exécution sur matériel
Prérequis
Nous suggérons que les utilisateurs soient familiers avec les sujets suivants avant de suivre ce tutoriel :
- Transpilez des circuits
- Configurez des gestionnaires de passes prédéfinis
- Passes du Transpiler alimenté par l'IA
Contexte
Le Transpiler Qiskit alimenté par l'IA introduit des passes de transpilation basées sur l'apprentissage automatique qui peuvent produire des circuits plus courts et plus efficaces pour le matériel que les méthodes heuristiques traditionnelles comme SABRE. Des circuits plus courts accumulent moins de bruit, ce qui améliore directement la qualité des résultats sur du vrai matériel quantique.
Dans ce tutoriel, nous comparons deux stratégies de transpilation :
| Stratégie | API |
|---|---|
| Par défaut | generate_preset_pass_manager(optimization_level=3, ...) |
| IA | generate_ai_pass_manager(optimization_level=1, ai_optimization_level=3, ...) |
Nous mesurons trois métriques pour chaque stratégie : profondeur des portes à deux qubits, nombre total de portes et temps d'exécution de la transpilation.
Benchmarks du Transpiler alimenté par l'IA
Dans les tests de benchmarking, le Transpiler alimenté par l'IA a systématiquement produit des circuits moins profonds et de meilleure qualité par rapport au Transpiler standard de Qiskit. Pour ces tests, nous avons utilisé la stratégie par défaut du gestionnaire de passes de Qiskit, configurée avec generate_preset_pass_manager. Bien que cette stratégie par défaut soit souvent efficace, elle peut rencontrer des difficultés avec des circuits plus grands ou plus complexes. En revanche, les passes alimentées par l'IA ont obtenu une réduction moyenne de 24 % du nombre de portes à deux qubits et une réduction de 36 % de la profondeur du circuit pour les grands circuits (plus de 100 qubits) lors de la transpilation vers la topologie heavy-hex du matériel IBM Quantum®. Pour plus d'informations sur ces benchmarks, consulte ce blog.

Ce tutoriel explore les principaux avantages des passes IA et comment elles se comparent aux méthodes traditionnelles.
Prérequis
Avant de commencer ce tutoriel, assure-toi d'avoir installé les éléments suivants :
- Qiskit SDK v2.0 ou ultérieur, avec le support de visualisation
- Qiskit Runtime (
pip install qiskit-ibm-runtime) v0.22 ou ultérieur - Qiskit IBM Transpiler avec le mode local IA (
pip install 'qiskit-ibm-transpiler[ai-local-mode]') - Qiskit Aer (
pip install qiskit-aer)
Configuration
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib qiskit qiskit-aer qiskit-ibm-runtime qiskit-ibm-transpiler
from qiskit import QuantumCircuit
from qiskit.circuit.random import random_circuit
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2
from qiskit_ibm_transpiler import generate_ai_pass_manager
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel, depolarizing_error
import matplotlib.pyplot as plt
from statistics import mean, stdev
import time
import logging
seed = 42
def transpile_with_metrics(pass_manager, circuit):
"""Transpile a circuit and return the result along with key metrics."""
start = time.time()
qc_out = pass_manager.run(circuit)
elapsed = time.time() - start
depth_2q = qc_out.depth(lambda x: x.operation.num_qubits == 2)
gate_count = qc_out.size()
return qc_out, {
"depth_2q": depth_2q,
"gate_count": gate_count,
"time_s": round(elapsed, 3),
}
def remap_to_contiguous(tqc):
"""Remap a transpiled circuit to use contiguous qubit indices.
Transpiled circuits target specific physical qubits (e.g., qubit 45, 67)
on a large backend. This remaps them to 0, 1, 2, ... so Aer only
simulates the active qubits."""
active = sorted(
{tqc.find_bit(q).index for inst in tqc.data for q in inst.qubits}
)
qubit_map = {old: new for new, old in enumerate(active)}
new_qc = QuantumCircuit(len(active))
for inst in tqc.data:
old_indices = [tqc.find_bit(q).index for q in inst.qubits]
new_qc.append(inst.operation, [qubit_map[i] for i in old_indices])
return new_qc
def build_mirror_circuit(tqc, simulate=True):
"""Build a mirror circuit: U followed by U-dagger, with measurements.
The expected output is always |0...0>, so measuring the survival
probability reveals how much noise each transpilation strategy adds.
Args:
tqc: A transpiled circuit.
simulate: If True (default), remap to contiguous qubits so Aer
only simulates the active qubits. If False, keep the full
physical layout for hardware execution."""
if simulate:
tqc = remap_to_contiguous(tqc)
mirror = tqc.compose(tqc.inverse())
mirror.measure_all()
return mirror
def print_summary(results):
"""Print a summary of each metric as mean +/- stdev across all circuits,
along with the mean percentage improvement of AI over Default."""
metrics = [
("Depth 2Q", "Depth 2Q (Default)", "Depth 2Q (AI)"),
("Gate Count", "Gate Count (Default)", "Gate Count (AI)"),
("Time (s)", "Time (Default)", "Time (AI)"),
]
header = (
f"{'Metric':<12}{'Default (mean +/- std)':>24}"
f"{'AI (mean +/- std)':>22}{'AI % improvement':>22}"
)
print(header)
print("-" * len(header))
for label, col_def, col_ai in metrics:
defaults = [r[col_def] for r in results]
ais = [r[col_ai] for r in results]
pct = [(d - a) / d * 100 for d, a in zip(defaults, ais)]
default_str = f"{mean(defaults):.1f} +/- {stdev(defaults):.1f}"
ai_str = f"{mean(ais):.1f} +/- {stdev(ais):.1f}"
pct_str = f"{mean(pct):+.1f}% +/- {stdev(pct):.1f}%"
print(f"{label:<12}{default_str:>24}{ai_str:>22}{pct_str:>22}")
def plot_metrics_and_pct(results, title_prefix):
"""Plot metric comparisons and percentage improvement of AI over Default."""
qubits = [r["Qubits"] for r in results]
metrics = [
("Depth 2Q (Default)", "Depth 2Q (AI)", "Two-Qubit Depth"),
("Gate Count (Default)", "Gate Count (AI)", "Gate Count"),
("Time (Default)", "Time (AI)", "Transpilation Time"),
]
# Row 1: raw metric comparison
fig, axs = plt.subplots(1, 3, figsize=(21, 5))
fig.suptitle(
f"{title_prefix}: Metric Comparison",
fontsize=15,
fontweight="bold",
y=1.02,
)
for ax, (col_def, col_ai, label) in zip(axs, metrics):
ax.plot(qubits, [r[col_def] for r in results], "o-", label="Default")
ax.plot(qubits, [r[col_ai] for r in results], "s-", label="AI")
ax.set_title(label)
ax.set_xlabel("Number of Qubits")
ax.set_ylabel(label)
ax.legend()
plt.tight_layout()
plt.show()
# Row 2: percentage improvement
fig, axs = plt.subplots(1, 3, figsize=(21, 5))
fig.suptitle(
f"{title_prefix}: % Improvement of AI over Default",
fontsize=15,
fontweight="bold",
y=1.02,
)
for ax, (col_def, col_ai, label) in zip(axs, metrics):
pct = [(r[col_def] - r[col_ai]) / r[col_def] * 100 for r in results]
ax.axhline(
0, color="#1f77b4", linewidth=2, label="Default (baseline)"
)
ax.plot(qubits, pct, "s-", color="#ff7f0e", label="AI")
ax.fill_between(qubits, 0, pct, alpha=0.15, color="#ff7f0e")
ax.set_title(label)
ax.set_xlabel("Number of Qubits")
ax.set_ylabel("% Improvement")
ax.legend()
plt.tight_layout()
plt.show()
# Suppress verbose AI-powered transpiler logs
logging.getLogger(
"qiskit_ibm_transpiler.wrappers.ai_local_synthesis"
).setLevel(logging.WARNING)
Exemple de simulateur à petite échelle
Étape 1 : Mapper les entrées classiques vers un problème quantique
Nous générons 20 circuits aléatoires avec une profondeur de 4, où le nombre de qubits varie de six à 25. Ces circuits serviront de cas de test pour comparer les stratégies de transpilation.
num_circuits_sim = 20
depth_sim = 4
qubit_range_sim = list(range(6, 26))
circuits_sim = [
# We have only two qubit gates, as those test how well the transpiler can optimize the circuit.
random_circuit(
num_qubits=n,
depth=depth_sim,
max_operands=2,
num_operand_distribution={2: 1},
seed=seed + i,
)
for i, n in enumerate(qubit_range_sim)
]
print(
f"Created {len(circuits_sim)} circuits with qubit counts: {qubit_range_sim}"
)
circuits_sim[0].draw(output="mpl", fold=-1)
Created 20 circuits with qubit counts: [6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
Étape 2 : Optimiser le problème pour l'exécution sur matériel quantique
Nous construisons le gestionnaire de passes par défaut (SABRE) pour le Backend choisi. Les deux stratégies de transpilation ciblent la carte de couplage complète du Backend. La simulation locale reste faisable par la suite car l'étape de simulation utilise remap_to_contiguous pour réétiqueter chaque circuit transpilé sur uniquement ses qubits actifs, de sorte qu'Aer simule uniquement ces qubits plutôt que l'ensemble du dispositif.
service = QiskitRuntimeService()
backend = service.least_busy(
min_num_qubits=100, operational=True, simulator=False
)
pm_default_sim = generate_preset_pass_manager(
optimization_level=3,
backend=backend,
seed_transpiler=seed,
)
results_sim = []
for i, qc in enumerate(circuits_sim):
n = qubit_range_sim[i]
qc_default, m_default = transpile_with_metrics(pm_default_sim, qc)
# Create a fresh AI pass manager each iteration to avoid stale layout state
pm_ai = generate_ai_pass_manager(
optimization_level=1,
ai_optimization_level=3,
backend=backend,
)
qc_ai, m_ai = transpile_with_metrics(pm_ai, qc)
results_sim.append(
{
"Qubits": n,
"Depth 2Q (Default)": m_default["depth_2q"],
"Depth 2Q (AI)": m_ai["depth_2q"],
"Gate Count (Default)": m_default["gate_count"],
"Gate Count (AI)": m_ai["gate_count"],
"Time (Default)": m_default["time_s"],
"Time (AI)": m_ai["time_s"],
}
)
print_summary(results_sim)
Fetching 4 files: 0%| | 0/4 [00:00<?, ?it/s]
Metric Default (mean +/- std) AI (mean +/- std) AI % improvement
--------------------------------------------------------------------------------
Depth 2Q 33.0 +/- 12.9 26.4 +/- 8.0 +15.8% +/- 17.6%
Gate Count 522.0 +/- 266.0 560.5 +/- 279.1 -9.0% +/- 9.0%
Time (s) 0.0 +/- 0.0 0.2 +/- 0.1 -893.6% +/- 362.9%
Le tableau récapitulatif affiche la moyenne et l'écart type de chaque métrique sur l'ensemble des 20 circuits, ainsi que le pourcentage moyen d'amélioration du Transpiler alimenté par l'IA par rapport au Transpiler par défaut. Les valeurs positives indiquent que le Transpiler alimenté par l'IA a produit de meilleurs résultats ; les valeurs négatives indiquent que le Transpiler par défaut était meilleur.
Pour cet exemple à petite échelle, le Transpiler alimenté par l'IA atteint environ 16 % de profondeur à deux qubits en moins en moyenne, mais au prix d'environ 9 % de nombre de portes en plus. Cela met en évidence un compromis clé lors du choix entre les deux stratégies : le Transpiler alimenté par l'IA privilégie la réduction de la profondeur (moins de couches séquentielles de portes à deux qubits), tandis que le Transpiler par défaut (SABRE) privilégie la minimisation du nombre total de portes (moins d'insertions de SWAP). Selon ton application, une métrique peut avoir plus d'importance que l'autre.
plot_metrics_and_pct(results_sim, "Small-Scale Random Circuits")


Profondeur à deux qubits : Le Transpiler alimenté par l'IA produit généralement des circuits avec une profondeur à deux qubits plus faible. La profondeur est l'une des métriques principales sur lesquelles le modèle de routage IA est entraîné à optimiser, et l'amélioration est visible sur la plupart des tailles de circuits, bien que SABRE l'égale ou le surpasse sur certains circuits individuels.
Nombre de portes : Les résultats sont très proches à cette échelle, SABRE ayant un léger avantage global. L'heuristique de routage de SABRE est conçue pour minimiser le nombre de portes SWAP insérées, ce qui réduit directement le nombre de portes. Pour les petites tailles de circuits, la différence est modeste.
Temps de transpilation : Le temps d'exécution de SABRE est quasi constant quel que soit le nombre de qubits, de sorte que la taille du circuit a peu d'effet sur son temps de transpilation à cette échelle. La logique de routage centrale de SABRE est très optimisée (en grande partie implémentée en Rust). Le Transpiler alimenté par l'IA prend nettement plus de temps et évolue avec la taille du circuit, bien que les temps absolus restent raisonnables pour une utilisation interactive.
Étape 3 : Exécuter en utilisant les primitives Qiskit
Pour évaluer l'impact de la transpilation sur la fidélité des circuits, construis des circuits miroirs à partir du cas à 10 qubits et exécute-les sur le simulateur Aer avec un modèle de bruit simple. La sortie attendue d'un circuit miroir est toujours la chaîne de bits tout-zéros, donc la probabilité de mesurer démontre dans quelle mesure chaque stratégie de transpilation préserve la fidélité.
# Use the 10-qubit circuit (index where qubits == 10)
idx_10q = qubit_range_sim.index(10)
qc_10q = circuits_sim[idx_10q]
qc_default_10q, _ = transpile_with_metrics(pm_default_sim, qc_10q)
pm_ai = generate_ai_pass_manager(
optimization_level=1,
ai_optimization_level=3,
backend=backend,
)
qc_ai_10q, _ = transpile_with_metrics(pm_ai, qc_10q)
tqc_methods = {
"Default": qc_default_10q,
"AI": qc_ai_10q,
}
print(
f"Default: depth {qc_default_10q.depth()}, gates {qc_default_10q.size()}"
)
print(f"AI: depth {qc_ai_10q.depth()}, gates {qc_ai_10q.size()}")
Default: depth 84, gates 280
AI: depth 91, gates 343
# Build a simple depolarizing noise model
noise_model = NoiseModel()
noise_model.add_all_qubit_quantum_error(
depolarizing_error(0.001, 1),
["sx", "x", "rz"], # ~0.1% per 1Q gate
)
noise_model.add_all_qubit_quantum_error(
depolarizing_error(0.01, 2),
["cx", "ecr"], # ~1% per 2Q gate
)
aer_sim = AerSimulator(noise_model=noise_model)
shots = 10000
survival_probs = {}
for method, tqc in tqc_methods.items():
mirror = build_mirror_circuit(tqc, simulate=True)
sampler = SamplerV2(mode=aer_sim)
job = sampler.run([mirror], shots=shots)
counts = job.result()[0].data.meas.get_counts()
all_zeros = "0" * mirror.num_qubits
survival = counts.get(all_zeros, 0) / shots
survival_probs[method] = survival
print(
f"{method:8s} P(|00...0>) = {survival:.4f} ({counts.get(all_zeros, 0)}/{shots})"
)
Default P(|00...0>) = 0.8460 (8460/10000)
AI P(|00...0>) = 0.8121 (8121/10000)
Nous avons exécuté les deux circuits miroirs sur le simulateur Aer avec un modèle de bruit dépolarisant simple. La probabilité de survie, définie comme la fraction des mesures qui renvoient la chaîne de bits tout-zéros, quantifie la quantité de bruit introduite par chaque stratégie de transpilation.
Étape 4 : Post-traiter et retourner le résultat dans le format classique souhaité
Nous extrayons la probabilité de mesurer la chaîne de bits tout-zéros des deux exécutions. Une probabilité de survie plus élevée indique une meilleure fidélité, ce qui signifie que la transpilation a introduit moins de bruit. Le graphique ci-dessous montre le complément, 1 - P(|0...0>), de sorte qu'une barre plus basse indique une meilleure fidélité et que les petites différences d'erreur sont plus faciles à voir.
# Plot 1 - P(|0...0>), the probability of an erroneous (non-zero) outcome.
# A lower bar means the transpilation introduced less noise.
error_probs = {method: 1 - p for method, p in survival_probs.items()}
fig, ax = plt.subplots(figsize=(6, 4))
ax.bar(
error_probs.keys(),
error_probs.values(),
color=["steelblue", "coral"],
)
ax.set_ylabel("1 - P(|0...0>)")
ax.set_title("Mirror Circuit Error (10-qubit, Aer Simulator)")
ax.set_ylim(0, 1)
plt.tight_layout()
plt.show()
Dans ce cas, le Transpiler par défaut a produit un circuit à la fois moins profond et plus petit pour cette instance particulière à 10 qubits, donc sa fidélité plus élevée est attendue. Les résultats par circuit varient : comme le montre le tableau récapitulatif ci-dessus, l'avantage du Transpiler alimenté par l'IA est une profondeur à deux qubits plus faible en moyenne, pas sur chaque circuit individuel. La stratégie qui donne une fidélité plus élevée dépend de l'ampleur de la différence de chaque métrique, des caractéristiques de bruit du matériel et de la structure du circuit. Sous un modèle de bruit dépolarisant uniforme, le nombre total de portes a souvent un impact plus direct sur l'erreur accumulée que la profondeur seule.
Exemple sur matériel à grande échelle
Étapes 1-4
Ici, tous ces détails sont rassemblés dans un flux de travail clair à une échelle plus grande, qui est ensuite exécuté sur du vrai matériel quantique.
Le code ci-dessous génère 25 circuits aléatoires avec une profondeur de 8, où le nombre de qubits varie de 26 à 50. Ces circuits sont ensuite transpilés avec les deux stratégies et les mêmes métriques sont collectées. Ensuite, nous construisons des circuits miroirs à partir du cas à 26 qubits et les soumettons au vrai Backend.
# -------------------------Step 1-------------------------
num_circuits_hw = 25
depth_hw = 8
qubit_range_hw = list(range(26, 51))
circuits_hw = [
# We have only two qubit gates, as those test how well the transpiler can optimize the circuit.
random_circuit(
num_qubits=n,
depth=depth_hw,
max_operands=2,
num_operand_distribution={2: 1},
seed=seed + i,
)
for i, n in enumerate(qubit_range_hw)
]
print(
f"Created {len(circuits_hw)} circuits with qubit counts: {qubit_range_hw}"
)
Created 25 circuits with qubit counts: [26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]
# -------------------------Step 2-------------------------
pm_default = generate_preset_pass_manager(
optimization_level=3,
backend=backend,
seed_transpiler=seed,
)
results_hw = []
for i, qc in enumerate(circuits_hw):
n = qubit_range_hw[i]
qc_default, m_default = transpile_with_metrics(pm_default, qc)
# Create a fresh AI pass manager each iteration to avoid stale layout state
pm_ai = generate_ai_pass_manager(
optimization_level=1,
ai_optimization_level=3,
backend=backend,
)
qc_ai, m_ai = transpile_with_metrics(pm_ai, qc)
results_hw.append(
{
"Qubits": n,
"Depth 2Q (Default)": m_default["depth_2q"],
"Depth 2Q (AI)": m_ai["depth_2q"],
"Gate Count (Default)": m_default["gate_count"],
"Gate Count (AI)": m_ai["gate_count"],
"Time (Default)": m_default["time_s"],
"Time (AI)": m_ai["time_s"],
}
)
print_summary(results_hw)
Metric Default (mean +/- std) AI (mean +/- std) AI % improvement
--------------------------------------------------------------------------------
Depth 2Q 217.4 +/- 50.4 191.0 +/- 35.6 +10.9% +/- 10.7%
Gate Count 4513.3 +/- 1394.3 5227.1 +/- 1536.4 -16.4% +/- 5.8%
Time (s) 0.1 +/- 0.0 3.5 +/- 1.5 -3588.2% +/- 643.6%
plot_metrics_and_pct(results_hw, "Large-Scale Random Circuits")


# -------------------------Step 3-------------------------
# Build mirror circuits from the 26-qubit case
idx_26q = qubit_range_hw.index(26)
qc_26q = circuits_hw[idx_26q]
qc_default_26q, _ = transpile_with_metrics(pm_default, qc_26q)
pm_ai = generate_ai_pass_manager(
optimization_level=1,
ai_optimization_level=3,
backend=backend,
)
qc_ai_26q, _ = transpile_with_metrics(pm_ai, qc_26q)
mirror_default_hw = build_mirror_circuit(qc_default_26q, simulate=False)
mirror_ai_hw = build_mirror_circuit(qc_ai_26q, simulate=False)
# Re-transpile to basis gates (the inverse can introduce gates like sxdg)
pm_basis = generate_preset_pass_manager(
optimization_level=0,
backend=backend,
)
mirror_default_hw = pm_basis.run(mirror_default_hw)
mirror_ai_hw = pm_basis.run(mirror_ai_hw)
print(
f"Mirror circuit (Default): depth {mirror_default_hw.depth()}, gates {mirror_default_hw.size()}"
)
print(
f"Mirror circuit (AI): depth {mirror_ai_hw.depth()}, gates {mirror_ai_hw.size()}"
)
# Submit to real hardware
sampler_hw = SamplerV2(mode=backend)
sampler_hw.options.environment.job_tags = ["TUT_AITI"]
shots_hw = 500000
job_hw = sampler_hw.run([mirror_default_hw, mirror_ai_hw], shots=shots_hw)
print(f"Job submitted: {job_hw.job_id()}")
Mirror circuit (Default): depth 1577, gates 9672
Mirror circuit (AI): depth 1235, gates 11092
Job submitted: d8gt7vm6983c73dqbg0g
# -------------------------Step 4-------------------------
result_hw = job_hw.result()
survival_probs_hw = {}
for i, method in enumerate(["Default", "AI"]):
counts = result_hw[i].data.meas.get_counts()
mirror = [mirror_default_hw, mirror_ai_hw][i]
all_zeros = "0" * mirror.num_qubits
survival = counts.get(all_zeros, 0) / shots_hw
survival_probs_hw[method] = survival
print(
f"{method:8s} P(|00...0>) = {survival:.4f} ({counts.get(all_zeros, 0)}/{shots_hw})"
)
# Plot 1 - P(|0...0>), the probability of an erroneous (non-zero) outcome.
# A lower bar means the transpilation introduced less noise.
error_probs_hw = {method: 1 - p for method, p in survival_probs_hw.items()}
fig, ax = plt.subplots(figsize=(6, 4))
ax.bar(
error_probs_hw.keys(),
error_probs_hw.values(),
color=["steelblue", "coral"],
)
ax.set_ylabel("1 - P(|0...0>)")
ax.set_title(f"Mirror Circuit Error (26-qubit, {backend.name})")
ax.set_ylim(0, 1)
plt.tight_layout()
plt.show()
Default P(|00...0>) = 0.0005 (239/500000)
AI P(|00...0>) = 0.0050 (2516/500000)
Analyse des résultats
Les résultats à grande échelle renforcent les tendances observées dans l'exemple à petite échelle, désormais à une échelle plus exigeante.
Profondeur à deux qubits : Le Transpiler alimenté par l'IA continue de produire une profondeur à deux qubits nettement plus faible sur toute la plage de tailles de circuits. L'optimisation de la profondeur est l'un des principaux objectifs sur lesquels le modèle de routage IA est entraîné, et l'avantage est plus prononcé pour les grands nombres de qubits où le problème de routage devient plus difficile pour les méthodes heuristiques.
Nombre de portes : Le Transpiler par défaut (SABRE) produit systématiquement des circuits avec moins de portes sur toutes les tailles de circuits dans cette plage. L'heuristique de SABRE est spécifiquement conçue pour minimiser le nombre de portes, et à cette échelle, l'avantage est clair et uniforme.
Temps de transpilation : L'écart dans le temps de transpilation s'élargit à plus grande échelle. SABRE reste quasi constant, tandis que le temps d'exécution du Transpiler alimenté par l'IA augmente plus fortement. Malgré cela, le temps d'exécution du Transpiler alimenté par l'IA reste pratique pour la plupart des flux de travail.
Fidélité des circuits miroirs : Les deux méthodes produisent des probabilités de survie bien inférieures à 1 % à cette échelle, laissant peu de signal exploitable. Avec des nombres totaux de portes d'environ 10 000 et des profondeurs à deux qubits dépassant 1 000, le bruit dépolarisant accumulé sur le circuit miroir submerge la plupart du signal. Cela met en évidence une limitation clé de l'approche par circuit miroir : bien qu'elle soit simple et ne nécessite pas de simulation classique, elle ne passe pas bien à l'échelle pour les circuits grands ou profonds, où les deux méthodes sont poussées près du plancher de bruit et le petit signal survivant est dominé par l'erreur accumulée.
Bien que ces résultats soulignent l'efficacité du Transpiler alimenté par l'IA, il est important de noter ses limitations. La méthode de synthèse IA n'est actuellement disponible que pour certaines cartes de couplage, ce qui peut restreindre son applicabilité plus large. Cette contrainte doit être prise en compte lors de l'évaluation de son utilisation dans différents scénarios.
Prochaines étapes
Si tu as trouvé ce travail intéressant, tu pourrais être intéressé par le matériel suivant :