Skip to main content
IBM Quantum Platform

Transpiler-Optimierungsstufe festlegen

  • Der Code auf dieser Seite wurde unter Berücksichtigung der folgenden Anforderungen entwickelt. Wir empfehlen die Verwendung dieser oder neuerer Versionen.

    qiskit[all]~=2.5.2
    qiskit-ibm-runtime~=0.47.0
    

Echte Quantenbauelemente sind mit Rauschen und Gatterfehlern behaftet, so dass eine Optimierung der Schaltungen zur Verringerung ihrer Tiefe und Gatteranzahl die Ergebnisse der Ausführung dieser Schaltungen erheblich verbessern kann. Die Funktion generate_preset_pass_manager funktion hat ein erforderliches Positionsargument, optimization_level, das steuert, wie viel Aufwand der Transpiler für die Optimierung von Schaltungen betreibt. Dieses Argument kann eine ganze Zahl mit einem der Werte 0, 1, 2 oder 3 sein. Höhere Optimierungsstufen erzeugen mehr optimierte Schaltungen auf Kosten einer längeren Kompilierzeit. In der folgenden Tabelle wird erläutert, welche Optimierungen mit den einzelnen Einstellungen vorgenommen werden.

Optimier.- stufe
Beschreibung
0

Keine Optimierung: typischerweise für die Charakterisierung von Hardware verwendet

  • Einfache Übersetzung
  • Layout/Routing: TrivialLayout es wählt die gleichen physischen Qubit-Nummern wie die virtuellen und fügt SWAPs ein, damit es funktioniert (unter SabreSwap)
1

Optimierung der Beleuchtung:

  • Layout/Routing: Das Layout wird zunächst mit TrivialLayout ausprobiert. Wenn zusätzliche SWAPs erforderlich sind, wird mit SabreSwap ein Layout mit einer minimalen Anzahl von SWAPs gefunden. Anschließend wird mit VF2LayoutPostLayout versucht, die besten Qubits im Graphen auszuwählen.
  • InverseCancellation
  • 1Q gate-Optimierung
2

Mittlere Optimierung:

  • Layout/Routing: Optimierungsstufe 1 (ohne Trivialität) + Heuristik optimiert mit größerer suchtiefe und Versuchen der Optimierungsfunktion. Da TrivialLayout nicht verwendet wird, wird nicht versucht, die gleichen physischen und virtuellen Qubit-Nummern zu verwenden.
  • CommutativeCancellation
3

Hohe Optimierung:

  • Optimierungsstufe 2 + Heuristik optimiert auf Layout/Routing weiter mit größerem Aufwand/Versuchen
  • Resynthese von Zwei-Qubit-Blöcken unter Verwendung der Cartan'schen KAK-Zerlegung.
  • Pässe, die die Einheitlichkeit durchbrechen:
    • OptimizeSwapBeforeMeasure: Verschiebt die Messungen, um SWAPs zu vermeiden
    • RemoveDiagonalGatesBeforeMeasure: Entfernt Gates vor den Messungen, die die Messungen nicht beeinflussen würden

Optimierungsstufe in Aktion

Da Zwei-Qubit-Gatter in der Regel die größte Fehlerquelle darstellen, können wir die "Hardware-Effizienz" der Transpilierung annähernd quantifizieren, indem wir die Anzahl der Zwei-Qubit-Gatter in der resultierenden Schaltung zählen. Hier werden wir die verschiedenen Optimierungsstufen an einer Eingangsschaltung ausprobieren, die aus einer zufälligen Unitary und einem SWAP-Gatter besteht.

from qiskit import QuantumCircuit
from qiskit.circuit.library import UnitaryGate
from qiskit.quantum_info import Operator, random_unitary

UU = random_unitary(4, seed=12345)
rand_U = UnitaryGate(UU)

qc = QuantumCircuit(2)
qc.append(rand_U, range(2))
qc.swap(0, 1)
qc.draw("mpl", style="iqp")

Output:

Output of the previous code cell
Note

In diesen Beispielen wird das FakeSherbrooke``qiskit_ibm_runtime Mock-Backend von verwendet, Sie können es jedoch mit jedem Qiskit-kompatiblen echten oder simulierten Backend ausprobieren. Ihre Ergebnisse können davon abweichen.

Zunächst führen wir die Transpilation mit der Optimierungsstufe 0 durch.

from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()

