Zum Hauptinhalt springe

Eiführung in de Qiskit KI-gstützte Transpiler-Service

Gschätzte QPU-Nutzung: Koi (HINWEIS: Des Tutorial führt koi Jobs aus, weil's sich uf Transpilation fokussiert)

Hintergrund

Dr Qiskit KI-gstützte Transpiler-Service (QTS) führt maschinelles-Lernen-basierti Optimierunge sowohl in Routing- als au in Synthesis-Passes ei. Die KI-Modi sind entwickelt worre, um d' Ischränkunge von dr traditionelle Transpilation azgehe, insbesondere für große Schaltunge und komplexe Hardware-Topologie.

Ab Juli 2025 isch dr Transpiler-Service zur neie IBM Quantum® Platform migriert worre und isch ned mehr verfügbar. Für d' neuschte Updates zum Status vom Transpiler-Service verweise mir uf d' Transpiler-Service-Dokumentation. Se könnet den KI-Transpiler weiterhin lokal verwende, ähnlich wie bei dr Standard-Qiskit-Transpilation. Ersetzet eifach generate_preset_pass_manager() durch generate_ai_pass_manager(). Die Funktion konstruiert an Pass-Manager, wo d' KI-gstützten Routing- und Synthesis-Passes direkt in Eiere lokale Transpilations-Workflow integriert.

Hauptmerkmal von de KI-Passes

  • Routing-Passes: KI-gstützts Routing ka Qubit-Pfad dynamisch basierend uf d' spezifische Schaltung und s' Backend apasse und de Bedarf a übermäßige SWAP-Gates reduziere.

    • AIRouting: Layout-Auswahl und Schaltungs-Routing
  • Synthesis-Passes: KI-Technike optimiere d' Zerlegung von Multi-Qubit-Gates und minimiere d' Anzahl von de Zwei-Qubit-Gates, wo typischerweise anfälliger für Fehler sind.

    • AICliffordSynthesis: Clifford-Gate-Synthese
    • AILinearFunctionSynthesis: Synthese von Linear-Funktionsschaltunge
    • AIPermutationSynthesis: Synthese von Permutationsschaltunge
    • AIPauliNetworkSynthesis: Synthese von Pauli-Netzwerkschaltunge (nur im Qiskit Transpiler Service verfügbar, ned in dr lokale Umgebung)
  • Vergleich mit traditioneller Transpilation: Dr Standard-Qiskit-Transpiler isch a robustes Werkzeug, wo a breits Spektrum von Quanteschaltunge effektiv handhabe ka. Wenn Schaltunge aber größer werre oder Hardware-Konfiguratione komplexer werre, könnet KI-Passes zusätzliche Optimierungsgewinn liefere. Durch d' Verwendung von glernde Modelle für Routing und Synthese verfeinert QTS Schaltungslayouts weiter und reduziert de Overhead für herausfordernde oder groß angelegte Quanteaufgabe.

Des Tutorial evaluiert d' KI-Modi unter Verwendung sowohl von Routing- als au von Synthesis-Passes und vergleicht d' Ergebnis mit traditioneller Transpilation, um hervorzuhebe, wo KI Leistungsvorteile bietet.

Weitere Details zu de verfügbare KI-Passes findet ihr in dr KI-Passes-Dokumentation.

Warum KI für Quanteschaltungs-Transpilation verwende?

Weil Quanteschaltunge in Größ und Komplexität zunehmet, hend traditionelle Transpilationsmethode Schwierigkeite, Layouts zu optimiere und Gate-Anzahle effizient zu reduziere. Größere Schaltunge, insbesondere solche mit Hunderte von Qubits, stelle erhebliche Herausforderunge an s' Routing und d' Synthese dar, wege Gerätebeschränkunge, begrenzter Konnektivität und Qubit-Fehlerraten.

Do bietet d' KI-gstützte Transpilation a potenzielle Lösung. Durch d' Nutzung von maschinelle Lerntechnike ka dr KI-gstützte Transpiler in Qiskit gscheitere Entscheidunge über Qubit-Routing und Gate-Synthese treffe, was zu besserer Optimierung von groß angelegte Quanteschaltunge führt.

Kurze Benchmarking-Ergebnis

Graph showing AI transpiler performance against Qiskit

In Benchmarking-Tests hend der KI-Transpiler konsistent flachere Schaltunge höherer Qualität im Vergleich zum Standard-Qiskit-Transpiler produziert. Für die Tests hend mir d' Standard-Pass-Manager-Strategie von Qiskit verwendet, konfiguriert mit [generate_preset_passmanager]. Während die Standardstrategie oft effektiv isch, ka sie bei größere oder komplexere Schaltunge Schwierigkeite hend. Im Gegensatz dazu hend KI-gstützte Passes a durchschnittliche Reduzierung von dr Zwei-Qubit-Gate-Anzahl um 24% und a Reduzierung von dr Schaltungstiefe um 36% für große Schaltunge (100+ Qubits) bei dr Transpilation uf d' Heavy-Hex-Topologie von IBM Quantum Hardware erreicht. Weitere Informationne zu die Benchmarks findet ihr in dem Blog.

Des Tutorial untersucht d' wichtigschte Vorteile von de KI-Passes und wie se sich mit traditionelle Methode vergleicht.

# Added by doQumentation — installs packages not in the Binder environment
!pip install -q qiskit-ibm-transpiler
# This cell is hidden from users;
# it just disables a linting rule.
# ruff: noqa: F811

Aforderunge

Stellt vor dem Beginn von dem Tutorial sicher, dass ihr Folgendes installiert hend:

  • Qiskit SDK v1.0 oder höher, mit Unterstützung für Visualisierung
  • Qiskit Runtime (pip install qiskit-ibm-runtime) v0.22 oder höher
  • Qiskit IBM® Transpiler mit KI-Lokalmodus(pip install 'qiskit-ibm-transpiler[ai-local-mode]')

Setup

from qiskit import QuantumCircuit
from qiskit.circuit.library import efficient_su2, PermutationGate
from qiskit.synthesis.qft import synth_qft_full
from qiskit.circuit.random import random_circuit, random_clifford_circuit
from qiskit.transpiler import generate_preset_pass_manager, CouplingMap
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_transpiler import generate_ai_pass_manager
from qiskit.synthesis.permutation import (
synth_permutation_depth_lnn_kms,
synth_permutation_basic,
)
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import time
import logging

seed = 42

# Used for generating permutation circuits in part two for comparison
def generate_permutation_circuit(width, pattern):
circuit = QuantumCircuit(width)
circuit.append(
PermutationGate(pattern=pattern),
qargs=range(width),
)
return circuit

# Creates a Bernstein-Vazirani circuit given the number of qubits
def create_bv_circuit(num_qubits):
qc = QuantumCircuit(num_qubits, num_qubits - 1)
qc.x(num_qubits - 1)
qc.h(qc.qubits)
for i in range(num_qubits - 1):
qc.cx(i, num_qubits - 1)
qc.h(qc.qubits[:-1])
return qc

# Transpile a circuit with a given pass manager and return metrics
def transpile_with_metrics(pass_manager, circuit):
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": elapsed,
}

