Skip to main content
IBM Quantum Platform

反復コード

使用時間の目安:Heronプロセッサーで1分未満(注:あくまでも目安です。 ランタイムは異なるかもしれない)。


背景

リアルタイムの量子エラー訂正(QEC)を可能にするためには、量子プログラムの実行中に量子プログラムの流れを動的に制御し、測定結果に応じて量子ゲートを条件付けできるようにする必要がある。 このチュートリアルでは、QEC の非常に単純な形式である bit-flip コードを実行します。 符号化量子ビットを1回のビット反転エラーから保護できる動的量子回路を実証し、ビット反転符号の性能を評価する。

さらにアンシラ量子ビットとエンタングルメントを利用すれば、符号化された量子情報を変換することなく安定化装置を測定することができる。 量子スタビライザーコードは、 kk 論理量子ビットを nn 物理量子ビットにエンコードする。 スタビライザー符号は、パウリ群 Πn\Pi^n からの支持を得て、離散的な誤り集合を訂正することに重点を置いている。

QECに関する詳細については、 『初心者向け量子エラー訂正』 を参照してください。


要件

このチュートリアルを始める前に、以下のものがインストールされていることを確認してください:

  • Qiskit SDK v2.0 またはそれ以降、 可視化サポート付き
  • Qiskit Runtime v0.40 またはそれ以降 (pip install qiskit-ibm-runtime)

セットアップ

# Qiskit imports
from qiskit import (
    QuantumCircuit,
    QuantumRegister,
    ClassicalRegister,
)

# qiskit-ibm-runtime
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler

from qiskit_ibm_runtime.circuit import MidCircuitMeasure

service = QiskitRuntimeService()

ステップ 1. 古典的な入力を量子問題にマッピングする

ビット反転安定化回路を構築する

ビット反転符号は、スタビライザー符号の最も単純な例である。 これは、符号化量子ビットのいずれかが1つのビット反転(X)エラーから状態を保護する。 01|0\rangle \rightarrow |1\rangle ϵ={E0,E1,E2}={IIX,IXI,XII}\epsilon = \{E_0, E_1, E_2 \} = \{IIX, IXI, XII\} と を任意の量子ビットにマップする、ビット反転エラー の作用を考える。このコードには5つの量子ビットが必要です。3つは保護された状態をエンコードするのに使われ、残りの2つはスタビライザー測定アンシラとして使われます。 10|1\rangle \rightarrow |0\rangle XX

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

Output of the previous code cell Output of the previous code cell

ステップ 2. 量子実行向けに問題を最適化する

ジョブの実行時間を短縮するため、 Qiskit primitives は、ターゲットシステムがサポートする命令および接続仕様に準拠した回路およびオブザーバブルのみを受け入れます(これらは命令セットアーキテクチャ(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:

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 primitives を使用して実行する

補正を適用したバージョンと補正なしのバージョンを実行する。

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()}"
)

Output:

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()}"
)

Output:

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 "
        f"{error_correction_events}/{shots} trials."
    )
    print(
        f"A final parity error was detected on "
        f"{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): "
    f"{data_result}"
)
print(
    f"Completed bit code experiment syndrome measurement counts (no correction): "
    f"{marginalized_syndrome_result}"
)
decode_result(data_result, marginalized_syndrome_result)

Output:

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): "
    f"{corrected_data_result}"
)
print(
    f"Completed bit code experiment syndrome measurement counts (corrected): "
    f"{corrected_syndrome_result}"
)
decode_result(corrected_data_result, corrected_syndrome_result)

Output:

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.

チュートリアル調査

このチュートリアルに関するご意見・ご感想をお寄せください。 あなたの洞察は、私たちのコンテンツの提供とユーザーエクスペリエンスを向上させるのに役立ちます。

アンケートへのリンク

このページは役に立ちましたか?
バグや誤字の報告、またはコンテンツの要求はGitHubで行ってください。