Checks
qiskit_paulice.checks
Functionality for finding effective spacetime Pauli checks.
add_pauli_checks
add_pauli_checks(circuit, target_qubits, noise_model, cost='gamma', cost_nshots=10000, method='windowed', ancilla_qubits=None, check_creg_name='checks_c', check_qreg_name='checks_q', seed=None, stabilizers=None)
Add spacetime Pauli checks to a Clifford circuit.
Checks are found for the circuit’s terminal measurements or, when stabilizers is given, for stabilizers of the state the circuit prepares:
- Measurements (
stabilizers=None):circuitends with Z-basis measurements. A check is valid if its forward-propagated image is diagonal on the measured qubits, so its syndrome bit is the parity of the check ancilla and the payload bits listed incheck_support. Thecostcounts an error as logical if it flips a measured bit. The checks are only valid for this measurement basis. - Stabilizers (
stabilizersgiven):circuitcontains no measurements. A check is valid if it back-propagates to a stabilizer of the input state , so its syndrome is the ancilla bit alone and it stays valid whatever is measured afterwards. Thecostcounts an error as logical if it flips one of the given stabilizers of the prepared state; with"all"that is any error that changes the state. The returned circuits measure only the check ancillas. Append your own basis rotations and payload measurements, then rebuild theCheckedCircuitwithdataclasses.replace()so post-selection sees the final classical register layout.
The check picking algorithm finds valid, low weight checks on each target qubit in the order they are specified in target_qubits and chooses the check which provides the most error detection coverage (i.e. minimizes the cost value). Once a check is committed on target_qubits[0], it will be set for the remainder of the algorithm and a search for a good check on target_qubits[1] will begin. For this reason, the ordering of target_qubits can have some impact on the set of checks produced by the function.
This function produces CheckedCircuit instances containing numbers of checks ranging from 0 to one check per target qubit. It can be instructive to view the convergence of the cost function as more checks are added, as one may see convergence of the cost using fewer checks.
Parameters
-
circuit (QuantumCircuit) – The Clifford circuit to dress with spacetime Pauli checks. Unless
stabilizersis given, the circuit must be terminated with a measurement on at least one qubit, and a measured qubit may have nothing but barriers after its measurement (aValueErroris raised otherwise). Withstabilizersit must contain no measurements. The circuit may be defined on virtual or physical qubits. If the circuit has a layout, the user must provideancilla_qubits. -
target_qubits (Sequence[int]) – Qubit indices of
circuitwhich will be used to entangle the check qubits to the payload. Whencircuithas a layout (ISA mode), these are physical qubit indices, in the same index space asancilla_qubits. -
noise_model (NoiseModel) – A noise model describing the effect of noise on the target device. This model will be used to estimate the effect of a given check during the check picking process. While one can generate a noise model from learned Pauli-Lindblad noise, a rougher approximation of the noise generated from backend benchmark data is often sufficient. Ancilla/target edges introduced by check insertion that aren’t in the supplied
GateWiseNoiseorLayeredGateNoiseare auto-inferred (median rate per Pauli pair across the supplied data); supply them explicitly to override. Idling noise is not supported and raises aValueError. -
cost (Literal['gamma', 'LER']) –
Metric to optimize. Can be
"gamma"or"LER"(logical error rate)."gamma": The gamma value associated with the inverse logical noise channel (i.e. the noise channel consisting of errors within the measurement lightcone that are undetectable by the checks)."LER": The empirical logical error rate after postselection. Performs Monte Carlo simulations to calculate the fraction of postselected shots affected by uncovered logical noise.
-
cost_nshots (int) – Number of Monte Carlo shots used by Monte Carlo-based cost metrics (currently only
"LER"). -
method (Literal['windowed', 'genetic', 'windowed_genetic']) –
Check picking method (
"windowed","genetic", or"windowed_genetic"). Each method will add checks totarget_qubitssequentially. Once a check is committed to a given target qubit, it will not be undone as more checks are added. Each method picks checks which provide maximum error detection capability (i.e. lowestcost)."windowed": Sample small subsets of the wires on each target qubit to find good checks"genetic": Evolve a set of candidate checks from the full wire-space of each target qubit"windowed_genetic": Run a genetic search within random windows of wires on each target qubit
-
ancilla_qubits (Sequence[int] | None) – List of physical qubit indices (one per index in
target_qubits) specifying where to place the check ancillas in the output circuit. Required whencircuit.layoutis notNone.ancilla_qubits[i]will share entangling gates withtarget_qubits[i]when implementing thei\ th check. -
check_creg_name (str) – Name of the classical register for check measurements (default: “checks_c”)
-
check_qreg_name (str) – Name of the quantum register holding the check ancillas in the output circuits (default: “checks_q”). Ignored in ISA mode.
-
seed (int | None) – Random seed for controlling randomness during the search for good checks. While this seed controls some randomness in the algorithm, some non-determinism still exists when using
LERcost function, or either variety of genetic check picking method. The combination ofcost="gamma"andmethod="windowed"is fully deterministic ifseedis notNone. -
stabilizers (Sequence[Pauli |str] | Literal['all'] | None) – Stabilizers of the state
circuitprepares to find checks for, orNoneto find checks for the circuit’s terminal measurements."all"protects the whole state. Otherwise a sequence ofPaulior labels on the qubits ofcircuitin Qiskit convention, so the rightmost character of a label acts on qubit0; a sign is permitted and ignored. In ISA mode they must act as the identity on every qubit outside the payload. Each must stabilize the prepared state, i.e. propagate back through the circuit to a product ofZs (aValueErroris raised otherwise). Since no payload qubit is measured in this mode,readout_noiseonly affects the check ancillas and so never counts toward the cost.
Returns
A list of CheckedCircuit instances – instances containing the bare circuit with no checks and one for each added check. The final element in the output contains the CheckedCircuit with checks on every target qubit, assuming a valid set of checks could be found.
Each element’s circuit is assembled the first time it is read, not before this function returns. Check metadata – cost and the qubit tuples – is always available, so reading only [c.cost for c in result] to watch the cost converge assembles nothing, and reading only result[-1].circuit assembles one circuit instead of all of them. If the requested gate set cannot express the inserted checks, the resulting warning is raised on that first read rather than here.
Raises
- ValueError –
circuithas no entangling gate, so there is nothing for a check to protect; a qubit has an instruction other than a barrier after its measurement; or a measurement targets a clbit outside every classical register. - ValueError –
circuithas neither terminal measurements norstabilizers, or has both. The checks are anchored at exactly one of the two. - ValueError – An entry of
stabilizersacts on a different number of qubits thancircuit, is not a stabilizer of the prepared state (it does not propagate back to a product ofZs), or in ISA mode acts on a qubit outside the payload;stabilizersis an empty sequence or a string other than"all". - ValueError –
target_qubitsare out of range, or in ISA mode are not payload qubits. - ValueError – In ISA mode
ancilla_qubitsis missing, has a different length thantarget_qubits, is out of range, repeats a qubit, or overlaps the payload. - ValueError –
check_creg_nameorcheck_qreg_nameequals the other or the name of a registercircuitalready has. - ValueError –
costis not"gamma"or"LER";noise_modelis empty, setsidling_noise, or has a rate outside its allowed range (seeNoiseModel).
Example
Checks for a circuit’s measurements post-select its results directly:
from qiskit import QuantumCircuit
from qiskit_paulice import NoiseModel, add_pauli_checks
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.cx(0, 1)
circuit.s(1)
circuit.cx(1, 2)
circuit.measure_all()
checked = add_pauli_checks(circuit, [1], NoiseModel(gate_noise=1e-3))[-1]
accept = checked.get_postselection_method() # takes a bitstring of ``checked.circuit``Checks for stabilizers leave the payload unmeasured. Measure it however you like, then rebind the checked circuit so post-selection reads the final registers:
from dataclasses import replace
from qiskit import ClassicalRegister
payload = circuit.remove_final_measurements(inplace=False)
noise = NoiseModel(gate_noise=1e-3)
checked = add_pauli_checks(payload, [1], noise, stabilizers="all")[-1]
measured = checked.circuit.copy()
measured.h(range(3)) # any basis rotation of the payload
meas = ClassicalRegister(3, "meas")
measured.add_register(meas)
measured.measure(range(3), meas)
checked = replace(checked, circuit=measured)
accept = checked.get_postselection_method() # takes a bitstring of ``measured``References
S. Martiel and A. Javadi-Abhari, Low-overhead error detection with spacetime codes, arXiv:2504.15725. Supplementary Sections II to VI describe how effective checks are found.