# Used for collecting metrics for part 3 of synthesis methods
def synth_transpile_with_metrics(qc, pm, pattern_id, method):
start = time.time()
qc = pm.run(qc)
elapsed = time.time() - start

return {
"Pattern": pattern_id,
"Method": method,
"Depth (2Q)": qc.depth(lambda x: x.operation.num_qubits == 2),
"Gates": qc.size(),
"Time (s)": elapsed,
}

# Ignore logs like "INFO:qiskit_ibm_transpiler.wrappers.ai_local_synthesis:Running Linear Functions AI synthesis on local mode"

logging.getLogger(
"qiskit_ibm_transpiler.wrappers.ai_local_synthesis"
).setLevel(logging.WARNING)

Teil I. Qiskit-Muster

Jetzt schaue mir uns a, wie mr de KI-Transpiler-Service mit anr einfache Quanteschaltung unter Verwendung von Qiskit-Muster verwendet. Dr Schlüssel isch d' Erstellung von am PassManager mit generate_ai_pass_manager() anstelle vom Standard generate_preset_pass_manager().

Schritt 1: Klassische Eigabe uf a Quanteproblem abbilden

In dem Abschnitt teste mir de KI-Transpiler a dr efficient_su2-Schaltung, am weit verbreitet hardwareeffizienten Ansatz. Die Schaltung isch besonders relevant für variationelle Quantealgorithme (zum Beispiel VQE) und Quantum-Machine-Learning-Aufgabe, was sie zu am ideale Testfall für d' Bewertung von dr Transpilationsleistung macht.

D' efficient_su2-Schaltung besteht aus abwechselnde Schichte von Ei-Qubit-Rotationne und verschränkende Gates wie CNOTs. Die Schichte ermögliche a flexible Erkundung vom Quantezustandsraum, während d' Gate-Tiefe überschaubar bleibt. Durch Optimierung von der Schaltung welle mir d' Gate-Anzahl reduziere, d' Fidelität verbessere und Rausche minimiere. Des macht sie zu am starke Kandidate zum Teste von dr Effizienz vom KI-Transpilers.