pass_manager = generate_preset_pass_manager(
    optimization_level=0, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Die transpilierte Schaltung hat sechs Zwei-Qubit-ECR-Gatter.

Wiederholen Sie den Vorgang für Optimierungsstufe 1:

from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

backend = FakeSherbrooke()

pass_manager = generate_preset_pass_manager(
    optimization_level=1, backend=backend, seed_transpiler=12345
)
qc_t1_exact = pass_manager.run(qc)
qc_t1_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Die transpilierte Schaltung hat immer noch sechs ECR-Gatter, aber die Anzahl der Ein-Qubit-Gatter hat sich verringert.

Wiederholen Sie den Vorgang für Optimierungsstufe 2:

pass_manager = generate_preset_pass_manager(
    optimization_level=2, backend=backend, seed_transpiler=12345
)
qc_t2_exact = pass_manager.run(qc)
qc_t2_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Dies führt zu den gleichen Ergebnissen wie Optimierungsstufe 1. Beachten Sie, dass eine Erhöhung des Optimierungsgrades nicht immer einen Unterschied macht.

Wiederholen Sie den Vorgang mit der Optimierungsstufe 3:

pass_manager = generate_preset_pass_manager(
    optimization_level=3, backend=backend, seed_transpiler=12345
)
qc_t3_exact = pass_manager.run(qc)
qc_t3_exact.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Jetzt gibt es nur noch drei ECR-Tore. Wir erhalten dieses Ergebnis, weil Qiskit auf Optimierungsebene 3 versucht, Zwei-Qubit-Blöcke von Gattern zu re-synthetisieren, und jedes Zwei-Qubit-Gatter kann mit höchstens drei ECR-Gattern implementiert werden. Wir können sogar noch weniger ECR-Gatter erhalten, wenn wir approximation_degree auf einen Wert kleiner als 1 setzen, was dem Transpiler erlaubt, Annäherungen vorzunehmen, die einen gewissen Fehler in die Gatterzerlegung einbringen können (siehe Häufig verwendete Parameter für die Transpilation ):

pass_manager = generate_preset_pass_manager(
    optimization_level=3,
    approximation_degree=0.99,
    backend=backend,
    seed_transpiler=12345,
)
qc_t3_approx = pass_manager.run(qc)
qc_t3_approx.draw("mpl", idle_wires=False)

Output:

Output of the previous code cell

Diese Schaltung hat nur zwei ECR-Gatter, aber es ist eine ungefähre Schaltung. Um zu verstehen, inwiefern sich die Wirkung von der exakten Schaltung unterscheidet, können wir die Treue zwischen dem unitären Operator, den diese Schaltung implementiert, und dem exakten unitären berechnen. Bevor wir die Berechnung durchführen, reduzieren wir zunächst die transpilierte Schaltung, die 127 Qubits enthält, auf eine Schaltung, die nur die aktiven Qubits enthält, von denen es zwei gibt.

import numpy as np


def trace_to_fidelity_2q(trace: float) -> float:
    return (4.0 + trace * trace.conjugate()) / 20.0


# Reduce circuits down to 2 qubits so they are easy to simulate
qc_t3_exact_small = QuantumCircuit.from_instructions(qc_t3_exact)
qc_t3_approx_small = QuantumCircuit.from_instructions(qc_t3_approx)

# Compute the fidelity
exact_fid = trace_to_fidelity_2q(
    np.trace(np.dot(Operator(qc_t3_exact_small).adjoint().data, UU))
)
approx_fid = trace_to_fidelity_2q(
    np.trace(np.dot(Operator(qc_t3_approx_small).adjoint().data, UU))
)
print(
    f"Synthesis fidelity\nExact: {exact_fid:.3f}\nApproximate: {approx_fid:.3f}"
)

Output:

Synthesis fidelity
Exact: 1.000+0.000j
Approximate: 0.992+0.000j

Die Anpassung des Optimierungsgrades kann auch andere Aspekte der Schaltung beeinflussen, nicht nur die Anzahl der ECR-Gatter. Beispiele dafür, wie sich die Änderung der Optimierungsstufe auf das Layout auswirkt, finden Sie unter „Darstellung von Quantencomputern “.


Nächste Schritte

Empfehlungen
War diese Seite hilfreich?
Melden Sie auf GitHub einen Fehler, einen Tippfehler oder fordern Sie Inhalte an.