Wiederholungscodes
Nutzungsschätzung: weniger als 1 Minute auf eim Heron-Prozessor (HINWEIS: Des isch bloß a Schätzung. Dei Laufzeit ka variiere.)
Hintergrund
Um Echtzeit-Quantenfehlerkorrektur (QEC) z'ermögliche, muss mr in dr Lag sei, den Quantenprogrammfluss während dr Ausführung dynamisch z'steuere, sodass Quantengates von Messergebnisse abhängig gmacht werde könnet. Des Tutorial führt den Bit-Flip-Code aus, der a ganz eifache Form von QEC isch. Es zeigt an dynamische Quantenschaltkreis, der a kodiertes Qubit vor eim einzelne Bit-Flip-Fehler schütze ka, und bewertet dann d'Leistung vom Bit-Flip-Code.
Mr könnet zusätzliche Hilfs-Qubits und Verschränkung nutze, um Stabilisatoren z'messe, die kodierte Quanteninformation ned transformieret, während se ons dennoch über etliche Fehlerklasse informieret, die vielleicht aufgtrette send. A Quanten-Stabilisator-Code kodiert logische Qubits in physische Qubits. Stabilisator-Codes konzentrieret sich vor allem auf d'Korrektur von eim diskreten Fehlersatz mit Unterstützung aus dr Pauli-Gruppe .
Für weitere Informatiione über QEC luag bei Quantum Error Correction for Beginners nei.
Anforderungen
Stell sicher, bevor's mit dem Tutorial losgeht, dass des Folgende installiert isch:
- Qiskit SDK v2.0 oder neuer, mit visualization-Unterstützung
- Qiskit Runtime v0.40 oder neuer (
pip install qiskit-ibm-runtime)
Setup
# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-ibm-runtime
# Qiskit imports
from qiskit import (
QuantumCircuit,
QuantumRegister,
ClassicalRegister,
)
# Qiskit Runtime
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
from qiskit_ibm_runtime.circuit import MidCircuitMeasure
service = QiskitRuntimeService()
Schritt 1. Klassische Eingaben auf a Quantenproblem abbilden
An Bit-Flip-Stabilisator-Schaltkreis erstelle
Der Bit-Flip-Code isch ois von de eifachste Beispiele vom aim Stabilisator-Code. Er schützt den Zustand vor eim einzelne Bit-Flip (X)-Fehler auf oim von de Kodierungs-Qubits. Betrachtet mr d'Wirkung vom Bit-Flip-Fehler , der und auf eim von unsere Qubits abbildet, dann hend mr . Der Code braucht fünf Qubits: Drei werdet verwendet, um den geschützten Zustand z'kodiere, und d'verbleibende zwoi werdet als Stabilisatormessungs-Ancillas verwendet.
# Choose the least busy backend that supports `measure_2`.
backend = service.least_busy(
filters=lambda b: "measure_2" in b.supported_instructions,
operational=True,
simulator=False,
dynamic_circuits=True,
)
qreg_data = QuantumRegister(3)
qreg_measure = QuantumRegister(2)
creg_data = ClassicalRegister(3, name="data")
creg_syndrome = ClassicalRegister(2, name="syndrome")
state_data = qreg_data[0]
ancillas_data = qreg_data[1:]
def build_qc():
"""Build a typical error correction circuit"""
return QuantumCircuit(qreg_data, qreg_measure, creg_data, creg_syndrome)
def initialize_qubits(circuit: QuantumCircuit):
"""Initialize qubit to |1>"""
circuit.x(qreg_data[0])
circuit.barrier(qreg_data)
return circuit
def encode_bit_flip(circuit, state, ancillas) -> QuantumCircuit:
"""Encode bit-flip. This is done by simply adding a cx"""
for ancilla in ancillas:
circuit.cx(state, ancilla)
circuit.barrier(state, *ancillas)
return circuit
def measure_syndrome_bit(circuit, qreg_data, qreg_measure, creg_measure):
"""
Measure the syndrome by measuring the parity.
We reset our ancilla qubits after measuring the stabilizer
so we can reuse them for repeated stabilizer measurements.
Because we have already observed the state of the qubit,
we can write the conditional reset protocol directly to
avoid another round of qubit measurement if we used
the `reset` instruction.
"""
circuit.cx(qreg_data[0], qreg_measure[0])
circuit.cx(qreg_data[1], qreg_measure[0])
circuit.cx(qreg_data[0], qreg_measure[1])
circuit.cx(qreg_data[2], qreg_measure[1])
circuit.barrier(*qreg_data, *qreg_measure)
circuit.append(MidCircuitMeasure(), [qreg_measure[0]], [creg_measure[0]])
circuit.append(MidCircuitMeasure(), [qreg_measure[1]], [creg_measure[1]])
with circuit.if_test((creg_measure[0], 1)):
circuit.x(qreg_measure[0])
with circuit.if_test((creg_measure[1], 1)):
circuit.x(qreg_measure[1])
circuit.barrier(*qreg_data, *qreg_measure)
return circuit
def apply_correction_bit(circuit, qreg_data, creg_syndrome):
"""We can detect where an error occurred and correct our state"""
with circuit.if_test((creg_syndrome, 3)):
circuit.x(qreg_data[0])
with circuit.if_test((creg_syndrome, 1)):
circuit.x(qreg_data[1])
with circuit.if_test((creg_syndrome, 2)):
circuit.x(qreg_data[2])
circuit.barrier(qreg_data)
return circuit
def apply_final_readout(circuit, qreg_data, creg_data):
"""Read out the final measurements"""
circuit.barrier(qreg_data)
circuit.measure(qreg_data, creg_data)
return circuit
def build_error_correction_sequence(apply_correction: bool) -> QuantumCircuit:
circuit = build_qc()
circuit = initialize_qubits(circuit)
circuit = encode_bit_flip(circuit, state_data, ancillas_data)
circuit = measure_syndrome_bit(
circuit, qreg_data, qreg_measure, creg_syndrome
)
if apply_correction:
circuit = apply_correction_bit(circuit, qreg_data, creg_syndrome)
circuit = apply_final_readout(circuit, qreg_data, creg_data)
return circuit
circuit = build_error_correction_sequence(apply_correction=True)
circuit.draw(output="mpl", style="iqp", cregbundle=False)
Schritt 2. Problem für d'Quantenausführung optimiere
Um d'Gesamtausführungszeit vom Job z'reduziere, akzeptieret Qiskit-Primitive bloß Schaltkreise und Observablen, die de vom Zielsystem unterstützte Anweisunge und dr Konnektivität entsprechet (bezeichnet als Instruction Set Architecture (ISA)-Schaltkreise und -Observablen). Erfahret mr mehr über Transpilation.
ISA-Schaltkreise generiere
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
isa_circuit.draw("mpl", style="iqp", idle_wires=False)