# For our transpilation, we will use a large circuit of 101 qubits
qc = efficient_su2(90, entanglement="circular", reps=1).decompose()

# Draw a smaller version of the circuit to get a visual representation
qc_small = efficient_su2(5, entanglement="circular", reps=1).decompose()
qc_small.draw(output="mpl")

Output of the previous code cell

Schritt 2: Problem für d' Ausführung uf Quantehardware optimiere

A Backend auswähle

Für des Beispiel wähle mir s' am wenigschte ausgelastete betriebsbereite IBM Quantum Backend, wo koi Simulator isch und mindestens 100 Qubits hend:

Hinweis: Weil sich s' am wenigschte ausgelastete Backend im Laufe von dr Zeit ändern ka, könnet für verschiedene Durchläuf unterschiedliche Geräte ausgewählt werre. Gerätespezifische Eigenschafte, wie Coupling-Maps, könnet zu Unterschied in de transpilierten Schaltunge führe.

service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=100
)
cm = backend.coupling_map
print(f"Using backend: {backend.name}")
Using backend: ibm_torino

KI- und traditionelle Pass-Manager erstelle

Um d' Effektivität vom KI-Transpilers zu bewerte, führe mir zwoi Transpilationsläuf durch. Zerscht transpiliere mir d' Schaltung mit dem KI-Transpiler. Na führe mir an Vergleich durch, indem mir dieselb Schaltung ohne de KI-Transpiler mit traditionelle Methode transpiliere. Beidne Transpilationsprozesse verwende dieselb Coupling-Map vom gwählt Backend und s' Optimierungslevel wird uf 3 gesetzt, für an fairen Vergleich.

Beidne Methode spiegle de Standardansatz zur Erstellung von PassManager-Instanze zur Transpilation von Schaltunge in Qiskit wider.

pm_ai = generate_ai_pass_manager(
optimization_level=3,
ai_optimization_level=3,
coupling_map=cm,
include_ai_synthesis=True, # used for part 3 when comparing synthesis methods
)

pm_no_ai = generate_preset_pass_manager(
optimization_level=3,
coupling_map=cm,
seed_transpiler=seed, # note that the AI pass manager does not currently support seeding
)

Transpilieret d' Schaltunge und zeichnet d' Zeite uf.

# Transpile using standard (non-AI) pass manager
_, metrics_no_ai = transpile_with_metrics(pm_no_ai, qc)
print(
f"Standard transpilation: Depth (2q) {metrics_no_ai['depth_2q']}, "
f"Gate count {metrics_no_ai['gate_count']}, Time {metrics_no_ai['time_s']}"
)

# Transpile using AI pass manager
_, metrics_ai = transpile_with_metrics(pm_ai, qc)
print(
f"AI transpilation : Depth (2q) {metrics_ai['depth_2q']}, "
f"Gate count {metrics_ai['gate_count']}, Time {metrics_ai['time_s']}"
)
Standard transpilation: Depth (2q) 95, Gate count 458, Time 0.04650712013244629
AI transpilation : Depth (2q) 90, Gate count 456, Time 0.9342479705810547

In dem Test vergleiche mir d' Leistung vom KI-Transpiler und von dr Standard-Transpilationsmethode a dr efficient_su2-Schaltung. Dr KI-Transpiler erreicht a merklich flachere Schaltungstiefe bei ähnlicher Gate-Anzahl.

  • Schaltungstiefe: Dr KI-Transpiler produziert a Schaltung mit geringerer Zwei-Qubit-Tiefe. Des isch zu erwarte, weil d' KI-Passes drauf trainiert sind, d' Tiefe zu optimiere, indem sie Qubit-Interaktionsmuster lerne und Hardware-Konnektivität effektiver als regelbasierti Heuristike ausnutze.

  • Gate-Anzahl: D' Gesamt-Gate-Anzahl bleibt zwischen de zwoi Methode ähnlich. Des entspricht de Erwartunge, weil d' Standard-SABRE-basierte Transpilation explizit d' Swap-Anzahl minimiert, wo de Gate-Overhead dominiert. Dr KI-Transpiler priorisiert stattdessen d' Gesamttiefe und ka gelegentlich a paar zusätzliche Gates für an kürzere Ausführungspfad ituusche.

  • Transpilationszeit: Dr KI-Transpiler braucht mehr Zeit als d' Standardmethode. Des liegt a de zusätzliche Rechekoste für s' Aufrufe von glernde Modelle während vom Routing und dr Synthese. Im Gegensatz dazu isch dr SABRE-basierte Transpiler jetzt nach Neufassung und Optimierung in Rust deutlich schneller und bietet hocheffizients heuristische Routing im großen Maßstab.

