QEC campaigns
A QEC campaign is an experiment (schema v2) that sweeps a stabilizer code
over a noise grid and measures its logical error rate. Like every Nuclei
experiment it’s a plain, git-friendly *.experiment.yaml — hand-writable or
generated from a template.
Schema
Section titled “Schema”schema: 2type: qec_campaignname: surface-memorysource: # exactly one of `generate:` or `entry:` entry: qec/surface_memory.pynoise: model: uniform_depolarizing # built-in name or a noise/*.noise.yaml name p: range: [0.001, 0.006, 0.001] # [start, stop, step] — or `values: [...]`decoders: - pymatching # and/or fusion_blossomcollect: max_shots: 100000 # stop each task at whichever limit comes first max_errors: 500workers: auto # 'auto' or a positive integernotes: optional free textsource — exactly one of two shapes
Section titled “source — exactly one of two shapes”generate:— a built-in Stim generator:{ code, distances, rounds }.codeis a generator target (e.g.surface_code:rotated_memory_z),distancesa list,roundsan integer or"<n>d"(n × distance).entry:— a project-relative Python file definingnuclei_circuits(noise) -> dict[str, stim.Circuit]. The runner calls it once per noise point with the resolved noise dict and collects the returned{label: circuit}. This is the editable path — you own the circuits.
model names a built-in or project noise model.
p is a sweep parameter: a range: [start, stop, step] (stop-inclusive within
an epsilon) or an explicit values: [...] list. For an entry: source the
resolved dict handed to nuclei_circuits is {p, ...stim generator args}.
decoders, collect, workers
Section titled “decoders, collect, workers”One task is generated per (label × noise point × decoder). collect bounds each
task by max_shots and/or max_errors (first to hit wins). workers sets
sinter’s process pool.
The d=<n> label convention
Section titled “The d=<n> label convention”The threshold panel fits Λ by grouping results by code distance. A
generate: source tags distance structurally. An entry: source emits
free-form labels, so to join the Λ fit it should name its circuits with the
distance embedded: d=3, d=5, d=7 (also d3, case-insensitive). Nuclei
parses that convention into a numeric distance; a label without one still
plots, it just doesn’t join a Λ fit. The built-in templates follow this
convention already.
Run directory
Section titled “Run directory”Each campaign run writes under
experiments/<name>/runs/<timestamp-id>/: a manifest.json reproducibility
record, the sinter-native stats csv, and per-point snapshot.json /
metrics.json. Resuming a stopped campaign reuses that csv so completed
tasks are never re-sampled. See
Reproducibility for the manifest shape and
its honest limits.