no_correction_circuit = build_error_correction_sequence(
apply_correction=False
)
isa_no_correction_circuit = pm.run(no_correction_circuit)
Schritt 3. Ausführe mit Qiskit-Primitive
Führet d'Version mit angewendeter Korrektur und oine ohne Korrektur aus.
sampler_no_correction = Sampler(backend)
job_no_correction = sampler_no_correction.run(
[isa_no_correction_circuit], shots=1000
)
result_no_correction = job_no_correction.result()[0]
sampler_with_correction = Sampler(backend)
job_with_correction = sampler_with_correction.run([isa_circuit], shots=1000)
result_with_correction = job_with_correction.result()[0]
print(f"Data (no correction):\n{result_no_correction.data.data.get_counts()}")
print(
f"Syndrome (no correction):\n{result_no_correction.data.syndrome.get_counts()}"
)
Data (no correction):
{'111': 878, '011': 42, '110': 35, '101': 40, '100': 1, '001': 2, '000': 2}
Syndrome (no correction):
{'00': 942, '10': 33, '01': 22, '11': 3}
print(f"Data (corrected):\n{result_with_correction.data.data.get_counts()}")
print(
f"Syndrome (corrected):\n{result_with_correction.data.syndrome.get_counts()}"
)
Data (corrected):
{'111': 889, '110': 25, '000': 11, '011': 45, '101': 17, '010': 10, '001': 2, '100': 1}
Syndrome (corrected):
{'00': 929, '01': 39, '10': 20, '11': 12}
Schritt 4. Nachbearbeitung, Rückgabe vom Ergebnis im klassische Format
Mr kennet sehe, dass der Bit-Flip-Code viele Fehler erkannt und korrigiert hat, was zu insgesamt weniger Fehlere gführt hat.
def decode_result(data_counts, syndrome_counts):
shots = sum(data_counts.values())
success_trials = data_counts.get("000", 0) + data_counts.get("111", 0)
failed_trials = shots - success_trials
error_correction_events = shots - syndrome_counts.get("00", 0)
print(
f"Bit flip errors were detected/corrected on {error_correction_events}/{shots} trials."
)
print(
f"A final parity error was detected on {failed_trials}/{shots} trials."
)
# non-corrected marginalized results
data_result = result_no_correction.data.data.get_counts()
marginalized_syndrome_result = result_no_correction.data.syndrome.get_counts()
print(
f"Completed bit code experiment data measurement counts (no correction): {data_result}"
)
print(
f"Completed bit code experiment syndrome measurement counts (no correction): {marginalized_syndrome_result}"
)
decode_result(data_result, marginalized_syndrome_result)
Completed bit code experiment data measurement counts (no correction): {'111': 878, '011': 42, '110': 35, '101': 40, '100': 1, '001': 2, '000': 2}
Completed bit code experiment syndrome measurement counts (no correction): {'00': 942, '10': 33, '01': 22, '11': 3}
Bit flip errors were detected/corrected on 58/1000 trials.
A final parity error was detected on 120/1000 trials.
# corrected marginalized results
corrected_data_result = result_with_correction.data.data.get_counts()
corrected_syndrome_result = result_with_correction.data.syndrome.get_counts()
print(
f"Completed bit code experiment data measurement counts (corrected): {corrected_data_result}"
)
print(
f"Completed bit code experiment syndrome measurement counts (corrected): {corrected_syndrome_result}"
)
decode_result(corrected_data_result, corrected_syndrome_result)
Completed bit code experiment data measurement counts (corrected): {'111': 889, '110': 25, '000': 11, '011': 45, '101': 17, '010': 10, '001': 2, '100': 1}
Completed bit code experiment syndrome measurement counts (corrected): {'00': 929, '01': 39, '10': 20, '11': 12}
Bit flip errors were detected/corrected on 71/1000 trials.
A final parity error was detected on 100/1000 trials.
Tutorial-Umfrage
Bitte machet bei derer kurze Umfrage mit, um Feedback zu dem Tutorial z'gebe. Dei Erkenntnisse helfet uns, unsere Inhaltsangebote und d'Benutzererfahrung z'verbessere.