's isch wichtig z'beachte, dass die Ergebnis nur uf anr Schaltung basiere. Um a umfassendes Verständnis davon z'kriege, wie sich dr KI-Transpiler im Vergleich zu traditionelle Methode verhält, isch es nötig, a Vielzahl von Schaltunge z'teste. D' Leistung von QTS ka je nach Art von dr zu optimierende Schaltung stark variiere. Für an breiteren Vergleich verweise mir uf d' obige Benchmarks oder besuchet de Blog.

Schritt 3: Ausführung mit Qiskit Primitives

Weil sich des Tutorial uf Transpilation konzentriert, werre koi Experimente uf em Quantegerät ausgeführt. S' Ziel isch es, d' Optimierunge aus Schritt 2 z'nutze, um a transpilierte Schaltung mit reduzierter Tiefe oder Gate-Anzahl z'kriege.

Schritt 4: Nachbearbeitung und Rückgab vom Ergebnis im gwünschte klassische Format

Weil's koi Ausführung für des Notebook git, git's koi Ergebnis zur Nachbearbeitung.

Teil II. Analyse und Benchmarking von de transpilierten Schaltunge

In dem Abschnitt zeige mir, wie mr d' transpilierte Schaltung analysiert und detaillierter mit dr Originalversion vergleicht. Mir konzentriere uns uf Metrike wie Schaltungstiefe, Gate-Anzahl und Transpilationszeit, um d' Effektivität von dr Optimierung z'bewerte. Zusätzlich diskutiere mir, wie d' Ergebnis über verschiedene Schaltungstyp hinweg variiere könnet, und biete Einblick in d' breiter Leistung vom Transpiler über verschiedene Szenarios hinweg.

# Circuits to benchmark
seed = 42
circuits = [
{
"name": "Random",
"qc": random_circuit(num_qubits=30, depth=10, seed=seed),
},
{
"name": "Clifford",
"qc": random_clifford_circuit(
num_qubits=40, num_gates=200, seed=seed
),
},
{
"name": "QFT",
"qc": synth_qft_full(num_qubits=20, do_swaps=False).decompose(),
},
{
"name": "BV",
"qc": create_bv_circuit(40),
},
]

results = []

# Run the transpilation for each circuit and store the results
for circuit in circuits:
qc_no_ai, metrics_no_ai = transpile_with_metrics(pm_no_ai, circuit["qc"])
qc_ai, metrics_ai = transpile_with_metrics(pm_ai, circuit["qc"])

print("Completed transpilation for", circuit["name"])

results.append(
{
"Circuit": circuit["name"],
"Depth 2Q (No AI)": metrics_no_ai["depth_2q"],
"Gate Count (No AI)": metrics_no_ai["gate_count"],
"Time (No AI)": metrics_no_ai["time_s"],
"Depth 2Q (AI)": metrics_ai["depth_2q"],
"Gate Count (AI)": metrics_ai["gate_count"],
"Time (AI)": metrics_ai["time_s"],
}
)

df = pd.DataFrame(results)
df
Completed transpilation for Random
Completed transpilation for Clifford
Completed transpilation for QFT
Completed transpilation for BV
Circuit  Depth 2Q (No AI)  Gate Count (No AI)  Time (No AI)  \
0 Random 37 221 0.039347
1 Clifford 36 232 0.036633
2 QFT 165 924 0.077458
3 BV 65 155 0.024993

Depth 2Q (AI) Gate Count (AI) Time (AI)
0 24 181 0.773718
1 43 267 1.097431
2 130 913 3.660771
3 70 155 0.345522

Durchschnittliche prozentuale Reduzierung für jedi Metrik. Positive sind Verbesserunge, negative sind Verschlechterunge.

# Average reduction from non-AI to AI transpilation as a percentage
avg_reduction_depth = (
(df["Depth 2Q (No AI)"] - df["Depth 2Q (AI)"]).mean()
/ df["Depth 2Q (No AI)"].mean()
* 100
)
avg_reduction_gates = (
(df["Gate Count (No AI)"] - df["Gate Count (AI)"]).mean()
/ df["Gate Count (No AI)"].mean()
* 100
)
avg_reduction_time = (
(df["Time (No AI)"] - df["Time (AI)"]).mean()
/ df["Time (No AI)"].mean()
* 100
)

print(f"Average reduction in depth: {avg_reduction_depth:.2f}%")
print(f"Average reduction in gate count: {avg_reduction_gates:.2f}%")
print(f"Average reduction in transpilation time: {avg_reduction_time:.2f}%")
Average reduction in depth: 11.88%
Average reduction in gate count: 1.04%
Average reduction in transpilation time: -3193.95%
fig, axs = plt.subplots(1, 3, figsize=(21, 6))
df.plot(
x="Circuit",
y=["Depth 2Q (No AI)", "Depth 2Q (AI)"],
kind="bar",
ax=axs[0],
)
axs[0].set_title("Circuit Depth Comparison")
axs[0].set_ylabel("Depth")
axs[0].set_xlabel("Circuit")
axs[0].tick_params(axis="x", rotation=45)
df.plot(
x="Circuit",
y=["Gate Count (No AI)", "Gate Count (AI)"],
kind="bar",
ax=axs[1],
)
axs[1].set_title("Gate Count Comparison")
axs[1].set_ylabel("Gate Count")
axs[1].set_xlabel("Circuit")
axs[1].tick_params(axis="x", rotation=45)
df.plot(x="Circuit", y=["Time (No AI)", "Time (AI)"], kind="bar", ax=axs[2])
axs[2].set_title("Time Comparison")
axs[2].set_ylabel("Time (seconds)")
axs[2].set_xlabel("Circuit")
axs[2].tick_params(axis="x", rotation=45)
fig.suptitle(
"Benchmarking AI transpilation vs Non-AI transpilation for various circuits"
)

plt.tight_layout()
plt.show()

Output of the previous code cell

D' Leistung vom KI-Transpilers variiert je nach Art von dr zu optimierende Schaltung erheblich. In manchen Fäll erreicht er bemerkenswerte Reduzierunge von dr Schaltungstiefe und Gate-Anzahl im Vergleich zum Standard-Transpiler. Die Verbesserunge gehe aber oft mit anr erhebliche Erhöhung von dr Laufzeit einher.

Für bestimmte Schaltungstyp ka dr KI-Transpiler a bissl bessere Ergebnis bezüglich dr Schaltungstiefe erziehe, aber au zu anr Erhöhung von dr Gate-Anzahl und anr erhebliche Laufzeitstraf führe. Die Beobachtunge lege nahe, dass d' Vorteile vom KI-Transpilers ned bei alle Schaltungstyp einheitlich sind. Stattdessen hängt sei Effektivität von de spezifische Eigenschafte von dr Schaltung ab, was en für mancher Anwendungsfäll besser geeignet macht als für andere.

Wenn solltet Benutzer KI-gstützte Transpilation wähle?

Dr KI-gstützte Transpiler in Qiskit glänzt in Szenarios, wo traditionelle Transpilationsmethode Schwierigkeite hend, insbesondere bei groß angelegte und komplexe Quanteschaltunge. Für Schaltunge mit Hunderte von Qubits oder solche, wo uf Hardware mit komplizierte Coupling-Maps abzielet, bietet dr KI-Transpiler überlegene Optimierung bezüglich Schaltungstiefe, Gate-Anzahl und Laufzeiteffizienz. In Benchmarking-Tests hend er traditionelle Methode konsistent übertroffe und deutlich flachere Schaltunge geliefert und Gate-Anzahle reduziert, was für d' Verbesserung von dr Leistung und d' Minderung von Rausche uf echter Quantehardware entscheidend isch.

Benutzer sollet KI-gstützte Transpilation in Betracht ziehe, wenn sie mit:

  • Große Schaltunge arbeite, wo traditionelle Methode de Maßstab ned effizient handhabe könnet.
  • Komplexe Hardware-Topologie, wo Gerätekonnektivität und Routing-Herausforderunge uftrette.
  • Leistungssensitive Awwendunge, wo d' Reduzierung von dr Schaltungstiefe und d' Verbesserung von dr Fidelität von größter Bedeutung sind.

Teil III. Erkundung von dr KI-gstützten Permutationsnetzwerk-Synthese

Permutationsnetzwerk sind grundlegend im Quantencomputing, insbesondere für Systeme, wo durch ischränkte Topologie beschränkt sind. Die Netzwerk erleichtern Langstreckeninteraktionne, indem sie Qubits dynamisch tausche, um All-to-All-Konnektivität uf Hardware mit begrenzter Konnektivität nachzuahme. Solche Transformationne sind für d' Implementierung komplexer Quantealgorithme uf kurzfristige Geräte unerlässlich, wo Interaktionne oft über nächste Nachbarn hinusgehen.

