Development · master
About these docs

The experiment at a glance

Keep the loss flag alongside each measurement. The decoder uses that information to predict the logical outcome.

  1. 01Generatecircuit.stim
  2. 02Samplepublic + private
  3. 03Decodepublic → predictions
  4. 04Checkpredictions + answers

Data boundary Only public records enter the decoder. Private answers are used at the final scoring step.

Before you start: install & working directory

Install the CLI below, or use a native binary. The default CLI includes envelope matching; no optional ILP solver is needed.

cargo install --locked rustqec-cli --version 0.3.0

Run the steps in order in a fresh directory, with rustqec on PATH and Python 3 installed. The example ZIP contains run.sh, check.py and a README; after extracting it, run sh run.sh to execute all four steps.

This site is Development · master; the installation command pins v0.3.0. Version details.

STEP 01 / 04

Generate the circuit

Create a distance-3 Mid-SWAP memory circuit. Set Pauli noise and atom-loss probabilities separately.

rustqec circuit gen \
  --code surface_code --task rotated_memory_z_midswap \
  --distance 3 --rounds 2 --noise 0.002 \
  --operation-loss-probability 0.002 \
  --measurement-loss-probability 0.003 \
  --out circuit.stim

Creates circuit.stim — the circuit used throughout this tutorial.

STEP 02 / 04

Sample 64 shots

Export loss-visible measurements and keep the answer key in a separate bundle.

mkdir -p data
rustqec dataset export \
  --circuit circuit.stim --shots 64 --seed 7 \
  --mode measurements_blinded --logical-x-qubits 1,8,15 \
  --public-out data/public --private-out data/private
DECODER INPUT

data/public/

Circuit, manifest and measurement rows in shots.b8.

SCORING ONLY

data/private/

Logical-error targets in answers.b8, input masks and a manifest.

Changing the layout? The logical-X support 1,8,15 is specific to this circuit. Recompute it and regenerate both bundles together.

STEP 03 / 04

Decode public records

Envelope matching reads the public bundle and predicts one logical outcome per shot.

rustqec decode --decoder envelope-matching \
  --dataset data/public \
  --out predictions.b8 --stats-out decode-stats.json

Creates predictions.b8 and decode-stats.json.

What is in the output?

The prediction file contains one byte per shot in this one-observable example. Statistics report shot counts, distinct loss patterns, compilation and decoding time, and failures.

Compare matching and exact MLE →

STEP 04 / 04

Check the predictions

Save check.py ↓ in your working directory (also included in the example ZIP), then run:

python3 check.py
Or copy the complete check into your terminal
python3 - <<'PY'
import json
from pathlib import Path

public = json.loads(Path('data/public/manifest.json').read_text())
private = json.loads(Path('data/private/manifest.json').read_text())
stats = json.loads(Path('decode-stats.json').read_text())
predictions = Path('predictions.b8').read_bytes()
answers = Path('data/private/answers.b8').read_bytes()
assert public['dataset_id'] == private['dataset_id'], 'Mismatched datasets'
assert public['circuit']['observables'] == 1, 'This check expects one observable'
assert (
    len(predictions) == len(answers) == public['shots'] == stats['shot_count']
), 'Incomplete rows'
assert all(bit in (0, 1) for bit in predictions + answers), 'Invalid padding bits'
errors = sum(predicted != answer for predicted, answer in zip(predictions, answers))
print(f"Decoded shots: {stats['shot_count']}")
print(f"Loss patterns: {stats['distinct_loss_patterns']}")
print(f"Logical errors: {errors} / {public['shots']}")
PY
EXPECTED RESULT · SEED 7
Decoded shots: 64
Loss patterns: 10
Logical errors: 0 / 64

You have completed the full circuit → sample → decode → score workflow.

Interpretation Zero errors in 64 shots checks this example. It does not establish a zero logical error rate.

Troubleshooting & support

The decoder reports unsupported_circuit

The input falls outside the compiler’s acceptance rules. Start with the exact circuit above, then compare your changes with the support contract. A rejection is not a logical prediction.

The output differs from the example

Check the CLI version, seed 7, 64 shots, circuit parameters and decoder choice. Use a fresh directory and rerun all four steps. Do not score a failed or incomplete decoding run.

The check reports mismatched datasets or incomplete rows

Regenerate the public and private bundles together, then rerun decoding. Both manifests must share a dataset_id, and prediction, answer and statistics counts must agree. Do not combine files from different runs.

Should I apply the private input masks again?

No. The physical logical-error targets already account for the hidden logical-input masks. Compare predictions directly with answers.b8.

Take the next step

Inspect a circuit visually →