ข้ามไปยังเนื้อหาหลัก
โครงการนี้อยู่ในช่วงเบต้า พบข้อผิดพลาด? สร้าง GitHub Issue มีคำถามหรือไอเดีย? ถามใน Discussions — ยินดีรับฟังความคิดเห็น!
คุณภาพการแปลในหน้านี้เป็นอย่างไร?

เริ่มต้นอย่างรวดเร็ว

คู่มือนี้แสดงตัวอย่างขั้นต่ำที่ใช้งานได้จริงของแพ็กเกจ qiskit-paulice เราใช้ spacetime Pauli checks เพื่อตรวจจับข้อผิดพลาดระหว่างการรัน Clifford circuit แล้วทำ postselect เฉพาะตัวอย่างที่ตรวจไม่พบข้อผิดพลาด หากต้องการเวิร์กโฟลว์แบบครบวงจรที่อธิบายละเอียดกว่าและวัดการปรับปรุงค่า fidelity ดูบทช่วยสอนเชิงลึก

ขั้นตอนของเวิร์กโฟลว์

  1. เตรียมอินพุต: Clifford payload circuit, qubit เป้าหมาย/ancilla ที่จะใช้วางการตรวจสอบ และ noise model
  2. หา spacetime Pauli checks ที่ดี แล้วเพิ่มลงใน circuit
  3. สุ่มตัวอย่างจาก circuit ที่มีการตรวจสอบ
  4. ทำ postselect เฉพาะตัวอย่างที่ตรวจไม่พบข้อผิดพลาด

1. เตรียมอินพุต​

add_pauli_checks รับ Clifford circuit ที่ลงท้ายด้วยการวัด (หรือถ้าใช้ kwarg stabilizers จะเป็น circuit ที่ไม่มีการวัด ดังในคู่มือ spacetime codes) qubit เป้าหมาย ที่จะใช้สร้างการตรวจสอบ และ noise model ที่ใช้ให้คะแนนการตรวจสอบที่เป็นตัวเลือก ในที่นี้เราสร้าง Clifford circuit แบบสุ่มที่ตื้น วางลงบนห่วงโซ่ 1 มิติของ qubit จริงบน ibm_boston จับคู่ qubit ของ payload แต่ละตัวกับ ancilla ที่อยู่ข้างเคียง (เพื่อให้การตรวจสอบไม่ต้องใช้ SWAP gate) และประมาณ noise model แบบ depolarizing อย่างคร่าว ๆ จากข้อมูล benchmark ของ backend

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit", "qiskit_aer": "qiskit-aer", "qiskit_ibm_runtime": "qiskit-ibm-runtime", "qiskit_paulice": "qiskit-paulice"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
import numpy as np
from qiskit import QuantumCircuit
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_paulice.layout import get_check_qubits
from qiskit_paulice.noise_models import NoiseModel

# Backend and a 1D chain of physical qubits to run on
backend = QiskitRuntimeService().backend("ibm_boston")
layout = [68, 69, 78, 89, 90, 91, 98, 111, 112, 113, 119, 133]

# A shallow brickwork random Clifford payload circuit
rng = np.random.default_rng(1764)
circuit = QuantumCircuit(len(layout))
circuit.h(range(circuit.num_qubits))
for d in range(4):
for i in range(d % 2, circuit.num_qubits - 1, 2):
circuit.cz(i, i + 1)
for q in range(circuit.num_qubits):
if rng.integers(0, 2):
circuit.sx(q)
if rng.integers(0, 2):
circuit.s(q)
circuit.measure_all()

# Pair each payload qubit with a neighboring ancilla to host a check (no SWAPs needed)
target_qubits, ancilla_qubits = get_check_qubits(backend.coupling_map, layout)

# A rough depolarizing noise model from backend benchmark data, used to score checks
noise_model = NoiseModel.from_backend(
backend, layout, uniform_gate_noise=True
)

circuit.draw("mpl", fold=-1)

Output of the previous code cell

2. หาและเพิ่ม spacetime Pauli checks​

