Rotated surface-code memory experiment on IQM Emerald — the Junction Hackathon 2026 "Surface Code on IQM Emerald" challenge.
This repository builds the full quantum-error-correction (QEC) memory pipeline end to end:
Stim circuit -> Qiskit circuit -> IQM Emerald (Resonance) -> syndrome extraction -> decoder -> logical error rate
It is a memory experiment: we encode one logical qubit in a distance-$d$ rotated surface code, run
Full numbers, tables, and figures: RESULTS.md.
-
Pulse-level execution cuts the surface-code logical error 7.3x. Same-calibration A/B/control on rotated-17 (
$d=3$ ,$R=1$ , memory-Z, 20k shots): pulse-level (PulLA, relaxation-reset init)$p_L = 0.050$ vs circuit-level$p_L = 0.364$ . The lever is high-fidelity state preparation, not the decoder. -
QEC works (repetition code): a
$d=3$ repetition code on a good-qubit line has$\varepsilon_L = 0.059,%$ /cycle (binomial-MLE fit over a 1–12 cycle sweep), ~700x below the$d=3$ surface rate on the same chip. -
Honest above-threshold characterization of the
$d=3$ surface code, a full decoder ablation on identical hardware data, and an AI (NVIDIA Ising) pre-decoder ablation (2.3x on matched-noise simulation).
- A clean, fully documented Python package (
qec_emerald/) that completes every stage of the pipeline. - Two circuit-construction backends behind one interface:
- Standard —
stim.Circuit.generated(...), the robust default for correctness and the decoder ablation. - NVIDIA Ising — circuits built with NVIDIA's
MemoryCircuit, required if you want to run the GPU-accelerated Ising pre-decoder (the baseline explicitly points here).
- Standard —
- Calibration-aware qubit placement that maps the surface code onto a verified region of Emerald's lattice with provably zero SWAPs — directly targeting the "prove a low number of SWAPs" judging criterion.
- A decoder registry: MWPM (PyMatching), correlated MWPM, BeliefMatching, and the NVIDIA Ising pre-decoder, all consuming the same detector data for an apples-to-apples ablation.
- A simulation harness (Stim + sinter) to validate the pipeline and predict LER before spending any QPU credits.
- A research pack (
docs/research/) and an implementation guide (docs/implementation/) that explain every decision.
Emerald's median two-qubit CZ fidelity is about 99.5 %, i.e. a CZ error rate near
The consequence, stated plainly so the pitch stays defensible:
- A distance-3 logical qubit will be worse than the best single physical qubit. That is the expected result above threshold, and it is publishable.
- The suppression factor
$\Lambda = \varepsilon_d / \varepsilon_{d+2}$ will be below 1 on hardware (no error suppression yet). - We do not claim "below threshold", "fault tolerance", or "beating the raw qubit". We quantify how far above threshold Emerald sits and compare decoders on identical data.
The per-round logical error rate is fit from the per-shot LER over
which for small
qec-emerald/
README.md <- you are here
RESULTS.md <- consolidated results (headline numbers, tables, figures)
pyproject.toml <- uv project: core + [hardware] + [decoders] + [pulla] extras
.env.example / .env <- token template / your RESONANCE_KEY (git-ignored)
qec_emerald/ <- the implementation package
pipeline.py THE UNIFIER: RunConfig + run() + run_sweep() (all levers, one flow)
config.py connection + auth (reads RESONANCE_KEY, builds the Emerald backend)
circuits.py make_stim_circuit / stim_to_qiskit / simulate / to_no_reset
topology.py Emerald lattice model, patch/line search, zero-SWAP qubit map
syndromes.py raw measurements -> detection events (+ no-reset transform)
decoders.py registry: MWPM / correlated / BP+OSD / belief-matching / Spitz / masked
hardware.py circuit-level execution on Emerald + decode into an LER
pulla_runner.py pulse-level execution via PulLA (relaxation-reset init, targeted DD)
analysis.py binomial-MLE epsilon_L fit + research-grade figures
validation.py local Aer alignment proof (free, before any QPU run)
ising/ NVIDIA Ising pre-decoder bridge (.dets export + Brev driver)
experiments/ <- run.py (unified CLI + presets), ablation.py (ablations + Campaign B),
reproduce.py (sim + figures), make_figures.py, pulla_dd.py
tests/ <- unit tests (alignment, no-reset transform, decoders, pipeline, pulla)
results/ <- raw data (.json/.npz; real-hardware tracked) + figures/ (curated)
scripts/ <- fetch_emerald_topology.py, ising_brev_setup.sh
docs/
results/ <- figure gallery + per-campaign findings writeups
implementation/ <- build guide, decoders (05), PulLA (04) + Ising (02) runbooks
research/ <- archived pre-build research pack (historical snapshot)
exploration-log.md <- living: directions, roadblocks, what-would-help
paper-notes.md <- living: methodology, results, related work
plan-pulse-then-xzzx.md <- the next-experiments plan (Campaign B then C)
This project uses uv. The dependencies are split so that a single hard-to-resolve package can never block the core environment.
uv python pin 3.12
uv syncThis installs Stim, PyMatching (2.3.1, with correlated matching), sinter, Qiskit, and the utilities. Simulation is done in Stim, so you can simulate and decode immediately — no token needed.
uv sync --extra hardware # IQM Resonance SDK (iqm-client[qiskit]) - talk to the real Emerald QPU
uv sync --extra decoders # BP+OSD + belief-matching for the decoder ablation (cap numpy<=2.2.6)
uv sync --extra pulla # iqm-pulla - pulse-level access (custom DD, complex readout)Then provide your token:
cp .env.example .env
# edit .env and paste your token after RESONANCE_KEY= (from https://resonance.iqm.tech)qec_emerald/config.py reads RESONANCE_KEY from .env and forwards it to the SDK.
The Ising pre-decoder runs on a separate GPU box (e.g. an NVIDIA Brev instance).
Provision it once with scripts/ising_brev_setup.sh (clones NVIDIA/Ising-Decoding,
installs torch + the repo's own code/requirements_public_inference.txt), then drive
it from here with experiments/ablation.py predecoder. See
docs/implementation/02-ising-brev-runbook.md.
Everything runs through one unified pipeline (qec_emerald/pipeline.py) and one
CLI (experiments/run.py). It is safe by default — only --backend emerald
(or emerald-pulse) with --confirm spends QPU credits.
# List every study (presets):
uv run python experiments/run.py --list
# Reproduce the whole simulation half + regenerate every figure (free, no token):
uv run python experiments/reproduce.py
# A single study on the free Stim backend:
uv run python experiments/run.py --preset rotated17 # surface, sim
uv run python experiments/run.py --preset repetition-ler # cycle sweep + epsilon_L fit
# On real Emerald (needs .env + --extra hardware; spends credits):
uv run python experiments/run.py --preset rotated17 --backend emerald --confirm
# Pulse-level targeted DD (needs pulse-level account entitlement):
uv run --with iqm-pulla python experiments/run.py --preset pulla-dd --confirmCompare every avenue (decoder / pre-decoder / pulse-control) and see how the
project evolved, via experiments/ablation.py (see RESULTS.md):
uv run python experiments/ablation.py summary # the evolution table (free)
uv run --extra decoders python experiments/ablation.py decoder # decoder ablation
uv run python experiments/ablation.py predecoder # NVIDIA Ising on Brev
uv run python experiments/ablation.py pulse # pulse vs circuit| Tier | What | Decoder(s) | Needs |
|---|---|---|---|
| 1 |
|
MWPM | core + hardware |
| 2 |
|
MWPM | core + hardware |
| 3 | decoder ablation; dynamical decoupling; cross-patch comparison | MWPM vs correlated vs BeliefMatching vs Ising | + GPU env |
Measured results (real Emerald) are in RESULTS.md and docs/results/; the next-experiments plan is docs/plan-pulse-then-xzzx.md.
- Results: RESULTS.md (summary) and docs/results/ (figure gallery + writeups).
- Decoders / pre-decoders:
docs/implementation/05-decoders.md. - Pulse-level (PulLA):
docs/implementation/04-pulla-runbook.md. - NVIDIA Ising on Brev:
docs/implementation/02-ising-brev-runbook.md. - Next experiments (Campaign B then C): docs/plan-pulse-then-xzzx.md.
- Reasoning / methodology (living):
docs/exploration-log.md,docs/paper-notes.md. - Archived pre-build research pack (historical):
docs/research/(state of the art, decoders, references; a snapshot, not the current reference).
Built for the Junction 2026 "Surface Code on IQM Emerald" challenge. The
trustworthy converter / qubit-classification logic from IQM's official baseline
scaffold (author: Niklas Steinmann, Fraunhofer FOKUS) was vendored and re-documented
into qec_emerald/ with attribution noted inline (the baseline tree itself is not
kept in the repo). The NVIDIA Ising pre-decoder is Apache-2.0
(github.com/NVIDIA/Ising-Decoding).