Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Verwenden Sie qodec das qdk.ec Modul aus dem Microsoft Quantum Development Kit (QDK) zum Definieren eines QEC-Codes (Quantum Error Correction), und verwandeln Sie ihn in ein ausführbares Protokoll. In diesem Artikel definieren Sie einen Fehlercode, erstellen einen Basisplan qodec, überprüfen die Deklarationen, berechnen den Gadgetabstand und speichern das Protokoll.
Die Beispiele in diesem Artikel verwenden den $[[4,2,2]]$ C4 -Code, der zwei logische Qubits in vier physischen Qubits speichert und jeden einzelnen physischen Pauli Fehler erkennt.
Prerequisites
Führen Sie diese Aufgaben aus, bevor Sie beginnen:
- Installation QDK für Fehlerkorrektur.
- Verwenden Sie eine Umgebung mit Python 3.11 oder höher.
- Vergewissern Sie sich, dass der qodecStim Parser verfügbar ist. Installieren Sie aus der Quelle,Arm64Windows und starten Python Sie den Kernel neu, Jupyter bevor Sie aufrufen
build_qodec.StimLinuxArm64
Definieren des Codes
Erstellen Sie ein qodec.Code Objekt mit den Codestabilisierungsreglern und einem logischen X- und Z-Vertreter für jeden logischen Qubit.
import qodec
c4 = qodec.Code(
"C4",
stabilizers=["X_0 X_1 X_2 X_3", "Z_0 Z_1 Z_2 Z_3"],
x=["X_0 X_1", "X_0 X_2"],
z=["Z_0 Z_2", "Z_0 Z_1"],
)
Das qodec Paket verwendet eine geringe Schreibweise für Pauli Zeichenfolgen. Jeder Ausdruck hat einen Pauli Buchstaben und eine physische Qubitbeschriftung. Wendet beispielsweise X_0 X_2 X auf physische Qubits 0 und 2 an.
Die Codedefinition ist ein statisches mathematisches Objekt. Es enthält keine Schaltkreise, die codierte Zustände vorbereiten, beibehalten oder messen.
Analysieren des Codes
Um eine Momentaufnahme der Codeoperatoren zu prüfen, erstellen Sie eine CodeProfile.
from qdk import ec
profile = ec.CodeProfile(c4)
print("Physical support:", sorted(profile.support))
print("Physical qubits:", profile.length)
print("Logical qubits:", profile.logical_qubit_count)
print("Stabilizers:", profile.stabilizers)
print("Logical X operators:", profile.x)
print("Logical Z operators:", profile.z)
Das Profil ändert sich nicht, wenn Sie das ursprüngliche qodec.Code Objekt später ändern.
Berechnen des Codeabstands
Um die minimale Anzahl der zulässigen physischen Fehler zu finden, die einen nichttriviellen logischen Effekt mit Null-Syndrom verursachen, rufen Sie distanceauf.
distance = profile.distance()
print("Code distance:", distance)
error = distance.witness.product
syndrome = profile.syndrome_of(error)
logical_effect = profile.logical_effect_of(error)
print("Witness:", error)
print("Syndrome:", sorted(syndrome))
print("Logical effect:", logical_effect)
assert distance.value == 2
assert profile.is_logical(error)
Standardmäßig weist die Suche jedem Einzel-Qubit X-, Y- oder Z-Fehler Kosten 1 zu. Der zurückgegebene Wert Distance verfügt über zertifizierte Grenzen und einen Zeugen für eine endliche obere Grenze.
Wenn eine vollständige genaue Suche zu viel kostet, verwenden Sie distance_bounds.
bounds = profile.distance_bounds(upper_bound=4)
print("Distance bounds:", bounds)
print("Lower bound:", bounds.lower_bound)
print("Upper bound:", bounds.upper_bound)
Der Standardlöser ist HiGHS. Um einen anderen Solver, einen anderen Solver festzulegen solver="enumeration"oder zu installieren MWPF und festzulegen solver="mwpf".
Erstellen eines Basisplans qodec
Es qodec wird beschrieben, wie codierte Anweisungen ausgeführt werden. Sie verfügt über Anweisungssätze, Codes, Ebenen, Gadgets, Schaltkreise, Prüfungen und Formeln zum Lesen.
Dient build_qodec zum Erstellen eines zweischichtigen Protokolls aus dem C4 Code.
protocol = ec.build_qodec(
c4,
strategy="bare-css/v1",
strict=False,
)
In diesem Beispiel können bare-css/v1 Sie ein einfaches Protokoll ohne Flag-Qubits untersuchen.
Caution
Die bare-css/v1 Strategie verspricht keine fehlertoleranten Schaltkreise. Berechnen Sie die Entfernung jedes Gadgets, bevor Sie das Protokoll für laute Experimente verwenden.
Der Generator versucht, diese logischen Anweisungen zu erstellen:
prepare_z_allprepare_x_allsyndromemeasure_z_allmeasure_x_allh_allcx_all
Das _all Suffix bedeutet, dass eine Anweisung auf jedem logischen Qubit in einem Block fungiert. Gilt beispielsweise cx_allCNOT zwischen entsprechenden logischen Qubits in zwei Blöcken.
Nicht jeder Code unterstützt jede Kandidatenanweisung. Bei strict=Trueder Standardeinstellung löst der Generator einen Fehler aus, wenn er einen Kandidaten nicht erstellen und überprüfen kann. Mit strict=False, der Generator behält die unterstützten Anweisungen und Zeichnet Auslassungen in protocol.metadata["qdk.ec"]["build"]["omitted"].
Überprüfen Sie die logische Ebene und die zugehörigen Gadgets.
logical_layer = protocol.layers[0]
print("Instructions:")
for mnemonic in logical_layer.instruction_set.instructions:
print(" -", mnemonic)
print("Gadgets:")
for mnemonic in logical_layer.gadgets:
print(" -", mnemonic)
Die zweite Ebene enthält den physikalischen Stim Anweisungssatz, den die generierten Schaltungen verwenden.
Überprüfen eines Gadgets
Eine logische Anweisung deklariert einen Vertrag. Sein Gadget gibt den Schaltkreis, der den Vertrag implementiert.
Überprüfen Sie das prepare_z_all Gadget.
gadget = logical_layer.gadgets["prepare_z_all"]
gadget_profile = ec.GadgetProfile(gadget)
print("Declared objective:")
print(gadget_profile.objective)
print("Computed action:")
print(gadget_profile.action)
Vergleichen Sie die vom Schaltkreis berechnete Aktion mit dem deklarierten Anweisungsziel.
objective = gadget_profile.objective
assert objective is not None
if gadget_profile.action.is_equivalent_to(objective):
print("The gadget implements its declared instruction.")
else:
print(objective.why_not_equivalent_to(gadget_profile.action))
A GadgetProfile takes a snapshot of its input, so it doesn't reflect later changes. Nachdem Sie ein Gadget bearbeitet haben, erstellen Sie ein neues Profil.
Überwachen des Protokolls
Wird audit verwendet, um das ganze qodeczu überprüfen.
report = ec.audit(protocol)
print(report)
Wenn die Überwachung keine Fehler oder Warnungen findet, wird folgendes ausgegeben:
audit: ok
Die Überwachung überprüft diese Bereiche:
- Codealgebren
- Anweisungs- und Schichtstruktur
- Schaltkreisaufrufe und Parameterbindungen
- Gadgetaktionen
- Formeln zum Überprüfen und Lesen
- Kennzeichnen von Formeln
- Beziehungen zu Eingabe- und Ausgabeframes
- Referenzgrenzen und Protokoll-Vollständigkeit
Verwenden Sie die Berichtssammlungen, um auf bestimmte Schweregrade zu reagieren.
if report.errors:
for diagnostic in report.errors:
print(diagnostic)
raise ValueError("The qodec has audit errors.")
if report.warnings:
for diagnostic in report.warnings:
print(diagnostic)
Der report.ok Wert bedeutet, dass der Bericht keine Fehler aufweist. Warnungen ändern diese Eigenschaft nicht.
Ableiten fehlender Formeln
Wird verwendet filled , wenn ein Entwurfs-Gadget ausgelassen wird oder qodec Überprüfungen oder logische Auslesegleichungen weggelassen werden, die genaue Simulation ableiten kann.
Im folgenden Beispiel wird eine unvollständige Kopie des Protokolls erstellt.
draft = qodec.Qodec.loads(protocol.dumps())
draft_gadgets = draft.layers[0].gadgets
draft_gadgets["measure_x_all"].readouts = []
draft_gadgets["cx_all"].checks = []
print(ec.audit(draft))
Füllen Sie die unterstützten Formeln aus, und überwachen Sie dann das Ergebnis.
completed = ec.filled(draft)
print(ec.audit(completed))
Die filled Funktion gibt ein neues Gadget zurück oder qodec ändert die Eingabe nicht. Es leitet Überprüfungen, feststellbare Lesbarkeitsgleichungen und Rahmenbeziehungen ab. Es behält Kennzeichnungsbindungen bei, da die rauschlose Simulation nicht erkennen kann, welche Fehler ein Flag erkennen soll.
Wenn das ursprüngliche Protokoll bereits direkte Formeln überprüft hat, filled behält es diese nach Möglichkeit bei.
Analysieren von Gadgetfehlern
Ein Audit ohne Fehler beweist rauschlose Konsistenz. Die Fehlertoleranz wird nicht nachgewiesen.
Rufen Sie GadgetProfile.distance auf, um die minimale Anzahl zulässiger Schaltkreisfehler zu ermitteln, die zu einem logischen Fehler führen, während alle deklarierten Prüfungen und Flags null bleiben. Der kombinierte Fehler muss auch jede Ausgabe innerhalb des Codebereichs belassen.
protocol = completed
for mnemonic, gadget in sorted(protocol.layers[0].gadgets.items()):
result = ec.GadgetProfile(gadget).distance()
witness = result.witness if result.upper_bound is not None else "none"
print(f"{mnemonic}: distance={result}, witness={witness}")
Das Standardfehlermodell enthält diese Ereignisse nach jedem Schaltkreisaufruf:
- Ein Pauli Fehler in den Qubits, die der Aufruf berührt
- Flip of a readout bit that the call produces
- Eine korrelierte Kombination dieser Fehler
Jedes Ereignis bei einem Aufruf kostet einen, auch wenn es einen korrelierten Multiqubit-Fehler aufweist.
Ein Code kann Abstand zwei haben, während eines seiner Gadgets abstand 1 hat. Beispielsweise kann ein einzelner Schaltkreisfehler durch eine Ancilla verteilt und einen nicht erkannten logischen Fehler erstellen. Fügen Sie Prüf- oder Kennzeichnungsschaltungen hinzu, erstellen Sie dann einen neuen GadgetProfile und berechnen Sie den Abstand erneut.
Prüfen eines bestimmten Fehlers
Wird verwendet FaultEvent.after , um einen Fehler nach einem Null-basierten Schaltkreisanrufindex zu definieren.
gadget = protocol.layers[0].gadgets["syndrome"]
profile = ec.GadgetProfile(gadget)
fault = ec.FaultEvent.after(0, ec.Pauli("X_0"))
(effect,) = profile.effects_of([fault])
print("Fault:", fault)
print("Changed quantities:", effect)
Eine FaultEffect kann geänderte Überprüfungen, logische Lesevorgänge und Ausgabeframezeichen umfassen. Verwenden Sie explizite Fehlersätze, wenn das Standardmodell auf Schaltkreisebene nicht ihren Hardwareannahmen entspricht.
result = profile.distance(faults=[fault])
print(result)
Genaue Gadgetsuchen können lange dauern, da der Standardfehlersatz exponentiell mit der Unterstützung jedes Anrufs wächst. Verwenden Sie distance_boundseinen expliziten Fehlersatz oder upper_bound einen, wenn Sie die Suche einschränken müssen.
Speichern des Protokolls
Überwachen Sie das Finale qodec , bevor Sie es speichern.
report = ec.audit(protocol)
if report.errors or report.warnings:
raise ValueError(str(report))
Speichern Sie das Protokoll als einzelnes YAML Bündel, und laden Sie es erneut, um zu überprüfen, ob es mit dem Original übereinstimmt.
from pathlib import Path
output_directory = Path("qodec-output")
output_directory.mkdir(exist_ok=True)
saved_path = protocol.save(str(output_directory), single_file=True)
loaded = qodec.Qodec.load(saved_path)
assert loaded == protocol
print("Saved qodec:", saved_path)
In einem Einzeldateibundle werden das Manifest, Codedefinitionen, Anweisungssätze, Gadgets und Schaltkreisquellen in einer YAML Datei gespeichert, wodurch das Freigeben und Erneuteladen vereinfacht wird.
Ausführen des Protokolls
Nachdem das qodec Audit bestanden wurde und Ihre Entfernungsanforderungen erfüllt, kompilieren Sie ein logisches Programm zu Quantum Intermediate Representation (QIR) und führen sie über das Protokoll aus. Siehe Ausführen und Decodieren logischer Programme.
Ein vollständiges Beispiel, das Flagschaltungen hinzufügt und logische Fehlerraten vergleicht, finden Sie in der exemplarischen Vorgehensweise des QEC-Protokolls im QDK GitHub-Repository.