반복 코드
사용 예상 시간: Heron 프로세서에서 1분 미만 (참고: 이는 추정치일 뿐이며, 실제 실행 시간은 다를 수 있습니다.)
배경
실시간 양자 오류 정정(QEC)을 구현하려면, 측정 결과에 따라 양자 게이트를 조건부로 실행할 수 있도록 실행 중에 양자 프로그램의 흐름을 동적으로 제어할 수 있어야 합니다. 이 튜토리얼은 비트 반전 코드(bit-flip code)를 실행하며, 이는 매우 간단한 형태의 QEC입니다. 인코딩된 Qubit을 단일 비트 반전 오류로부터 보호할 수 있는 동적 양자 Circuit을 시연하고, 비트 반전 코드의 성능을 평가합니다.
추가 앤실라(ancilla) Qubit과 얽힘을 활용하여 인코딩된 양자 정보를 변환하지 않으면서도 발생했을 수 있는 특정 종류의 오류를 알려주는 *스태빌라이저(stabilizer)*를 측정할 수 있습니다. 양자 스태빌라이저 코드는 개의 논리 Qubit을 개의 물리 Qubit으로 인코딩합니다. 스태빌라이저 코드는 파울리 그룹 을 지원하는 이산 오류 집합의 수정에 핵심적으로 집중합니다.
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단계. 고전적 입력을 양자 문제로 변환
비트 반전 스태빌라이저 Circuit 구축
비트 반전 코드는 스태빌라이저 코드의 가장 간단한 예 중 하나입니다. 이 코드는 인코딩 Qubit 중 어느 하나에 대한 단일 비트 반전(X) 오류로부터 상태를 보호합니다. 및 으로 매핑하는 비트 반전 오류 의 작용을 고려하면, 가 됩니다. 이 코드는 다섯 개의 Qubit이 필요합니다: 세 개는 보호할 상태를 인코딩하는 데 사용되고, 나머지 두 개는 스태빌라이저 측정 앤실라로 사용됩니다.
# 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 프리미티브는 대상 시스템이 지원하는 명령어 및 연결성에 맞는 Circuit과 옵저버블만 허용합니다(명령어 집합 아키텍처(ISA) Circuit 및 옵저버블이라고 합니다). 트랜스파일에 대해 더 알아보기.
ISA Circuit 생성
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)