BP / OSD / LSD Decoder Sandbox
Run a quantum LDPC decoder end to end on a Tanner graph. A parity-check matrix $H$ links checks $C_i$ to qubits $q_j$; an error $e$ gives the syndrome $s = He$. Belief propagation passes log-likelihood messages along the edges and turns them into a belief per qubit. When BP stalls on a degenerate error, a post-processor finishes the job: OSD solves $H\hat e = s$ on the most likely qubits, LSD grows clusters around the unsatisfied checks and solves each one locally. Every message, belief and solve is drawn and written out, and the result is judged against the stabilizer group, not just the syndrome.
1 · Instance
Custom matrices (rows of 0/1)
2 · Decoder
Worked examples load, then step through
3 · Run
Code
Syndrome $s = He \bmod 2$
Parity-check matrix $H \in \mathbb{F}_2^{\,m\times n}$
Beliefs posterior LLR $\Lambda_j$
Convergence per iteration
Messages
Compare rules and schedules same instance, no early stop
Exact answer brute force over all $e'$ with $He' = s$
Step log
Notes
What BP computes
Given the syndrome $s$, BP estimates the marginal $P(e_j = 1 \mid s)$ for every qubit, written as the log-likelihood ratio $\Lambda_j = \log \frac{P(e_j=0\mid s)}{P(e_j=1\mid s)}$. Negative means "probably flipped". The prior is the channel, $L_j = \log\frac{1-p}{p}$. On a cycle-free Tanner graph the marginals are exact after as many iterations as the graph is deep; with cycles they are an approximation, and short cycles (4-cycles are unavoidable in CSS codes) make it worse.
Update rules
Check to qubit: $\lambda_{i\to j} = (1-2s_i)\,2\tanh^{-1}\prod_{j'\in N(i)\setminus j}\tanh\frac{\mu_{j'\to i}}{2}$. A satisfied check pushes its qubits toward 0, an unsatisfied one toward 1, never harder than its least certain other qubit. The page evaluates the product pairwise in the box-plus form, which has no overflow. Min-sum replaces the magnitude by $\alpha\min|\mu| - \beta$ (floored at 0): cheaper and overconfident, which sometimes helps and sometimes hurts.
Qubit to check: $\mu_{j\to i} = L_j + \sum_{i'\neq i}\lambda_{i'\to j}$. Flooding updates all checks, then all qubits. The serial schedule sweeps the qubits in order and uses fresh messages immediately; it converges faster and breaks symmetric ties.
Stopping and success
The usual rule stops at the first iteration whose hard decision satisfies $H\hat e = s$. That is a syndrome test, not a correctness test: the Steane example stops after one iteration on a weight-4 output that is a logical error, while two more iterations would have found the weight-1 error.
For a CSS code the residual $r = e \oplus \hat e$ is harmless if it is a stabilizer, i.e. in the row space of the other check matrix. It is a logical error if it anticommutes with a logical operator of the other type. This page tests both; for a classical code only $r = 0$ counts.
Why degeneracy breaks BP
Two errors that differ by a stabilizer have the same syndrome and the same effect; the best decoder only needs the right equivalence class. BP does not know classes. If $e$ and $e' = e \oplus$ (stabilizer) are equally likely, every qubit in their symmetric difference gets belief about one half, so the hard decision flips all of them or none, and neither satisfies the syndrome. The marginals can be exactly right while the decision is wrong: compare the bars with the brute-force ticks in the toric and Shor examples.
OSD
Order the qubits from most to least likely flipped ($\Lambda_j$ ascending). Take the first $\mathrm{rank}(H)$ independent columns as the basis $S$, set the rest $T$ to zero and solve $H_S \hat e_S = s$ by Gaussian elimination: this is OSD-0 and always satisfies the syndrome. Higher orders also try patterns on $T$: OSD-E tries all $2^\lambda$ patterns on the $\lambda$ most likely bits of $T$, OSD-CS tries every weight-1 pattern on $T$ and every weight-2 pattern inside the first $\lambda$. For each pattern $\hat e_S$ is re-solved and the lightest total solution wins.
LSD
Start one cluster at every unsatisfied check. In each round every invalid cluster adds one neighbouring qubit, the one with the lowest $\Lambda_j$, together with all checks on that qubit; clusters that meet merge. A cluster is valid when its local syndrome lies in the column space of its local matrix. Once all clusters are valid, each is solved on its own by OSD and the pieces are joined. The global solve of OSD becomes several small independent solves.