קודי חזרה
הערכת שימוש: פחות מדקה על מעבד Heron (הערה: זוהי הערכה בלבד. זמן הריצה שלך עשוי להשתנות.)
רקע
כדי לאפשר תיקון שגיאות קוונטיות (QEC) בזמן אמת, עליך להיות מסוגל לשלוט באופן דינמי בזרימת תוכנית קוונטית במהלך הביצוע, כך שניתן יהיה לתנות שערים קוונטיים על תוצאות מדידה. מדריך זה מריץ את קוד היפוך הביט, שהוא צורה פשוטה מאוד של QEC. הוא מדגים מעגל קוונטי דינמי שיכול להגן על קיוביט מקודד מפני שגיאת היפוך ביט בודדת, ולאחר מכן מעריך את ביצועי קוד היפוך הביט.
ניתן לנצל קיוביטי ancilla נוספים ושזירה כדי למדוד מייצבים שאינם משנים את המידע הקוונטי המקודד, תוך כדי שהם עדיין מודיעים לך על סוגים מסוימים של שגיאות שעלולות להתרחש. קוד מייצב קוונטי מקודד קיוביטים לוגיים לתוך קיוביטים פיזיים. קודי מייצבים מתמקדים באופן קריטי בתיקון קבוצת שגיאות בדידה עם תמיכה מקבוצת Pauli .
למידע נוסף על QEC, עיין ב-Quantum Error Correction for Beginners.
דרישות
לפני תחילת מדריך זה, ודא שהדברים הבאים מותקנים:
- Qiskit SDK גרסה 2.0 ומעלה, עם תמיכה ב-visualization
- Qiskit Runtime גרסה 0.40 ומעלה (
pip install 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()
שלב 1. מיפוי קלטים קלאסיים לבעיה קוונטית
בניית מעגל מייצב היפוך ביט
קוד היפוך הביט הוא אחד הדוגמאות הפשוטות ביותר לקוד מייצב. הוא מגן על המצב מפני שגיאת היפוך ביט (X) בודדת על כל אחד מקיוביטי הקידוד. נשקול את פעולת שגיאת היפוך הביט , שממפה ו- על כל אחד מהקיוביטים שלנו, אז מתקבל . הקוד דורש חמישה קיוביטים: שלושה משמשים לקידוד המצב המוגן, והשניים הנותרים משמשים כ-ancilla למדידת מייצבים.
# 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)
שלב 2. אופטימיזציה של הבעיה לביצוע קוונטי
כדי לצמצם את זמן הביצוע הכולל של המשימה, פרימיטיבים של Qiskit מקבלים רק מעגלים ואובזרבבלים התואמים להוראות ולקישוריות הנתמכות על ידי מערכת היעד (המכונה מעגלי ISA ואובזרבבלים). למד עוד על transpilation.
יצירת מעגלי ISA
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)
שלב 3. ביצוע באמצעות פרימיטיבים של Qiskit
הפעל את הגרסה עם תיקון מיושם ואחת ללא תיקון.
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}
שלב 4. עיבוד לאחר, החזרת תוצאה בפורמט קלאסי
ניתן לראות שקוד היפוך הביט זיהה ותיקן שגיאות רבות, מה שהביא לפחות שגיאות בסך הכל.
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.
סקר מדריך
אנא מלא סקר קצר זה כדי לספק משוב על מדריך זה. התובנות שלך יעזרו לנו לשפר את תוכן ההצעות שלנו וחוויית המשתמש.