RustQEC 0.3 · Development

Circuit syntax

A .stim file contains one instruction per line: NAME(arguments) targets. Arguments and targets depend on the instruction. # introduces a comment; REPEAT N { ... } repeats a block. Qubit targets are zero-based integers. Use rstim circuit stats --in circuit.stim to parse a file and inspect its measurement, detector and observable counts.

InstructionRoleExample
R, RX, RYPrepare a qubit in a Pauli basis; restores a lost atomR 0 1
H, S, CX, CZClifford evolution on available qubitsCX 0 1
X_ERROR(p), DEPOLARIZE1(p), DEPOLARIZE2(p)Stochastic Pauli noiseX_ERROR(0.01) 0
M, MX, MY, MRMeasure, optionally resetM 0 1
DETECTORDeclare a measurement parity relative to the noiseless referenceDETECTOR rec[-1]
OBSERVABLE_INCLUDE(k)Add measurement parity to logical observable kOBSERVABLE_INCLUDE(0) rec[-1]
TICK, coordinatesTiming and drawing annotationsTICK

A record target rec[-k] refers to the kth most recent stored bit at that point in execution. It is not a qubit index. Each detector and observable computes a parity; these declarations do not perform another measurement. The Get started circuit explains the example step by step.

RustQEC reads Stim-style syntax, but support differs by execution, analysis and export mode. The support contract scopes compatibility; accepted simulator instructions are not automatically accepted by every decoder. Stim's upstream gate reference is background for overlapping instructions, not a promise of complete compatibility.

Atom-loss extensions

LOSS(p) q... independently removes each still-present target with probability p. Loss persists until reset. Ideal single-qubit gates do nothing to absent atoms; a two-qubit interaction is skipped if either partner is absent. In the current executor, DEPOLARIZE2 also skips an incomplete pair. These execution rules define this simulator's model and do not claim to describe all physical loss mechanisms.

InstructionStored recordReset
ML / MZLloss flag, then Z-value bit for each targetNo
MRL / MRZLloss flag, then Z-value bit for each targetYes, after readout
MXL, MYLloss flag, then X/Y-value bitNo
MRXL, MRYLloss flag, then X/Y-value bitYes

Flag 1 means the atom is absent at readout. An uninverted lost measurement stores value 1 as a placeholder, not a physical outcome. Reset restores the atom after recording the flag. The simulator's X/Y loss readouts do not extend the native loss decoder: v1 accepts Z loss readouts only. A decoder's result must not depend on the chosen placeholder.

Blinded logical input marker

TICK[rstim:logical_flip_point] marks the insertion point for a private logical Pauli in a blinded dataset. It must occur exactly once at top level, after ideal preparation and before positive-probability noise. A comment with similar text is not the marker. The training tutorial explains how the labels and masks relate.

Native loss decoder acceptance

The following is rendered from the canonical v1 contract. It defines parser and compiler acceptance, resource limits, bundle validation and failure codes. Acceptance of an external producer is determined by circuit conformance; release support promises additionally have a finite tested scope. See the support boundary.

Status: stable contract (versioned). This document is the public specification of the circuit subset accepted by rstim decode and produced by rstim dataset export. It exists so that dataset producers outside this repository can generate decodable datasets without reading the compiler source.

The reference implementation is rstim/src/unified_cli/decode/compiler.rs (compile_circuit and normalize_supported_circuit). Where this document and the implementation disagree, the implementation is wrong or this document is stale; both are pinned together by the test suite, so please file an issue.

1. Scope and versioning

  • Subset version: v1.
  • The decoder accepts exactly one circuit per dataset, stored as circuit.stim inside a public dataset bundle (see §7).
  • Any circuit meeting every requirement in §2–§6 is accepted, regardless of which software generated it. Acceptance is capability-checked per circuit; there is no allow-list of generator programs or code families.
  • Widening the subset (new instructions, REPEAT, additional loss-visible bases) requires a new subset version. Rejections that v1 specifies must stay rejections within v1.

2. File-level requirements

RequirementError code on violation
Circuit is valid UTF-8 and parses under rstim::validation::parse_and_validateinvalid_dataset / unsupported_circuit
Circuit is flat: no REPEAT blocksunsupported_circuit ("outside the flat native Mid-SWAP subset")
Measurement/detector/observable/sweep-bit counts match manifest.jsoninvalid_dataset
No sweep bits; between 1 and 64 observablesunsupported_circuit

3. Instruction subset

Each instruction is classified as kept for analysis (present in the DEM extraction circuit), structural (consumed by the loss compiler itself), or rejected.

