Introduzione al transpiler basato su Qiskit AI
Stima della durata: 5 minuti su IBM Heron (NOTA: si tratta solo di una stima. (La durata potrebbe variare.)
Risultati di apprendimento
Dopo aver seguito questo tutorial, gli utenti dovrebbero aver compreso:
- Come utilizzare il transpiler basato sull'intelligenza artificiale (
generate_ai_pass_manager) come sostituto diretto del transpiler standard - Confronto tra il transpiler basato sull'intelligenza artificiale e quello predefinito in termini di profondità a due qubit, numero di gate e tempo di transpilazione
- Come utilizzare i circuiti specchio per valutare la qualità della transpilazione tramite l'esecuzione hardware
Prerequisiti
Consigliamo agli utenti di acquisire familiarità con i seguenti argomenti prima di seguire questo tutorial:
- Circuiti Transpile
- Configurare i gestori di pass predefiniti
- Il transpiler basato sull'intelligenza artificiale supera il test
Sfondo
Il transpiler basato sull'intelligenza artificiale di Qiskit introduce passaggi di transpilazione basati sull'apprendimento automatico in grado di produrre circuiti più brevi e più efficienti dal punto di vista hardware rispetto ai metodi euristici tradizionali come SABRE. I circuiti più corti accumulano meno rumore, il che migliora direttamente la qualità dei risultati sull'hardware quantistico reale.
In questo tutorial mettiamo a confronto due strategie di transpilazione:
Strategia | Services |
|---|---|
| Predefinito | generate_preset_pass_manager(optimization_level=3, ...) |
| IA | generate_ai_pass_manager(optimization_level=1, ai_optimization_level=3, ...) |
Per ogni strategia misuriamo tre parametri: la profondità dei gate a due qubit, il numero totale di gate e il tempo di esecuzione della transpilazione.
Benchmark dei transpiler basati sull'intelligenza artificiale
Nei test di benchmark, il transpiler basato sull'intelligenza artificiale ha prodotto costantemente circuiti meno complessi e di qualità superiore rispetto al transpiler standard di Qiskit. Per questi test abbiamo utilizzato la strategia predefinita di gestione dei passaggi di Qiskit, configurata con generate_preset_pass_manager. Sebbene questa strategia predefinita sia spesso efficace, può incontrare difficoltà con circuiti più grandi o più complessi. Al contrario, i passaggi basati sull’intelligenza artificiale hanno consentito una riduzione media del 24% nel numero di gate a due qubit e del 36% nella profondità dei circuiti di grandi dimensioni (oltre 100 qubit) durante la transpilazione nella topologia “heavy-hex” dell’hardware dell’ IBM Quantum®. Per ulteriori informazioni su questi benchmark, consulta questo blog.
Questo tutorial illustra i principali vantaggi dei passaggi basati sull'intelligenza artificiale e li mette a confronto con i metodi tradizionali.
Requisiti
Prima di iniziare questo tutorial, assicurati di avere installato quanto segue:
- Qiskit SDK v2.0 o versioni successive, con supporto alla visualizzazione
- Qiskit Runtime
pip install qiskit-ibm-runtimev0.22 o versioni successive - Transpilatore Qiskit IBM con modalità locale AI (
pip install 'qiskit-ibm-transpiler[ai-local-mode]') - Qiskit Aer (
pip install qiskit-aer)
Configura
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)Esempio di simulatore su piccola scala
Fase 1: mappare gli input classici su un problema quantistico
Generiamo 20 circuiti casuali di profondità 4, in cui il numero di qubit varia da sei a 25. Questi circuiti fungeranno da casi di prova per il confronto tra le diverse strategie di transpilazione.
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 "
f"from {qubit_range_sim[0]} to {qubit_range_sim[-1]}"
)
circuits_sim[0].draw(output="mpl", fold=-1)Output:
Created 20 circuits with qubit counts from 6 to 25
Fase 2: Ottimizzazione del problema per l'esecuzione su hardware quantistico
Creiamo il gestore di passaggi predefinito (SABRE) per il backend selezionato. Entrambe le strategie di transpilazione prendono di mira la mappa di accoppiamento completa del backend. La simulazione locale rimane gestibile anche in seguito, poiché la fase di simulazione utilizza remap_to_contiguous per riassegnare ogni circuito transpilato esclusivamente ai propri qubit attivi; in questo modo, Aer simula solo quei qubit anziché l'intero dispositivo.
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)Output:
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%
La tabella riassuntiva mostra la media e la deviazione standard di ciascun parametro per tutti i 20 circuiti, insieme alla percentuale media di miglioramento ottenuta dal transpiler basato sull'intelligenza artificiale rispetto a quello predefinito. I valori positivi indicano che il transpiler basato sull'intelligenza artificiale ha prodotto risultati migliori; i valori negativi indicano che l'impostazione predefinita era migliore.
In questo esempio su piccola scala, il transpiler basato sull’intelligenza artificiale raggiunge in media una profondità a due qubit inferiore di circa il 16%, ma a costo di un numero di gate superiore di circa il 9%. Ciò mette in evidenza un compromesso fondamentale nella scelta tra le due strategie: il transpiler basato sull’intelligenza artificiale privilegia la riduzione della profondità (un numero minore di livelli sequenziali di porte a due qubit), mentre il transpiler predefinito (SABRE) privilegia la riduzione al minimo del numero totale di porte (un numero minore di inserimenti di porte SWAP). A seconda dell'applicazione, un parametro potrebbe risultare più importante dell'altro.
plot_metrics_and_pct(results_sim, "Small-Scale Random Circuits")Output:
Profondità a due qubit: il transpiler basato sull'intelligenza artificiale produce generalmente circuiti con una profondità a due qubit inferiore. La profondità è uno dei parametri principali che il modello di instradamento basato sull’intelligenza artificiale è stato addestrato a ottimizzare, e il miglioramento è evidente nella maggior parte delle dimensioni dei circuiti, sebbene SABRE riesca a eguagliarlo o a superarlo su singoli circuiti.
Conteggio dei voti: i risultati sono molto simili su questa scala, con SABRE che mantiene un leggero vantaggio complessivo. L'euristica di instradamento di SABRE è progettata per ridurre al minimo il numero di porte SWAP inserite, il che comporta una riduzione diretta del numero di porte. Quando le dimensioni dei circuiti sono ridotte, la differenza è modesta.
Tempo di transpilazione: il tempo di esecuzione di SABRE è pressoché costante indipendentemente dal numero di qubit, quindi le dimensioni del circuito hanno un effetto minimo sul tempo di transpilazione a questa scala. La logica di routing principale di SABRE è altamente ottimizzata (implementata in gran parte in Rust). Il transpiler basato sull'intelligenza artificiale richiede un tempo notevolmente più lungo e la durata aumenta in base alle dimensioni del circuito, anche se i tempi assoluti rimangono ragionevoli per un utilizzo interattivo.
Passaggio 3: eseguire utilizzando Qiskit primitives
Per valutare l'impatto della transpilazione sulla fedeltà del circuito, costruire circuiti speculari a partire dal caso a 10 qubit ed eseguirli sul simulatore Aer con un modello di rumore semplice. L'output atteso di un circuito a specchio è sempre una stringa di bit composta interamente da zeri; pertanto, la probabilità di rilevare un e dimostra in che misura ciascuna strategia di transpilazione preservi la fedeltà.
# 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()}")Output:
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} "
f"({counts.get(all_zeros, 0)}/{shots})"
)Output:
Default P(|00...0>) = 0.8460 (8460/10000)
AI P(|00...0>) = 0.8121 (8121/10000)
Abbiamo eseguito entrambi i circuiti a specchio nel simulatore Aer utilizzando un semplice modello di rumore depolarizzante. La probabilità di sopravvivenza, definita come la frazione di tentativi che restituiscono la stringa di bit composta interamente da zeri, quantifica la quantità di rumore introdotta da ciascuna strategia di transpilazione.
Fase 4: Post-elaborazione e restituzione del risultato nel formato classico desiderato
Calcoliamo la probabilità di ottenere una stringa di bit composta interamente da zeri in entrambe le serie di misurazioni. Una maggiore probabilità di sopravvivenza indica una maggiore fedeltà, il che significa che la trascrizione ha introdotto meno rumore. Il grafico sottostante mostra il complemento, 1 - P(|0...0>), in modo che una barra più bassa indichi una maggiore fedeltà e che le piccole differenze di errore siano più facilmente individuabili.
# 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()Output:
In questo caso, il transpiler predefinito ha generato un circuito sia meno profondo che più piccolo per questa specifica istanza a 10 qubit, pertanto ci si aspetta che presenti una fedeltà maggiore. I risultati variano a seconda del circuito: come mostra la tabella riassuntiva qui sopra, il vantaggio offerto dal transpiler basato sull’intelligenza artificiale consiste in una profondità media inferiore a due qubit, non in ogni singolo circuito. La strategia che garantisce una maggiore fedeltà dipende dall'entità della differenza in ciascuna metrica, dalle caratteristiche di rumore dell'hardware e dalla struttura del circuito. In un modello di rumore depolarizzante uniforme, il numero totale di gate ha spesso un impatto più diretto sull’errore accumulato rispetto alla sola profondità.
Esempio di hardware su larga scala
Passaggi da 1 a 4
Qui tutti questi dettagli vengono integrati in un flusso di lavoro chiaro su scala più ampia, che viene poi eseguito su hardware quantistico reale.
Il codice riportato di seguito genera 25 circuiti casuali con profondità 8, in cui il numero di qubit varia da 26 a 50. Questi circuiti vengono quindi transpilati utilizzando entrambe le strategie e vengono raccolte le stesse metriche. Quindi costruiamo circuiti speculari partendo dal caso a 26 qubit e li inviamo al backend reale.
# -------------------------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 "
f"from {qubit_range_hw[0]} to {qubit_range_hw[-1]}"
)Output:
Created 25 circuits with qubit counts from 26 to 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)Output:
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")Output:
# -------------------------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()}, "
f"gates {mirror_default_hw.size()}"
)
print(
f"Mirror circuit (AI): depth {mirror_ai_hw.depth()}, "
f"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()}")Output:
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} "
f"({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()Output:
Default P(|00...0>) = 0.0005 (239/500000)
AI P(|00...0>) = 0.0050 (2516/500000)
Analisi dei risultati
I risultati su larga scala confermano le tendenze osservate nell'esempio su piccola scala, ora in un contesto più impegnativo.
Profondità a due qubit: il transpiler basato sull’intelligenza artificiale continua a garantire una profondità a due qubit notevolmente inferiore su tutta la gamma di dimensioni dei circuiti. L'ottimizzazione della profondità è uno degli obiettivi principali su cui è addestrato il modello di routing basato sull'intelligenza artificiale, e il vantaggio risulta più evidente con un numero maggiore di qubit, quando il problema di routing diventa più complesso per i metodi euristici.
Numero di porte: il transpiler predefinito (SABRE) produce costantemente circuiti con un numero inferiore di porte per tutte le dimensioni dei circuiti comprese in questo intervallo. L'euristica di SABRE è stata progettata specificatamente per ridurre al minimo il numero di porte logiche e, su questa scala, il vantaggio è evidente e uniforme.
Tempo di traspilazione: il divario nel tempo di traspilazione aumenta alle scale più grandi. Il tempo di esecuzione di SABRE rimane pressoché costante, mentre quello del transpiler basato sull'intelligenza artificiale cresce in modo più marcato. Ciononostante, il runtime del transpiler basato sull'intelligenza artificiale rimane una soluzione pratica per la maggior parte dei flussi di lavoro.
Fidelità del circuito a specchio: entrambi i metodi producono probabilità di sopravvivenza ben inferiori all'1% a questa scala, lasciando poco segnale utilizzabile. Con un numero totale di porte pari a circa 10.000 e una profondità a due qubit superiore a 1.000, il rumore di depolarizzazione accumulato nel circuito a specchio sovrasta la maggior parte del segnale. Ciò evidenzia un limite fondamentale dell'approccio basato sui circuiti a specchio: sebbene sia semplice e non richieda alcuna simulazione classica, non si adatta bene a circuiti di grandi dimensioni o profondi, dove entrambi i metodi vengono spinti vicino alla soglia di rumore e il debole segnale residuo è dominato dall'errore accumulato.
Sebbene questi risultati mettano in evidenza l'efficacia del transpiler basato sull'intelligenza artificiale, è importante sottolinearne i limiti. Il metodo di sintesi basato sull'intelligenza artificiale è attualmente disponibile solo per alcune mappe di accoppiamento, il che potrebbe limitarne l'applicabilità su più ampia scala. È opportuno tenere conto di questa limitazione nel valutare il suo impiego in diversi scenari.
Passi successivi
Se questo lavoro ti è sembrato interessante, potrebbero interessarti anche i seguenti contenuti: