Decoding¶
Stabilizer Codes left off with a syndrome in hand and a question: knowing that something's wrong isn't the same as knowing what to do about it. That's the decoder's job.
We have a syndrome. Now what?
A decoder takes the measured syndrome and infers which error pattern most likely occurred.
Main Interactive — Decode the Syndrome¶
Set up a scenario, measure the syndrome, then run the decoder and watch all four stages fill in.
Notice the decoder never looked at which button you clicked — only at the syndrome. That's the whole point: syndrome = evidence about the error, not the error itself.
Introducing Ambiguity¶
For this small code, the syndrome happens to pin down the error exactly. That won't always be true. Even here, if we allow more than one qubit to have an error at once, something interesting happens:
Both produce the exact same syndrome: an X error on q₂ flips both checks, but so does flipping q₁ and q₃ together — q₁ disagrees with q₂ (flipping \(S_1\)) while q₃ disagrees with q₂ (flipping \(S_2\)), and q₂ itself never changed. Same evidence, two different physical stories.
The decoder is therefore not simply "reading the answer." It is making an inference.
Why the Decoder Needs an Error Model¶
To choose between competing explanations, a decoder needs some assumption about how errors actually occur. The simplest useful one:
- X error on any given physical qubit: probability \(p\)
- No error on that qubit: probability \(1-p\)
If some error patterns are more likely than others under this assumption, the decoder can use that to prefer one explanation over another.
This becomes especially important later, in Hardware-Aware QEC, where the "error model" reflects real properties of physical hardware.
Interactive — Change the Noise Model¶
Take the ambiguous syndrome from above: Error A (X₂ alone, one qubit) vs. Error B (X₁ and X₃, two qubits). Drag the slider to change the assumed per-qubit error probability \(p\) and watch how confident the decoder is in each explanation.
Notice that the ranking barely moves across realistic error rates — lower-weight explanations are favored whenever errors are reasonably rare. That preference for "the explanation touching the fewest qubits" is exactly the intuition behind minimum-weight decoding, which you'll meet properly in Minimum-Weight Perfect Matching.
From Correction to Equivalence¶
Here's the uncomfortable part: a syndrome-consistent correction is not automatically a successful one.
What matters isn't recovering the exact microscopic history of the noise — it's whether the chosen correction restores the logical information. Sometimes a perfectly syndrome-consistent correction still gets that wrong, precisely because the syndrome didn't uniquely determine the error in the first place.
Advanced: logical equivalence
Formally, two corrections are "equally good" if they differ only by a stabilizer (something that doesn't touch the logical information) — but two corrections that differ by a logical operator are not equivalent, even if both are consistent with the same syndrome. That's the case B above: the decoder's guess and the true error differ by exactly \(X_1X_2X_3\), which acts as the logical \(X\) operator for this code. This full "logical equivalence class" formalism is beyond what we need here — just know the vocabulary exists.
The Scaling Problem¶
For 3 qubits, this is manageable:
But real codes use far more physical qubits — surface codes often use hundreds or thousands. The lookup-table approach doesn't survive that jump:
From One Decoder to a Family of Decoders¶
There isn't one universal decoding algorithm — different codes and situations call for different approaches:
We'll go deep on Minimum-Weight Perfect Matching (MWPM) shortly — it's the standard decoding algorithm for surface codes, and it's really just an efficient, scalable way of doing exactly what "lowest weight wins" was doing by hand above.
Takeaway¶
A decoder uses syndrome information and an error model to infer a correction that is likely to preserve the logical information. Likely — not guaranteed, as the worked example above showed.
For a large surface code, there can be an enormous number of possible error patterns. How can we find a good correction efficiently?