InstructionClassNotes
LOSS q...structuralDeclares a loss-opportunity site. Not itself analyzed; it opens the window in which a later loss-visible readout may herald a loss. Targets must be plain qubits.
ML, MZLstructural → MLoss-visible Z readout. Emits two measurement records: flag then value (see §4).
MRL, MRZLstructural → MRLoss-visible Z readout with reset. Same two-record layout; closes the loss window for that wire.
MXL, MYL, MRXL, MRYLrejectedNon-Z loss-visible bases are future work.
HkeptAlso tracked as a basis-change site for envelope compilation.
CX, CNOT, ZCXkept (decomposed to H–CZ–H)Targets must form complete, pairwise-disjoint qubit pairs within one instruction.
R, RZkeptCloses any open loss window for the targeted wires.
X_ERROR, DEPOLARIZE1, DEPOLARIZE2keptThe only noise channels in v1. All probabilities must be finite and < 0.5 at DEM level.
QUBIT_COORDS, SHIFT_COORDS, TICK, DETECTOR, OBSERVABLE_INCLUDEkeptSemantically inert annotations for loss-envelope construction; they remain in the analysis circuit so detector coordinates are preserved.
anything else (incl. Y_ERROR, Z_ERROR, PAULI_CHANNEL_*, CORRELATED_ERROR, MPP, S, SWAP, …)rejectedunsupported_circuit naming the instruction.

Loss-visible readouts with inline noise arguments (ML(p) ...) are rejected.

4. Loss-record layout

For every loss-visible readout the measurement record interleaves:

  1. flag record — 1 iff the atom was heralded lost at this readout;
  2. value record — the measurement value bit.

The flag occupies the earlier measurement index. During compilation the flag position is materialized as an MPAD placeholder so record indices stay stable. Consequences:

  • DETECTOR and OBSERVABLE_INCLUDE must reference value records, never flag records (unsupported_circuit, "detectors and observables must reference value bits, not loss flags").
  • Each readout must have at least one LOSS site on that wire since the last reset (unsupported_circuit, "no LOSS opportunity since reset").
  • A readout without reset (ML/MZL) is terminal for its wire: no subsequent instruction may target that wire (unsupported_circuit, "ML must be terminal for each measured physical wire").

5. Detector error model requirements

The kept-for-analysis circuit (loss structure removed, noiseless variant used for reference samples) must yield a DEM satisfying:

  • every detector carries at least x, y, t coordinates;
  • every error probability is finite and < 0.5 (zero-probability errors are ignored);
  • after DEM decomposition, every error component touches at most two detectors (graphlike). Non-graphlike remnants are rejected (unsupported_circuit, "non-graphlike Pauli effect");
  • observable-only error components are rejected for the matching backend ("observable-only Pauli effects are unsupported by envelope-matching");
  • at least one decodable effect and one graph edge exist.

Edges are classified for diagnostics: same (x, y) → time-like, otherwise space-like, single-detector → boundary.

6. Resource limits

LimitValueError on exceed
Envelope-MLE candidates per loss measurement100 000unsupported_circuit ("exceeds candidate limit")
Unique primitive loss probes100 000unsupported_circuit ("exceeds primitive probe limit")
Primitive detector/observable symptom terms10 000 000unsupported_circuit ("exceeds primitive symptom-term limit")
Measurements / detectors10 000 000 eachlayout error
Observablesmin(64, 1 000 000)unsupported_circuit
Parity terms in measurement transforms100 000 000layout error
Transform working memory512 MiB transform / 256 MiB blocklayout error

Primitive effects are deduplicated by (instruction boundary, qubit, Pauli) and evaluated in one reverse detector-sensitivity traversal. Envelope-Matching uses the primitive-to-edge union directly and therefore does not enumerate the composite Envelope-MLE candidate set. Successful decode stats expose primitive_probe_count, primitive_symptom_terms, and loss_envelope_candidate_count so generator growth remains observable.

7. Dataset bundle contract (consumer side)

rstim decode accepts a directory containing exactly:

  • manifest.json — format rstim_decoder_dataset schema v1, or qude_decoder_dataset schema v3 (Decoder-Server interchange);
  • circuit.stim — a v1-subset circuit;
  • shots.b8 — lsb_first bit-packed measurement rows, width equal to the circuit's measurement count, zero padding.

SHA-256 hashes of both files, row widths, shot count, file size, and (for the rstim format) the derived dataset_id are verified before compilation. Violations report missing_dataset_file, invalid_dataset, or unsupported_dataset_mode. Decode-time failures report decode_timeout or decode_infeasible (exit code 3); all other failures exit 2.

8. Relationship to built-in generators

rstim circuit gen --code surface_code --task rotated_memory_z_midswap emits circuits inside this subset, and the decode regression suite replays them. Membership in the subset is the contract, not the generator. The compiler performs no generator identification: any circuit satisfying §2–§6 is accepted, whether hand-written, generated by this repository, or produced by third-party tooling. Conformance fixtures that bypass the built-in generators live under rstim/tests/ and are added together with this specification's rollout.

9. Error-code summary

CodeMeaningExit
unsupported_circuitcircuit violates §2–§62
invalid_datasetmanifest/hash/layout mismatch2
missing_dataset_filebundle file absent or unreadable2
unsupported_dataset_modedataset is not measurements_blinded2
decode_timeoutper-shot time limit hit3
decode_infeasiblemodel infeasible for a shot3