add_pauli_checks ค้นหาการตรวจสอบที่มีประสิทธิภาพและมีน้ำหนักต่ำสำหรับ qubit เป้าหมายแต่ละตัว แล้วเพิ่มลงใน circuit โดยคืนค่าเป็นลำดับของอินสแตนซ์ CheckedCircuit อินสแตนซ์ CheckedCircuit เหล่านี้มีจำนวนการตรวจสอบเพิ่มขึ้นเรื่อย ๆ ตั้งแต่ 0 ไปจนถึงหนึ่งการตรวจสอบต่อ qubit เป้าหมายหนึ่งตัว การตรวจสอบแต่ละครั้งช่วยเพิ่มความสามารถในการตรวจจับข้อผิดพลาด โดยแลกกับความลึกของ circuit ที่เพิ่มขึ้นเล็กน้อย ในตัวอย่างนี้เราจะใช้ circuit ที่มีการตรวจสอบบน qubit เป้าหมายทุกตัว

from qiskit_paulice import add_pauli_checks

# The circuit has virtual qubits, so we specify our target qubits with virtual indices
target_qubits_v = [layout.index(q) for q in target_qubits]

# Add spacetime Pauli checks
checked_circuit = add_pauli_checks(circuit, target_qubits_v, noise_model)[-1]
checked_circuit.circuit.draw("mpl", fold=-1, scale=0.4, idle_wires=False)

Output of the previous code cell

3. สุ่มตัวอย่างจาก circuit ที่มีการตรวจสอบ​

ก่อนสุ่มตัวอย่าง เราจะ transpile circuit ที่มีการตรวจสอบลงบน qubit จริง (initial_layout = layout + ancilla_qubits) และแปลงเป็นชุด basis gate แบบ native ของ ibm_boston เพื่อจำลอง QPU ที่มีสัญญาณรบกวน เราสุ่มตัวอย่างด้วย backend stabilizer ของ Aer ที่มีสัญญาณรบกวน ซึ่งมีอัตราข้อผิดพลาดตรงกับ noise_model ที่ใช้เลือกการตรวจสอบ

from qiskit import transpile
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel as AerNoiseModel
from qiskit_aer.noise import ReadoutError, depolarizing_error

# Transpile once: lay the checked circuit out on our qubits and into the native basis
isa_circuit = transpile(
checked_circuit.circuit,
backend,
initial_layout=layout + ancilla_qubits,
optimization_level=0,
)

# Build an Aer noise model matching the depolarizing model used to pick checks
aer_noise = AerNoiseModel()
aer_noise.add_all_qubit_quantum_error(
depolarizing_error(noise_model.gate_noise, 2), ["cz"]
)
p = noise_model.readout_noise
aer_noise.add_all_qubit_readout_error(ReadoutError([[1 - p, p], [p, 1 - p]]))
simulator = AerSimulator(method="stabilizer", noise_model=aer_noise)

counts = (
simulator.run(isa_circuit, shots=1000, seed_simulator=1764)
.result()
.get_counts()
)
print(f"sampled {sum(counts.values())} shots")
sampled 1000 shots

4. ทำ postselect ตัวอย่างที่ตรวจไม่พบข้อผิดพลาด​

get_postselection_method แมปแต่ละ shot ไปยังเวกเตอร์ syndrome ของมัน เราเก็บไว้เฉพาะ shot ที่มี syndrome เป็นศูนย์ทั้งหมด — คือ shot ที่ไม่มีการตรวจสอบใดตรวจพบข้อผิดพลาด การทิ้ง shot ที่ถูกตั้งธงไว้จะกำจัดข้อผิดพลาดที่ตรวจพบออกจากการแจกแจงที่เหลืออยู่ ทำให้ fidelity ดีขึ้น โดยแลกกับอัตราการสุ่มตัวอย่างที่ต่ำลง ดูบทช่วยสอนสำหรับการเปรียบเทียบ fidelity เชิงปริมาณ

# Keep only the shots in which no check reported an error
ps_fn = checked_circuit.get_postselection_method()
counts_postselected = {
bs: n for bs, n in counts.items() if not ps_fn(bs).any()
}

kept, total = sum(counts_postselected.values()), sum(counts.values())
print(f"kept {kept} of {total} shots ({kept / total:.0%})")
kept 927 of 1000 shots (93%)