Error Correction
Turn a noisy code circuit into decoder inputs: detection events, a detector error model, and the matching/parity-check exports built from it. Decode with one of the six built-in decoders (qliff.qec.decoder.make), or feed the exports to pymatching, BP, or an ML decoder directly, as below.
Repetition-code memory experiment
Build a distance-
from qliff.qec import repetition_code
rep = repetition_code(distance=3, rounds=3, p=0.05)
dets, obs = rep.detector_sampler().sample(10000, seed=0)dets has shape (10000, n_detectors) of detection events; obs holds the logical-observable flips (the labels). A clean run gives all-zero syndromes.
Rotated surface-code memory experiment
The same interface scales to a 2-D code; here a distance-3 rotated surface code under depolarizing noise.
from qliff.qec import rotated_surface_code
sur = rotated_surface_code(3, 3, 0.01) # distance, rounds, p
dets, obs = sur.detector_sampler().sample(10000, seed=0)Lower per-step error rate
Export a detector error model
dem() propagates each Pauli fault to the circuit end; check_matrix() returns the parity-check H, the priors, and the observable matrix for BP decoders.
from qliff.qec import repetition_code
rep = repetition_code(distance=3, rounds=3, p=0.05)
dem = rep.dem()
H, priors, obs_matrix = dem.check_matrix()H is detectors priors carries each mechanism's probability
Decode with pymatching and measure the logical fidelity
Wire the exports into MWPM, decode the sampled syndromes, and compare to the labels. logical_fidelity returns
from pymatching import Matching
from qliff.qec import repetition_code, logical_fidelity
rep = repetition_code(distance=3, rounds=3, p=0.05)
dem = rep.dem()
H, priors, obs_matrix = dem.check_matrix()
matching = Matching.from_check_matrix(
H, weights=dem.weights(), faults_matrix=obs_matrix
)
dets, obs = rep.detector_sampler().sample(20000, seed=0)
predicted = matching.decode_batch(dets)
fidelity = logical_fidelity(predicted, obs) # 1 - logical error ratefidelity is close to
A logical error rate below the Monte-Carlo floor
Direct sampling needs about SplittingEstimator runs a ladder of physical error rates instead, spending a fixed decode budget.
from qliff.noise import SplittingEstimator
from qliff.qec import rotated_surface_code
est = SplittingEstimator(lambda p: rotated_surface_code(3, 3, p), 0.001)
res = est.estimate(p_top=0.05, p_target=0.001, levels=7, top_shots=25_000,
burn=1_500, samples=8_000, seed=1)
res.ler # 2.4e-05
res.rel_err # 0.049
res.decodes # 8200082,000 decodes resolve a rate that plain Monte-Carlo at the same budget would see about two failures at. The estimator is Pauli-only, because it works from a detector error model: see rare-event splitting for the twirl caveat under non-Pauli noise.
NOTE
The detector error model and detection sampler use Pauli-noise trajectories. For logical error rates under coherent noise, estimate the logical observable directly with the importance sampler.