QECTOR BP-OSD
Source of authority: v1.0.0 reference manual, chapters 8, 9.
Where BP-OSD applies
BP-OSD is the only decoder defined for arbitrary GF(2) parity-check
matrices (manual 11.1). The matching decoders reject any code with
a qubit of degree > 2; the Union-Find rejection is the explicit
contract, not a bug (manual 20.8). BP-OSD handles:
- qLDPC codes (bicycle, bivariate-bicycle, hypergraph-product).
- Color codes (
codes.color_code).
- Any code with hyperedges (weight > 2 mechanisms).
- Codes fed by a DEM with mechanisms that cannot be collapsed to
graph edges.
The belief-propagation update (manual 8.1)
Let gamma_q = LLR_prior(q) + sum_{c in N(q)} m_{c->q} be the
posterior LLR of qubit q. The check-node update is the box-plus
kernel in the log domain:
phi(x) = -ln(tanh(x/2)) = ln coth(x/2) for x > 0
phi(0) = +inf
phi(x) -> 0 for large x
Three schedules are supported:
| Schedule |
Formula |
Notes |
| Exact sum-product |
`m_{c->q} = sgn * phi( sum_{q'} phi( |
m_{q'->c} |
| Min-sum |
`m_{c->q} = sgn * min_{q'} |
m_{q'->c} |
| Relay (layered) |
same kernel; checks processed sequentially |
faster convergence on loopy graphs |
The Rust implementation evaluates phi exactly below 0.25 and
uses a 2^16-entry linearly-interpolated table above it, with
maximum interpolation error about 2e-7 on the tabulated range.
The OSD stage (manual 8.2)
- OSD-0: sort columns by ascending
|LLR| (least reliable
first), extract a rank-r independent basis by GF(2) Gaussian
elimination, keep the BP hard decision on the free (most
reliable) columns, solve the basis for the residual syndrome.
- OSD-W (
osd_order >= 1): additionally sweep combinations of
the W = max(2 * osd_order, 6) least-reliable columns and keep
the lowest-weight faithful candidate.
Theorem 11 (residual-solve faithfulness, manual 8.2)
Let B be a rank-r column basis of H, and let
s_eff = s + H_fixed e_fixed (mod 2) be the residual after
fixing the reliable columns. Then the system
H_B e_B = s_eff has a solution whenever s is reachable, and
every OSD candidate
c = e_fixed + (e_B on B, 0 elsewhere) satisfies H c = s.
The algebraic guarantee is independent of BP convergence
quality: LLRs only influence which coset is selected, never
whether the returned correction reproduces the syndrome.
The reliability partition and component-wise solving (manual 9)
- Threshold
tau on |LLR|. Split qubits into
Q_rel = {q : |gamma_q| >= tau} and Q_amb = {q : |gamma_q| < tau}.
- Freeze
Q_rel to hard decisions e_rel. Compute the residual
s_res = s + H_rel e_rel (mod 2). If s_res = 0 the decode is
complete.
- Otherwise the Tanner-induced subgraph on
Q_amb splits into
connected components C_k. Each component with
size <= K_max (default 12) is solved exactly by enumeration
over its 2^k error patterns, minimizing weight among faithful
solutions. Larger components use a restricted OSD-0 over the
cluster columns.
Theorem 12 (component-wise faithfulness, manual 9.2)
Let c = e_rel xor (xor_k e_k), where each component is solved
with H_{C_k} e_k = s_res restricted to its support. Then
H c = s (mod 2), independently of the threshold tau.
Tuning kwargs (manual 16.2 - Provisional)
The BPOSDDecoder tuning kwarg names are stable; defaults may shift
in 1.x. Verify the live values via introspection; do not hard-code.
bp_method: "sum_product" (default) or "min_sum".
osd_order: integer, default 0; >= 1 enables OSD-W with
W = max(2 * osd_order, 6).
max_bp_iters: integer; default typically 50.
tau: reliability threshold; default typically 0.0 (no
ambiguity clustering).
Worked example (manual 8.5)
H = [[1,1,0],[0,1,1]] over F2, syndrome s = [1,0].
- BP's hard decision:
e_hard = [1,0,0], residual zero, decode
returns immediately. H e = [1,0] = s.
- If BP were uncertain and produced
e_hard = [0,1,0], residual
s_eff = [0,1]. The most reliable column (column 1) is fixed at
its BP hard decision 0; the basis {0, 2} must solve
H_B e_B = s_eff. Column 2 alone contributes [0,1], so
e_B = (0, 1) on the basis columns and c = [0,1,1]. H c = s.
The example shows the division of labour: BP proposes, OSD
repairs, and the repaired correction always satisfies the
syndrome.
Numerical stability
The phi LUT keeps the update numerically stable across the full
dynamic range. qector_decoder_v3.bp_osd exposes the
plausibility_guard; the regression suite includes
test_bp_numerical_stability.py and test_bposd_osd_orders.py.
Common pitfalls
- Calling
bposd on a graphlike code -> it works, but the
matching decoders are faster on tested configurations. Use
bposd only when the parity-check matrix is non-graphlike.
- Ignoring
max_bp_iters -> the decoder may return before
convergence. The hard-decision return short-circuits when
H e_hard = s; otherwise OSD repairs.
- Comparing BP-OSD accuracy to a matching decoder without
identical parity-check matrix and noise model -> the harness
drives both through the same pipeline (manual 15.3).
- Hardcoding tuning kwargs -> names are stable, defaults may
shift in 1.x (manual 16.2).
How the bench server helps
qector-research.code_family_info reports whether a code is
graphlike and the routing hint.
qector-research.decode_faithfulness_check re-verifies
H c = s externally for any decoder output.
qector-research.pymatching_compat_check is a related smoke test
(graphlike codes only).
1---2name: qector-bp-osd3description: Belief propagation with ordered-statistics post-processing (BP-OSD) for QECTOR. Covers the box-plus kernel phi(x) = -ln(tanh(x/2)), the log-domain sum-product / min-sum / relay schedules, the OSD-0 / OSD-W solve (Theorem 11), the ambiguity-cluster partition (Theorem 12), and the worked examples from the v1.0.0 reference manual (chapters 8 and 9). Load for any qLDPC, hyperedge, or non-graphlike question, or for the BP-OSD tuning surface.4---56# QECTOR BP-OSD78Source of authority: v1.0.0 reference manual, chapters 8, 9.910## Where BP-OSD applies1112BP-OSD is the only decoder defined for **arbitrary GF(2) parity-check13matrices** (manual 11.1). The matching decoders reject any code with14a qubit of degree > 2; the Union-Find rejection is the explicit15contract, not a bug (manual 20.8). BP-OSD handles:1617- qLDPC codes (bicycle, bivariate-bicycle, hypergraph-product).18- Color codes (`codes.color_code`).19- Any code with hyperedges (weight > 2 mechanisms).20- Codes fed by a DEM with mechanisms that cannot be collapsed to21 graph edges.2223## The belief-propagation update (manual 8.1)2425Let `gamma_q = LLR_prior(q) + sum_{c in N(q)} m_{c->q}` be the26posterior LLR of qubit `q`. The check-node update is the **box-plus27kernel** in the log domain:2829 phi(x) = -ln(tanh(x/2)) = ln coth(x/2) for x > 030 phi(0) = +inf31 phi(x) -> 0 for large x3233Three schedules are supported:3435| Schedule | Formula | Notes |36| ------------------ | -------------------------------------------------------- | ---------------------------------------- |37| Exact sum-product | `m_{c->q} = sgn * phi( sum_{q'} phi(|m_{q'->c}|) )` | default; numerically stable |38| Min-sum | `m_{c->q} = sgn * min_{q'} |m_{q'->c}|` | classical approximation, opt-in |39| Relay (layered) | same kernel; checks processed sequentially | faster convergence on loopy graphs |4041The Rust implementation evaluates `phi` exactly below `0.25` and42uses a `2^16`-entry linearly-interpolated table above it, with43maximum interpolation error about `2e-7` on the tabulated range.4445## The OSD stage (manual 8.2)4647- **OSD-0**: sort columns by ascending `|LLR|` (least reliable48 first), extract a rank-r independent basis by GF(2) Gaussian49 elimination, keep the BP hard decision on the free (most50 reliable) columns, solve the basis for the residual syndrome.51- **OSD-W** (`osd_order >= 1`): additionally sweep combinations of52 the `W = max(2 * osd_order, 6)` least-reliable columns and keep53 the lowest-weight faithful candidate.5455## Theorem 11 (residual-solve faithfulness, manual 8.2)5657> Let `B` be a rank-r column basis of `H`, and let58> `s_eff = s + H_fixed e_fixed (mod 2)` be the residual after59> fixing the reliable columns. Then the system60> `H_B e_B = s_eff` has a solution whenever `s` is reachable, and61> every OSD candidate62> `c = e_fixed + (e_B on B, 0 elsewhere)` satisfies `H c = s`.6364The algebraic guarantee is **independent of BP convergence65quality**: LLRs only influence which coset is selected, never66whether the returned correction reproduces the syndrome.6768## The reliability partition and component-wise solving (manual 9)6970- Threshold `tau` on `|LLR|`. Split qubits into71 `Q_rel = {q : |gamma_q| >= tau}` and `Q_amb = {q : |gamma_q| < tau}`.72- Freeze `Q_rel` to hard decisions `e_rel`. Compute the residual73 `s_res = s + H_rel e_rel (mod 2)`. If `s_res = 0` the decode is74 complete.75- Otherwise the Tanner-induced subgraph on `Q_amb` splits into76 connected components `C_k`. Each component with77 `size <= K_max` (default 12) is solved exactly by enumeration78 over its `2^k` error patterns, minimizing weight among faithful79 solutions. Larger components use a restricted OSD-0 over the80 cluster columns.8182## Theorem 12 (component-wise faithfulness, manual 9.2)8384> Let `c = e_rel xor (xor_k e_k)`, where each component is solved85> with `H_{C_k} e_k = s_res` restricted to its support. Then86> `H c = s (mod 2)`, independently of the threshold `tau`.8788## Tuning kwargs (manual 16.2 - Provisional)8990The `BPOSDDecoder` tuning kwarg names are stable; defaults may shift91in 1.x. Verify the live values via introspection; do not hard-code.9293- `bp_method`: `"sum_product"` (default) or `"min_sum"`.94- `osd_order`: integer, default 0; `>= 1` enables OSD-W with95 `W = max(2 * osd_order, 6)`.96- `max_bp_iters`: integer; default typically 50.97- `tau`: reliability threshold; default typically 0.0 (no98 ambiguity clustering).99100## Worked example (manual 8.5)101102`H = [[1,1,0],[0,1,1]]` over F2, syndrome `s = [1,0]`.103104- BP's hard decision: `e_hard = [1,0,0]`, residual zero, decode105 returns immediately. `H e = [1,0] = s`.106- If BP were uncertain and produced `e_hard = [0,1,0]`, residual107 `s_eff = [0,1]`. The most reliable column (column 1) is fixed at108 its BP hard decision 0; the basis `{0, 2}` must solve109 `H_B e_B = s_eff`. Column 2 alone contributes `[0,1]`, so110 `e_B = (0, 1)` on the basis columns and `c = [0,1,1]`. `H c = s`.111112The example shows the division of labour: **BP proposes, OSD113repairs, and the repaired correction always satisfies the114syndrome**.115116## Numerical stability117118The `phi` LUT keeps the update numerically stable across the full119dynamic range. `qector_decoder_v3.bp_osd` exposes the120`plausibility_guard`; the regression suite includes121`test_bp_numerical_stability.py` and `test_bposd_osd_orders.py`.122123## Common pitfalls124125- **Calling `bposd` on a graphlike code** -> it works, but the126 matching decoders are faster on tested configurations. Use127 `bposd` only when the parity-check matrix is non-graphlike.128- **Ignoring `max_bp_iters`** -> the decoder may return before129 convergence. The hard-decision return short-circuits when130 `H e_hard = s`; otherwise OSD repairs.131- **Comparing BP-OSD accuracy to a matching decoder** without132 identical parity-check matrix and noise model -> the harness133 drives both through the same pipeline (manual 15.3).134- **Hardcoding tuning kwargs** -> names are stable, defaults may135 shift in 1.x (manual 16.2).136137## How the bench server helps138139- `qector-research.code_family_info` reports whether a code is140 graphlike and the routing hint.141- `qector-research.decode_faithfulness_check` re-verifies142 `H c = s` externally for any decoder output.143- `qector-research.pymatching_compat_check` is a related smoke test144 (graphlike codes only).