Zom Hauptinhalt springe

Widderhollungscodes

Schätzung för de Nutzung: winniger als 1 Minuut op enem Heron-Prozessor (HINWEIS: Dat es nur en Schätzung. Üch tatschlije Laufzigg kann avwijche.)

Hengerjrund

Domet echte Quantefählerkorrektur (QEC) en Echtzigg funktioniere kann, moß mer dä Programmablauf während der Usföhrung dynamisch stüüere künne, esu dat Quantegates op Meßerjebnisse bedingt wääde künne. Dat Tutorial führ dän Bit-Flip-Code uß, dä e sehr eenfache Form vun QEC es. Et zeijt enne dynamische Quanteschaltkreis, dä e kodierted Qubit vör enem einzelne Bit-Flip-Fähler schütze kann, un bewertet donoh de Leistung vum Bit-Flip-Code.

Mer kann zosätzlich Ancilla-Qubits un Verschränkung nutze, öm Stabilisatore zo messe, die de kodierde Quanteinformation nit verändere, avver trotzdäm övver bestimmte Klasse vun Fählere informiere, die opschtocke könte. En Quante-Stabilisatorcode kodiert kk logische Qubits en nn physikalische Qubits. Stabilisatorcodes setze dern Schwerpunkt op de Korrektur vun enem diskreten Fählersatz met Ongerstützung vun der Pauli-Jrupp Πn\Pi^n.

Mieh Informazjone övver QEC fingk Ehr en Quantum Error Correction for Beginners.

Vürussetzunge

Bevor Ehr met däm Tutorial aanfangt, stellt sicher, dat Ehr foljendes installiert hät:

  • Qiskit SDK v2.0 udder neuer, met Visualisierungs-Ongerstützung
  • Qiskit Runtime v0.40 udder neuer (pip install qiskit-ibm-runtime)

Enrichtung

# 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 Engabe op e Quanteproblem övverdrare

Enne Bit-Flip-Stabilisatorschaltkreis baue

Dä Bit-Flip-Code es eins vun de eenfachste Bispiller vun enem Stabilisatorcode. He schützt dä Zostand jäje enne einzelne Bit-Flip-(X-)Fähler op einem vun de Kodierungqubits. Wenn mer de Wirkung vum Bit-Flip-Fähler XX betrachtelt, dä 01|0\rangle \rightarrow |1\rangle un 10|1\rangle \rightarrow |0\rangle mappe deit op einem unserer Qubits, dann krieje mer ϵ={E0,E1,E2}={IIX,IXI,XII}\epsilon = \{E_0, E_1, E_2 \} = \{IIX, IXI, XII\}. Dä Code bruucht fünf Qubits: drei wääde benutzt, öm dän jeschützten Zostand zo kodiere, un de übrije zwei dene als Stabilisatormessungs-Ancillas.

# 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)

Output of the previous code cell

Output of the previous code cell

Schritt 2. Dat Problem för de Quanteusföhrung optimiere

Öm de jesamt Job-Usföhrungsziggt ze verkürze, neeme Qiskit-Primitiven nur Schaltkreise un Observablen aan, die de Befehle un de Verbindunge vum Zielsystem erfülle (auch als ISA-Schaltkreise un Observablen bekannt). Mieh övver Transpilation erfahre.

ISA-Schaltkreise erzüje

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)

Output of the previous code cell

Output of the previous code cell

no_correction_circuit = build_error_correction_sequence(
apply_correction=False
)

isa_no_correction_circuit = pm.run(no_correction_circuit)

Schritt 3. Met Qiskit-Primitiven usföhre

Föhrt de Version met Korrektur un die oohne Korrektur uß.

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. Nohbearbeide un Ergebnis em klassische Format zrückjäve

Mer kann sinn, dat dä Bit-Flip-Code vill Fähler erkannt un korrijiert hät, esu dat insjesamt winniger Fähler övvrijbleive.

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-Ömfrare

Bitte nemmt an dä körze Ömfrare teil, öm Rückmeldung zo däm Tutorial ze jäve. Üch Hinweis helfe uns, unsere Inhälde un de Benutzererfahrung ze verbessere.

Link zur Ömfrare