Erstellen eines Pass Managers für Dynamical Decoupling
Paketversionen
Der Code auf dieser Seite wurde mit den folgenden Anforderungen entwickelt. Wir empfehlen die Verwendung dieser oder neuerer Versionen.
qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1
Diese Seite demonstriert, wie der PadDynamicalDecoupling-Pass verwendet wird, um eine Fehlerunterdrückungstechnik namens Dynamical Decoupling zur Schaltung hinzuzufügen.
Dynamical Decoupling funktioniert, indem Pulssequenzen (bekannt als Dynamical Decoupling-Sequenzen) zu inaktiven Qubits hinzugefügt werden, um sie um die Bloch-Kugel zu drehen, was die Wirkung von Rauschkanälen aufhebt und dadurch Dekohärenz unterdrückt. Diese Pulssequenzen ähneln Refokussierungspulsen, die in der Kernspinresonanz verwendet werden. Eine vollständige Beschreibung findest du in A Quantum Engineer's Guide to Superconducting Qubits.
Da der PadDynamicalDecoupling-Pass nur auf geplanten Schaltungen arbeitet und Gates umfasst, die nicht notwendigerweise Basis-Gates unseres Ziels sind, benötigst du auch die ALAPScheduleAnalysis- und BasisTranslator-Passes.
Dieses Beispiel verwendet ibm_fez, das zuvor initialisiert wurde. Hole die target-Informationen vom backend und speichere die Operationsnamen als basis_gates, da das target modifiziert werden muss, um Timing-Informationen für die im Dynamical Decoupling verwendeten Gates hinzuzufügen.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-ibm-runtime
from qiskit_ibm_runtime import QiskitRuntimeService
service = QiskitRuntimeService()
backend = service.backend("ibm_fez")
target = backend.target
basis_gates = list(target.operation_names)
Erstelle als Beispiel eine efficient_su2-Schaltung. Transpiliere zunächst die Schaltung zum Backend, da Dynamical Decoupling-Pulse hinzugefügt werden müssen, nachdem die Schaltung transpiliert und geplant wurde. Dynamical Decoupling funktioniert oft am besten, wenn es viel Leerlaufzeit in den Quantenschaltungen gibt - das heißt, es gibt Qubits, die nicht verwendet werden, während andere aktiv sind. Dies ist bei dieser Schaltung der Fall, da die Zwei-Qubit-ecr-Gates in diesem Ansatz sequenziell angewendet werden.
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.circuit.library import efficient_su2
qc = efficient_su2(12, entanglement="circular", reps=1)
pm = generate_preset_pass_manager(1, target=target, seed_transpiler=12345)
qc_t = pm.run(qc)
qc_t.draw("mpl", fold=-1, idle_wires=False)
Eine Dynamical Decoupling-Sequenz ist eine Reihe von Gates, die zur Identität zusammengesetzt werden und in der Zeit regelmäßig verteilt sind. Beginne beispielsweise mit der Erstellung einer einfachen Sequenz namens XY4, die aus vier Gates besteht.
from qiskit.circuit.library import XGate, YGate
X = XGate()
Y = YGate()
dd_sequence = [X, Y, X, Y]
Aufgrund der regelmäßigen Zeitsteuerung von Dynamical Decoupling-Sequenzen müssen Informationen über das YGate zum target hinzugefügt werden, da es kein Basis-Gate ist, während das XGate eines ist. Wir wissen jedoch a priori, dass das YGate die gleiche Dauer und den gleichen Fehler wie das XGate hat, sodass wir diese Eigenschaften einfach vom target abrufen und für die YGate-Objekte zurückgeben können. Deshalb wurden die basis_gates separat gespeichert, da wir die YGate-Anweisung zum target hinzufügen, obwohl es kein tatsächliches Basis-Gate von ibm_fez ist.
from qiskit.transpiler import InstructionProperties
y_gate_properties = {}
for qubit in range(target.num_qubits):
y_gate_properties.update(
{
(qubit,): InstructionProperties(
duration=target["x"][(qubit,)].duration,
error=target["x"][(qubit,)].error,
)
}
)
target.add_instruction(YGate(), y_gate_properties)
Ansatz-Schaltungen wie efficient_su2 sind parametrisiert, sodass ihnen Werte zugewiesen werden müssen, bevor sie an das Backend gesendet werden. Hier werden zufällige Parameter zugewiesen.
import numpy as np
rng = np.random.default_rng(1234)
qc_t.assign_parameters(
rng.uniform(-np.pi, np.pi, qc_t.num_parameters), inplace=True
)
Als Nächstes führe die benutzerdefinierten Passes aus. Instanziiere den PassManager mit ALAPScheduleAnalysis und PadDynamicalDecoupling. Führe zuerst ALAPScheduleAnalysis aus, um Timing-Informationen über die Quantenschaltung hinzuzufügen, bevor die regelmäßig verteilten Dynamical Decoupling-Sequenzen hinzugefügt werden können. Diese Passes werden mit .run() auf der Schaltung ausgeführt.
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes.scheduling import (
ALAPScheduleAnalysis,
PadDynamicalDecoupling,
)
dd_pm = PassManager(
[
ALAPScheduleAnalysis(target=target),
PadDynamicalDecoupling(target=target, dd_sequence=dd_sequence),
]
)
qc_dd = dd_pm.run(qc_t)
Verwende das Visualisierungstool timeline_drawer, um die Zeitsteuerung der Schaltung zu sehen und zu bestätigen, dass eine regelmäßig verteilte Sequenz von XGate-Objekten und YGate-Objekten in der Schaltung erscheint.
from qiskit.visualization import timeline_drawer
timeline_drawer(qc_dd, idle_wires=False, target=target)
Wende zuletzt manuell den BasisTranslator-Pass an, da das YGate kein tatsächliches Basis-Gate unseres Backends ist (dies ist ein Standard-Pass, wird aber vor der Planung ausgeführt, sodass er erneut angewendet werden muss). Die Session Equivalence Library ist eine Bibliothek von Schaltungsäquivalenzen, die es dem Transpiler ermöglicht, Schaltungen in Basis-Gates zu zerlegen, wie ebenfalls als Argument angegeben.
from qiskit.circuit.equivalence_library import (
SessionEquivalenceLibrary as sel,
)
from qiskit.transpiler.passes import BasisTranslator
qc_dd = BasisTranslator(sel, basis_gates)(qc_dd)
qc_dd.draw("mpl", fold=-1, idle_wires=False)
Jetzt fehlen YGate-Objekte in unserer Schaltung, und es gibt explizite Timing-Informationen in Form von Delay-Gates. Diese transpilierte Schaltung mit Dynamical Decoupling ist nun bereit, an das Backend gesendet zu werden.
Nächste Schritte
- Um zu erfahren, wie du die Funktion
generate_preset_passmanageranstelle des Schreibens eigener Passes verwendest, beginne mit dem Thema Transpilation default settings and configuration options. - Probiere den Guide Compare transpiler settings aus.
- Siehe die Transpile-API-Dokumentation.