In dem Abschnitt hebe mir d' Synthese von Permutationsnetzwerk als überzeugende Awwendung für de KI-gstützte Transpiler in Qiskit hervor. Insbesondere nutzt dr AIPermutationSynthesis-Pass KI-gesteuerte Optimierung, um effiziente Schaltunge für Qubit-Permutationsaufgabe zu generiere. Im Gegensatz dazu hend generische Synthese-Ansätz oft Schwierigkeite, Gate-Anzahl und Schaltungstiefe azubalanciere, insbesondere in Szenarios mit dichte Qubit-Interaktionne oder beim Versuch, volle Konnektivität z'erreiche.

Mir werre a Qiskit-Musterbeispiel durchgehe, wo d' Synthese von am Permutationsnetzwerk zeigt, um All-to-All-Konnektivität für an Satz von Qubits z'erreiche. Mir werre d' Leistung von AIPermutationSynthesis mit de Standard-Synthesemethode in Qiskit vergleiche. Des Beispiel wird zeige, wie dr KI-Transpiler für geringere Schaltungstiefe und Gate-Anzahl optimiert und sei Vorteile in praktische Quanten-Workflows hervorhebt. Um de KI-Synthese-Pass z'aktiviere, verwende mir d' Funktion generate_ai_pass_manager() mit dem Parameter include_ai_synthesis uf True gesetzt.

Schritt 1: Klassische Eigabe uf a Quanteproblem abbilden

Um a klassischs Permutationsproblem uf am Quantencomputer darzustelle, fange mir mit dr Definition von dr Struktur von de Quanteschaltunge a. Für des Beispiel:

  1. Quanteschaltungs-Initialisierung: Mir weise 27 Qubits zu, um zum Backend z'passe, wo mir verwende werre, des 27 Qubits hend.

  2. Permutationne awende: Mir generiere zehn zufällige Permutationsmuster (pattern_1 bis pattern_10) unter Verwendung von am feste Seeds für Reproduzierbarkeit. Jedes Permutationsmuster wird uf a separate Quanteschaltung awende (qc_1 bis qc_10).

  3. Schaltungszerlegung: Jede Permutationsoperation wird in native Gate-Sets zerlegt, wo mit dr Ziel-Quantehardware kompatibel sind. Mir analysiere d' Tiefe und d' Anzahl von de Zwei-Qubit-Gates (nichtlokale Gates) für jedi zerlegte Schaltung.

D' Ergebnis gebe Einblick in d' Komplexität von dr Darstellung klassischer Permutationsprobleme uf am Quantegerät und demonstriere d' Ressourcenanforderunge für verschiedene Permutationsmuster.

# Parameters
width = 27
num_circuits = 10

# Set random seed
np.random.seed(seed)

# Generate random patterns and circuits
patterns = [
np.random.permutation(width).tolist() for _ in range(num_circuits)
]
circuits = {
f"qc_{i}": generate_permutation_circuit(width, pattern)
for i, pattern in enumerate(patterns, start=1)
}

# Display one of the circuits
circuits["qc_1"].decompose(reps=3).draw(output="mpl", fold=-1)

Output of the previous code cell

Schritt 2: Problem für d' Ausführung uf Quantehardware optimiere

In dem Schritt fahre mir mit dr Optimierung unter Verwendung von de KI-Synthese-Passes fort.

Für d' KI-Synthese-Passes braucht dr PassManager nur d' Coupling-Map vom Backend. 's isch aber wichtig z'beachte, dass ned alli Coupling-Maps kompatibel sind; nur diejenige, uf dene dr AIPermutationSynthesis-Pass trainiert worre isch, werret funktioniere. Aktuell unterstützt dr AIPermutationSynthesis-Pass Blöck von de Größe 65, 33 und 27 Qubits. Für des Beispiel verwende mir a 27-Qubit-QPU.

Zum Vergleich werre mir d' Leistung von dr KI-Synthese gegen generische Permutations-Synthesemethode in Qiskit evaluiere, einschließlich:

  • synth_permutation_depth_lnn_kms: Die Methode synthetisiert a Permutationsschaltung für a lineare Nächste-Nachbar-(LNN)-Architektur unter Verwendung vom Kutin-, Moulton- und Smithline-(KMS)-Algorithmus. Sie garantiert a Schaltung mit anr Tiefe von höchstens nn und anr Größ von höchstens n(n1)/2n(n-1)/2, wobei sowohl Tiefe als au Größ in Bezug uf SWAP-Gates gemesse werre.

  • synth_permutation_basic: Des isch a einfache Implementierung, wo Permutationsschaltunge synthetisiert, ohne Beschränkunge für Konnektivität oder Optimierung für spezifische Architekturen aufzuerlege. Sie dient als Basislinie für de Vergleich von dr Leistung mit fortgeschrittene Methode.

