You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -20,7 +20,7 @@ and commercial licences are what keep the decoder maintained.
20
20
| Channel | Who it's for |
21
21
|---|---|
22
22
|[GitHub Sponsors](https://github.com/sponsors/qectorlab)| Individuals and companies funding ongoing development |
23
-
|[Commercial licence](https://www.qector.store/pricing)| Required for company, SaaS, OEM or funded institutional use — see [COMMERCIAL.md](https://github.com/GuillaumeLessard/qector-decoder/blob/main/COMMERCIAL.md)|
23
+
|[Commercial licence](https://www.qector.store/pricing)| Required for company, SaaS, OEM or funded institutional use, see [COMMERCIAL.md](https://github.com/GuillaumeLessard/qector-decoder/blob/main/COMMERCIAL.md)|
The core also resolves a key on its own, in this order: `QECTOR_LICENSE_KEY`,
209
209
then `QECTOR_LICENSE_FILE`, then `~/.qector/license.key`. Prefer a file in
210
-
deployments — the key then never appears in a process listing or shell history.
210
+
deployments: the key then never appears in a process listing or shell history.
211
211
Check `info["key_status"] == "valid"`, not just the tier: a `QECTOR_LICENSE_FILE`
212
212
that is set but unreadable is reported as an *invalid* key rather than silently
213
213
falling back to Community.
@@ -303,13 +303,13 @@ QECTOR uses **offline Ed25519 signature verification** for license tokens. No ne
303
303
## Tuning environment variables
304
304
305
305
These change decoder behaviour at construction time. Two of them affect
306
-
**matching quality**, and therefore logical error rate — set them deliberately,
306
+
**matching quality**, and therefore logical error rate; set them deliberately,
307
307
and record them alongside any benchmark you publish.
308
308
309
309
| Variable | Default | Effect |
310
310
| --- | --- | --- |
311
311
|`QECTOR_BLOSSOM_K_MULT`|`2.0`| Candidate-neighbour multiplier for sparse MWPM: `k = max(12, ceil(mult · sqrt(n_defects)))`. **Affects accuracy.** Lowering it reduces latency but can exclude the optimal partner on dense instances, producing a heavier (sub-optimal) matching. `2.0` is the tuned minimum that preserved exact-MWPM parity at d ≥ 15. |
312
-
|`QECTOR_BLOSSOM_INTRA_PAR`| auto | Force intra-decode parallelism for candidate discovery. `0` disables, `1` forces. Unset selects automatically when the graph has ≥ 64 nodes (roughly d ≥ 9 for rotated surface codes). Performance only — output is bit-identical either way. |
312
+
|`QECTOR_BLOSSOM_INTRA_PAR`| auto | Force intra-decode parallelism for candidate discovery. `0` disables, `1` forces. Unset selects automatically when the graph has ≥ 64 nodes (roughly d ≥ 9 for rotated surface codes). Performance only; output is bit-identical either way. |
313
313
|`QECTOR_BLOSSOM_INTRA_THREADS`| unset | Size a dedicated Rayon pool for candidate discovery, independent of the global batch pool. Unset or `< 1` uses the global pool. Performance only. |
314
314
|`QECTOR_CUDA_DEVICE_ID`|`0`| Which CUDA device the native batch/BP-OSD decoders bind to. |
315
315
|`QECTOR_OPENCL_DEVICE_ALLOW`| unset | Comma-separated substrings matched case-insensitively against OpenCL device names, e.g. `nvidia,geforce`. Unset accepts any device. Use it to avoid selecting an integrated GPU on multi-device hosts. |
@@ -335,16 +335,16 @@ Commercial licenses are issued automatically via Stripe Checkout:
335
335
336
336
| Area | Description |
337
337
| --- | --- |
338
-
|**`qector` CLI**|`qector decode` / `bench` / `serve`, plus `qector-doctor` — a 15-check environment diagnostic that tells you *why* a decoder is unavailable instead of failing at decode time |
338
+
|**`qector` CLI**|`qector decode` / `bench` / `serve`, plus `qector-doctor`, a 15-check environment diagnostic that tells you *why* a decoder is unavailable instead of failing at decode time |
339
339
|**Ecosystem entry points**| Five Sinter decoders and the qiskit-qec plugin are now registered entry points, so `sinter.collect(decoders=["qector_blossom", ...])` works without `custom_decoders=`|
340
-
|**`pymatching` shim**|`from qector_decoder_v3.pymatching import Matching` — the submodule spelling, not only the attribute |
341
-
|**New decoder families**|`AmbiguityClusterDecoder` (BP + \|LLR\| partition + exact per-cluster enumeration), `TwoStageDecoder` (X sector, propagate, Z sector), `ColourCodeDecoder` (BP-OSD on the *undecomposed* hypergraph — matching is not a correct colour-code decoder) |
340
+
|**`pymatching` shim**|`from qector_decoder_v3.pymatching import Matching`, the submodule spelling, not only the attribute |
341
+
|**New decoder families**|`AmbiguityClusterDecoder` (BP + \|LLR\| partition + exact per-cluster enumeration), `TwoStageDecoder` (X sector, propagate, Z sector), `ColourCodeDecoder` (BP-OSD on the *undecomposed* hypergraph; matching is not a correct colour-code decoder) |
342
342
|**Relay-BP**| Layered serial BP schedule for qLDPC (`bp_method="relay"`); each check sees the freshest messages |
343
343
|**Weighted Union-Find on the GPU**|`CUDABatchDecoder` and `OpenCLBatchDecoder` accept `edge_weights` and run adaptive weighted growth; both kernels agree, which is the cross-check that the port is faithful |
344
-
|**`DemModel.make_decoder`**| Covers all nine shipped families, not five — a DEM is the entry point real circuit-level workloads use |
345
-
|**Belief matching**|`from_numpy_h` decoders no longer return empty corrections — output is a faithful length-`n_qubits` vector (`H @ corr == syndrome`) |
344
+
|**`DemModel.make_decoder`**| Covers all nine shipped families, not five; a DEM is the entry point real circuit-level workloads use |
345
+
|**Belief matching**|`from_numpy_h` decoders no longer return empty corrections; output is a faithful length-`n_qubits` vector (`H @ corr == syndrome`) |
346
346
|**BP-OSD accuracy**| Exact log-domain sum-product BP by default; true combination-sweep OSD-1/2 via `osd_order`|
347
-
|**Rust core: crash safety**| Six panic-to-abort paths removed — gRPC and CUDA mutex-poison propagation, swallowed CUDA async errors, `Bernoulli::new` unwrap, cascade-decoder `expect`. Under `panic = "abort"` each of these killed the host process |
347
+
|**Rust core: crash safety**| Six panic-to-abort paths removed: gRPC and CUDA mutex-poison propagation, swallowed CUDA async errors, `Bernoulli::new` unwrap, cascade-decoder `expect`. Under `panic = "abort"` each of these killed the host process |
348
348
|**Licence hardening**| Malformed tokens return `False` instead of raising; v2 tokens carry tier + expiry inside the signature; `QECTOR_LICENSE_FILE` and `~/.qector/license.key` are read, and an unreadable file reports *invalid* rather than silently dropping to Community |
349
349
|**Benchmark honesty**| The pre-v0.7.0 comparison tables are withdrawn; `ler.assert_comparable` now blocks cross-noise-model comparisons at the source |
350
350
@@ -370,8 +370,8 @@ Commercial licenses are issued automatically via Stripe Checkout:
370
370
371
371
### Withdrawn: the pre-v1.0.0 comparison tables
372
372
373
-
**Four benchmark tables that stood here — MWPM parity vs PyMatching at d=13/15,
374
-
belief-matching LER at d=5/7, GPU bit-identity, and the native memory profile —
373
+
**Four benchmark tables that stood here: MWPM parity vs PyMatching at d=13/15,
374
+
belief-matching LER at d=5/7, GPU bit-identity, and the native memory profile,
375
375
are withdrawn. Do not cite them.**
376
376
377
377
Two independent reasons, either sufficient:
@@ -382,7 +382,7 @@ Two independent reasons, either sufficient:
382
382
so the "parity" the tables reported was an artifact of the harness, not a
383
383
property of the decoders.
384
384
2.**The artifacts are unobtainable.** Each table cited a file under
385
-
`benchmark_results/` — a path that is in `.gitignore` and has never been part
385
+
`benchmark_results/`, a path that is in `.gitignore` and has never been part
386
386
of any published commit or wheel. The files are also no longer on disk. Nobody
387
387
could have checked the numbers even when they were displayed.
388
388
@@ -394,9 +394,9 @@ cannot recur silently.
394
394
395
395
**What replaces them:**`scripts/regenerate_benchmark_artifacts.py` and
396
396
`scripts/run_custom_comparison_benchmark.py` both drive every decoder through
397
-
one circuit-level pipeline —`ler.estimate_ler_circuit_level`, one Stim circuit,
397
+
one circuit-level pipeline:`ler.estimate_ler_circuit_level`, one Stim circuit,
398
398
one decomposed DEM, one detector/observable sample set per cell, one
399
-
`decode_batch` resolver, scored against the circuit's own logical observables —
399
+
`decode_batch` resolver, scored against the circuit's own logical observables;
400
400
and stamp the result with its methodology, git commit, tree-dirty flag,
401
401
parameters and dependency versions. `ler.assert_comparable` gates the rows
402
402
before they are written.
@@ -418,27 +418,27 @@ through the package MCP server (stdio, JSON-RPC 2.0) on `2026-08-02T05:59:13Z`
-**No speedup multiplier is claimed.** Apple-to-apple vs PyMatching (see `benchmarks/v1.0.0/VERIFIED_APPLE_TO_APPLE_REPORT.pdf`): comparable, with PyMatching often slightly ahead on the synchronized batch.
424
424
425
425
The previous `official_benchmark_results.*` (2026-08-01 circuit-level comparison,
426
426
generated from a dirty working tree at `b436f04e`, carrying per-row
427
-
speedup-vs-PyMatching multipliers) is **withdrawn** — it is not part of the
427
+
speedup-vs-PyMatching multipliers) is **withdrawn**: it is not part of the
428
428
verified release and must not be cited.
429
429
430
430
> **Benchmark figures are not published beyond the verified set for this release.**
431
431
> Decoder throughput and logical error rate depend on your hardware, code family,
432
432
> distance and noise model, so any table printed here would describe a machine that
433
433
> is not yours. The benchmark harness ships with the package and writes JSON carrying
434
-
> its own environment and parameter block — run it on your target hardware
434
+
> its own environment and parameter block; run it on your target hardware
435
435
> (`qector benchmark --verify` or `python -m qector.validate`) and compare decoders
436
436
> under the conditions you actually care about.
437
437
438
438
**GPU accuracy depends on whether matching weights are supplied.**
439
439
`CUDABatchDecoder` and `OpenCLBatchDecoder` accept an optional `edge_weights`
440
440
argument. Omitting it selects topology-only cluster growth, whose logical error
441
-
rate does not improve with code distance — the signature of operation above
441
+
rate does not improve with code distance: the signature of operation above
442
442
threshold. Supplying the DEM's `log((1-p)/p)` weights restores distance scaling.
443
443
The weighted path costs more per shot than the unweighted one.
444
444
`docs/BENCHMARK_COMPETITIVE.md` records the same effect for unweighted
@@ -462,14 +462,14 @@ project lives in the archived datasets, not in this file:
462
462
463
463
| Record | What it establishes | Methodology |
464
464
| --- | --- | --- |
465
-
|[10.5281/zenodo.21501377](https://doi.org/10.5281/zenodo.21501377) — Empirical benchmarks, v0.6.8 (CC-BY-4.0) | Archived empirical benchmark dataset for v0.6.8, including syndrome-faithfulness verification (`H·ê = s`) and matching parity against PyMatching | Circuit-level, single pipeline. Ships 5 raw JSON datasets, 6 repro scripts, and a `manifest.json` carrying the wheel SHA256 and pinned dependency versions. Host: HP dual-core, 3.1 GB RAM, AntiX live USB, Python 3.13.5, pymatching 2.4.0, stim/sinter 1.16.0 |
466
-
|[10.5281/zenodo.21339300](https://doi.org/10.5281/zenodo.21339300) — Workbench benchmark master report, v0.6.6 (CC-BY-4.0) | 1,858 measurements over 105 runs; latency, throughput and peak memory for `d = 3–19` across 6 topologies |`p = 0.05`. Reports QECTOR decoders against each other — it is **not** a cross-library comparison |
465
+
|[10.5281/zenodo.21501377](https://doi.org/10.5281/zenodo.21501377): Empirical benchmarks, v0.6.8 (CC-BY-4.0) | Archived empirical benchmark dataset for v0.6.8, including syndrome-faithfulness verification (`H·ê = s`) and matching parity against PyMatching | Circuit-level, single pipeline. Ships 5 raw JSON datasets, 6 repro scripts, and a `manifest.json` carrying the wheel SHA256 and pinned dependency versions. Host: HP dual-core, 3.1 GB RAM, AntiX live USB, Python 3.13.5, pymatching 2.4.0, stim/sinter 1.16.0 |
466
+
|[10.5281/zenodo.21339300](https://doi.org/10.5281/zenodo.21339300): Workbench benchmark master report, v0.6.6 (CC-BY-4.0) | 1,858 measurements over 105 runs; latency, throughput and peak memory for `d = 3-19` across 6 topologies |`p = 0.05`. Reports QECTOR decoders against each other; it is **not** a cross-library comparison |
467
467
468
468
Both are one release behind the working tree (v0.6.8 and v0.6.6 against 1.0.0);
469
469
read them as evidence about those versions.
470
470
471
471
Benchmark results are hardware, driver, compiler, and workload dependent.
472
-
Regenerate before quoting performance numbers, and state the noise model —
472
+
Regenerate before quoting performance numbers, and state the noise model:
473
473
code-capacity and circuit-level LERs are different quantities.
with `QECTOR_SILENT=1`). Point your MCP client at that file — e.g. Claude Code
555
+
with `QECTOR_SILENT=1`). Point your MCP client at that file, e.g. Claude Code
556
556
supports `mcp.add` with the `qector` server name. The server advertises 13
557
557
tools, all verified on the released wheel:
558
558
@@ -582,12 +582,12 @@ controlled use; like REST/gRPC, it is not hardened for public SaaS exposure.
582
582
| Area | Boundary |
583
583
| --- | --- |
584
584
| MWPM latency | PyMatching remains faster than exact `BlossomDecoder` on standard surface-code MWPM. QECTOR's value is decoder breadth and qLDPC coverage, not beating PyMatching at its own workload |
585
-
| Belief-matching | Accuracy/research mode — can improve LER but much slower |
585
+
| Belief-matching | Accuracy/research mode; can improve LER but much slower |
586
586
| GPU accuracy | Unweighted GPU kernels trade logical accuracy for throughput; pass `edge_weights` or accept that |
587
587
| GPU performance | Speedup is not universal, and the weighted kernel is currently slower than the weighted CPU path |
588
588
| Benchmark tables | The pre-v0.7.0 comparison tables are withdrawn (see above). Cite the archived datasets or regenerate |
589
589
| OpenCL | Depends on build configuration; confirm locally |
590
-
| SparseBlossom | Near-optimal, not exact MWPM — use `BlossomDecoder` for exact |
590
+
| SparseBlossom | Near-optimal, not exact MWPM; use `BlossomDecoder` for exact |
591
591
| UnionFind | Fast approximate path; not universal for arbitrary graphs |
592
592
| REST/gRPC/MCP | Not hardened as public SaaS without separate security review |
593
593
@@ -607,7 +607,7 @@ QECTOR Decoder v3 is **source-available** under the **PolyForm Noncommercial Lic
0 commit comments