Přeskočit na hlavní obsah
Tento projekt je v betě. Našel jsi chybu? Otevřít issue na GitHubu. Máš otázku nebo nápad? Zeptej se v Discussions — rádi si poslechneme tvou zpětnou vazbu!
Jaká je kvalita překladu na této stránce?

Rychlý start

Tento průvodce ukazuje minimální funkční příklad balíčku qiskit-paulice. Pomocí časoprostorových Pauliho kontrol detekujeme chyby během provádění Cliffordova obvodu a poté postselekcí ponecháme pouze vzorky, u kterých nebyla detekována žádná chyba. Podrobnější end-to-end postup, který kvantifikuje zlepšení věrnosti, najdeš v podrobném tutoriálu.

Kroky postupu

  1. Připrav vstupy: Cliffordův obvod s užitečným zatížením, cílové/pomocné qubity pro kontroly a model šumu.
  2. Najdi dobré časoprostorové Pauliho kontroly a přidej je do obvodu.
  3. Vzorkuj obvod s kontrolami.
  4. Postselekcí ponech pouze vzorky, u kterých nebyla detekována žádná chyba.

1. Příprava vstupů​

add_pauli_checks přijímá Cliffordův obvod zakončený měřeními (nebo, s argumentem stabilizers, obvod bez měření, jako v průvodci časoprostorovými kódy), cílové qubity, které se použijí k implementaci kontrol, a model šumu sloužící k hodnocení kandidátních kontrol. Zde sestavíme mělký náhodný Cliffordův obvod, rozložíme ho na 1D řetězec fyzických qubitů na ibm_boston, každému qubitu užitečného zatížení přiřadíme sousední pomocný qubit (aby kontrola nepotřebovala hradla SWAP) a z dat benchmarku backendu odvodíme hrubý depolarizační model šumu.

# 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. Nalezení a přidání časoprostorových Pauliho kontrol​

add_pauli_checks vyhledá efektivní kontroly s nízkou váhou pro každý cílový qubit a přidá je do obvodu; vrací posloupnost instancí CheckedCircuit. Instance CheckedCircuit obsahují rostoucí počet kontrol, od 0 kontrol až po jednu kontrolu na každý cílový qubit. Každá kontrola zlepšuje schopnost detekce chyb za cenu mírně větší hloubky obvodu. V tomto příkladu použijeme obvod s kontrolou na každém cílovém qubitu.

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. Vzorkování obvodu s kontrolami​

Před vzorkováním transpilujeme obvod s kontrolami na fyzické qubity (initial_layout = layout + ancilla_qubits) a do nativní sady bázových hradel ibm_boston. Abychom napodobili zašuměný QPU, vzorkujeme se zašuměným stabilizátorovým backendem Aer, jehož chybovosti odpovídají noise_model použitému k výběru kontrol.

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. Postselekce vzorků bez detekované chyby​

get_postselection_method přiřadí každému shotu jeho vektor syndromu; ponecháme pouze shoty s nulovým syndromem — tedy ty, ve kterých žádná kontrola nedetekovala chybu. Zahozením označených shotů se z přeživšího rozdělení odstraní detekované chyby, čímž se zlepší jeho věrnost za cenu nižší rychlosti vzorkování. Kvantitativní srovnání věrnosti najdeš v tutoriálu.

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