Jedi von de Methode repräsentiert an eigene Ansatz zur Synthese von Permutationsnetzwerk und bietet an umfassende Benchmark gegen d' KI-gstützten Methode.

Weitere Details zu Synthesemethode in Qiskit findet ihr in dr Qiskit-API-Dokumentation.

Definiert d' Coupling-Map, wo d' 27-Qubit-QPU repräsentiert.

coupling_map = [
[1, 0],
[2, 1],
[3, 2],
[3, 5],
[4, 1],
[6, 7],
[7, 4],
[7, 10],
[8, 5],
[8, 9],
[8, 11],
[11, 14],
[12, 10],
[12, 13],
[12, 15],
[13, 14],
[16, 14],
[17, 18],
[18, 15],
[18, 21],
[19, 16],
[19, 22],
[20, 19],
[21, 23],
[23, 24],
[25, 22],
[25, 24],
[26, 25],
]
CouplingMap(coupling_map).draw()

Output of the previous code cell

Transpilieret jedi von de Permutationsschaltunge unter Verwendung von de KI-Synthese-Passes und generische Synthesemethode.

results = []
pm_no_ai_synth = generate_preset_pass_manager(
coupling_map=cm,
optimization_level=1, # set to 1 since we are using the synthesis methods
)

# Transpile and analyze all circuits
for i, (qc_name, qc) in enumerate(circuits.items(), start=1):
pattern = patterns[i - 1] # Get the corresponding pattern

qc_depth_lnn_kms = synth_permutation_depth_lnn_kms(pattern)
qc_basic = synth_permutation_basic(pattern)

# AI synthesis
results.append(
synth_transpile_with_metrics(
qc.decompose(reps=3),
pm_ai,
qc_name,
"AI",
)
)

# Depth-LNN-KMS Method
results.append(
synth_transpile_with_metrics(
qc_depth_lnn_kms.decompose(reps=3),
pm_no_ai_synth,
qc_name,
"Depth-LNN-KMS",
)
)

# Basic Method
results.append(
synth_transpile_with_metrics(
qc_basic.decompose(reps=3),
pm_no_ai_synth,
qc_name,
"Basic",
)
)

results_df = pd.DataFrame(results)

Zeichnet d' Metrike (Tiefe, Gate-Anzahl, Zeit) für jedi Schaltung nach dr Transpilation uf.

# Calculate averages for each metric
average_metrics = results_df.groupby("Method")[
["Depth (2Q)", "Gates", "Time (s)"]
].mean()
average_metrics = average_metrics.round(3) # Round to two decimal places
print("\n=== Average Metrics ===")
print(average_metrics)

# Identify the best non-AI method based on least average depth
non_ai_methods = [
method for method in results_df["Method"].unique() if method != "AI"
]
best_non_ai_method = average_metrics.loc[non_ai_methods][
"Depth (2Q)"
].idxmin()
print(
f"\nBest Non-AI Method (based on least average depth): {best_non_ai_method}"
)

# Compare AI to the best non-AI method
ai_metrics = average_metrics.loc["AI"]
best_non_ai_metrics = average_metrics.loc[best_non_ai_method]

comparison = {
"Metric": ["Depth (2Q)", "Gates", "Time (s)"],
"AI": [
ai_metrics["Depth (2Q)"],
ai_metrics["Gates"],
ai_metrics["Time (s)"],
],
best_non_ai_method: [
best_non_ai_metrics["Depth (2Q)"],
best_non_ai_metrics["Gates"],
best_non_ai_metrics["Time (s)"],
],
"Improvement (AI vs Best Non-AI)": [
ai_metrics["Depth (2Q)"] - best_non_ai_metrics["Depth (2Q)"],
ai_metrics["Gates"] - best_non_ai_metrics["Gates"],
ai_metrics["Time (s)"] - best_non_ai_metrics["Time (s)"],
],
}

comparison_df = pd.DataFrame(comparison)
print("\n=== Comparison of AI vs Best Non-AI Method ===")
comparison_df
=== Average Metrics ===
Depth (2Q) Gates Time (s)
Method
AI 23.9 82.8 0.248
Basic 29.8 91.0 0.012
Depth-LNN-KMS 70.8 531.6 0.017

Best Non-AI Method (based on least average depth): Basic

=== Comparison of AI vs Best Non-AI Method ===
Metric      AI   Basic  Improvement (AI vs Best Non-AI)
0 Depth (2Q) 23.900 29.800 -5.900
1 Gates 82.800 91.000 -8.200
2 Time (s) 0.248 0.012 0.236

