Перейти до основного вмісту

Коди повторення

Оцінка використання: менше 1 хвилини на процесорі Heron (ПРИМІТКА: Це лише оцінка. Ваш час виконання може відрізнятися.)

Загальна інформація

Щоб забезпечити квантове виправлення помилок (QEC) у реальному часі, вам потрібна можливість динамічно контролювати потік квантової програми під час виконання, щоб квантові вентилі могли залежати від результатів вимірювань. Цей посібник запускає код перевертання біта, який є дуже простою формою QEC. Він демонструє динамічну квантову схему, яка може захистити закодований кубіт від однієї помилки перевертання біта, а потім оцінює продуктивність коду перевертання біта.

Ви можете використовувати додаткові допоміжні кубіти та заплутаність для вимірювання стабілізаторів, які не перетворюють закодовану квантову інформацію, водночас інформуючи вас про деякі класи помилок, які могли статися. Квантовий код стабілізатора кодує kk логічних кубітів у nn фізичних кубітів. Коди стабілізатора критично зосереджені на виправленні дискретного набору помилок з підтримкою групи Паулі Πn\Pi^n.

Для отримання додаткової інформації про QEC зверніться до Quantum Error Correction for Beginners.

Вимоги

Перед початком цього посібника переконайтеся, що у вас встановлено наступне:

  • Qiskit SDK v2.0 або новіший, з підтримкою візуалізації
  • Qiskit Runtime v0.40 або новіший (pip install qiskit-ibm-runtime)

Налаштування

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

Крок 1. Відображення класичних входів на квантову задачу

Побудова схеми стабілізатора перевертання біта

Код перевертання біта є одним з найпростіших прикладів коду стабілізатора. Він захищає стан від однієї помилки перевертання біта (X) на будь-якому з кодувальних кубітів. Розглянемо дію помилки перевертання біта XX, яка відображає 01|0\rangle \rightarrow |1\rangle і 10|1\rangle \rightarrow |0\rangle на будь-якому з наших кубітів, тоді ми маємо ϵ={E0,E1,E2}={IIX,IXI,XII}\epsilon = \{E_0, E_1, E_2 \} = \{IIX, IXI, XII\}. Код вимагає п'яти кубітів: три використовуються для кодування захищеного стану, а два інші використовуються як допоміжні для вимірювання стабілізатора.

# 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

Крок 2. Оптимізація задачі для квантового виконання

Щоб зменшити загальний час виконання завдання, примітиви Qiskit приймають лише схеми та спостережувані величини, що відповідають інструкціям та з'єднанню, підтримуваним цільовою системою (які називаються схемами та спостережуваними величинами архітектури набору інструкцій (ISA)). Дізнайтеся більше про транспіляцію.

Генерація 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)

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)

Крок 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.

Опитування посібника

Будь ласка, пройди це коротке опитування, щоб надати відгук про цей посібник. Твої ідеї допоможуть нам покращити наші пропозиції контенту та користувацький досвід.

Посилання на опитування