D' Ergebnis zeige, dass dr KI-Transpiler alli andere Qiskit-Synthesemethode für den Satz zufälliger Permutationsschaltunge übertrifft. Wichtige Erkenntnisse umfasse:

  1. Tiefe: Dr KI-Transpiler erreicht d' niedrigschte durchschnittliche Tiefe, was uf überlegene Optimierung von Schaltungslayouts hinweist.
  2. Gate-Anzahl: Er reduziert d' Anzahl von de Gates im Vergleich zu andere Methode erheblich und verbessert d' Ausführungs-Fidelität und -Effizienz.
  3. Transpilationszeit: Alli Methode laufe uf der Skala sehr schnell, was sie praktisch einsetzbar macht. Dr KI-Transpiler hend aber a bemerkenswerte Laufzeiterhöhung im Vergleich zu traditionelle Methode wege dr Komplexität von de verwendete KI-Modelle.

Die Ergebnis etabliere de KI-Transpiler als de effektivschte Ansatz für den Benchmark, insbesondere für Tiefen- und Gate-Anzahl-Optimierung.

Stellet d' Ergebnis dar, um d' Leistung von de KI-Synthese-Passes mit de generische Synthesemethode z'vergleiche.

methods = results_df["Method"].unique()

fig, axs = plt.subplots(1, 3, figsize=(18, 5))

# Pivot the DataFrame and reorder columns to ensure AI is first
pivot_depth = results_df.pivot(
index="Pattern", columns="Method", values="Depth (2Q)"
)[["AI", "Depth-LNN-KMS", "Basic"]]
pivot_gates = results_df.pivot(
index="Pattern", columns="Method", values="Gates"
)[["AI", "Depth-LNN-KMS", "Basic"]]
pivot_time = results_df.pivot(
index="Pattern", columns="Method", values="Time (s)"
)[["AI", "Depth-LNN-KMS", "Basic"]]

pivot_depth.plot(kind="bar", ax=axs[0], legend=False)
axs[0].set_title("Circuit Depth Comparison")
axs[0].set_ylabel("Depth")
axs[0].set_xlabel("Pattern")
axs[0].tick_params(axis="x", rotation=45)
pivot_gates.plot(kind="bar", ax=axs[1], legend=False)
axs[1].set_title("2Q Gate Count Comparison")
axs[1].set_ylabel("Number of 2Q Gates")
axs[1].set_xlabel("Pattern")
axs[1].tick_params(axis="x", rotation=45)
pivot_time.plot(
kind="bar", ax=axs[2], legend=True, title="Legend"
) # Show legend on the last plot
axs[2].set_title("Time Comparison")
axs[2].set_ylabel("Time (seconds)")
axs[2].set_xlabel("Pattern")
axs[2].tick_params(axis="x", rotation=45)
fig.suptitle(
"Benchmarking AI Synthesis Methods vs Non-AI Synthesis Methods For Random Permutations Circuits",
fontsize=16,
y=1,
)

plt.tight_layout()
plt.show()

Output of the previous code cell

Des Diagramm hebt d' individuellen Ergebnis für jedi Schaltung (qc_1 bis qc_10) über verschiedene Synthesemethode hinweg hervor:

Während die Ergebnis d' Effektivität vom KI-Transpilers für Permutationsschaltunge unterstriche, isch es wichtig, sei Ischränkunge z'beachte. D' KI-Synthesemethode isch aktuell nur für bestimmte Coupling-Maps verfügbar, was ihre breiter Awwendbarkeit ischränke ka. Die Ischränkung sollet bei dr Bewertung von ihrer Verwendung in verschiedene Szenarios berücksichtigt werre.

Insgesamt zeigt dr KI-Transpiler vielversprechende Verbesserunge in dr Tiefen- und Gate-Anzahl-Optimierung für die spezifische Schaltunge bei vergleichbare Transpilationszeite.

Schritt 3: Ausführung mit Qiskit Primitives

Weil sich des Tutorial uf Transpilation konzentriert, werre koi Experimente uf em Quantegerät ausgeführt. S' Ziel isch es, d' Optimierunge aus Schritt 2 z'nutze, um a transpilierte Schaltung mit reduzierter Tiefe oder Gate-Anzahl z'kriege.

Schritt 4: Nachbearbeitung und Rückgab vom Ergebnis im gwünschte klassische Format

Weil's koi Ausführung für des Notebook git, git's koi Ergebnis zur Nachbearbeitung.

Tutorial-Umfrag

Bitte mached bei der kurze Umfrag mit, um Feedback zu dem Tutorial z'gebe. Eiere Erkenntnisse helfe uns, unser Inhaltsangebot und unser Benutzererfahrung z'verbessere.

Link zur Umfrag