Skip to content

Latest commit

 

History

227 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

QECTOR Logo

QECTOR Decoder v3

Production-grade quantum error correction decoding library, Python + Rust.
Copyright © 2026 Guillaume Lessard / iD01t Productions. All Rights Reserved.

Engine Workbench Plugin Python License

Install · Quick Start · Decoder Families · MCP Server · Licensing · Contact

CI PyPI Python

🚀 Support QECTOR Development

QECTOR is source-available and developed independently. Non-commercial use is free; sponsorship and commercial licences are what keep the decoder maintained.

Sponsor qectorlab Commercial licence Pricing

Channel Who it's for
GitHub Sponsors Individuals and companies funding ongoing development
Commercial licence Required for company, SaaS, OEM or funded institutional use, see COMMERCIAL.md
Direct purchase Immediate Stripe checkout, licence issued automatically
admin@qector.store Site licences, custom terms, academic partnerships

PyMatching-compatible MWPM validation · Belief-matching accuracy mode · BP-OSD for LDPC/qLDPC · CPU/GPU batch decoding · 7-tier self-debugging fallback engine · Ed25519 cryptographic license verification

Website · PyPI · Commercial licensing


Install

pip install qector-decoder-v3

Supported: Python 3.9-3.13 (requires-python = ">=3.9") on Linux x86_64, Windows x64, and macOS arm64.

Each release publishes 15 binary wheels: CPython 3.9/3.10/3.11/3.12/3.13 × win_amd64 / manylinux_2_17_x86_64 / macosx_11_0_arm64. There is no sdist and no aarch64, musllinux, or macOS x86_64 wheel, so pip install on any other platform will fail rather than fall back to a source build. Those targets need a local build from a licensed source checkout.

Optional extras:

pip install "qector-decoder-v3[stim]"    # Stim/Sinter/PyMatching/LDPC ecosystem
pip install "qector-decoder-v3[bench]"   # Benchmark harness (psutil, matplotlib, scipy)
pip install "qector-decoder-v3[all]"     # Full validation environment

Quick start

import numpy as np
from qector_decoder_v3 import UnionFindDecoder, BlossomDecoder

check_to_qubits = [[0, 1], [1, 2], [2, 3], [3, 4]]
n_qubits = 5
syndrome = np.array([0, 1, 0, 0], dtype=np.uint8)

fast = UnionFindDecoder(check_to_qubits, n_qubits)
print(fast.decode(syndrome))

mwpm = BlossomDecoder(check_to_qubits, n_qubits)
print(mwpm.decode(syndrome))

Batch decoding

from qector_decoder_v3 import BatchDecoder, CUDABatchDecoder

checks = [[0, 1], [1, 2], [2, 3], [3, 4]]
syndromes = np.random.randint(0, 2, size=(4096, 4), dtype=np.uint8)

cpu = BatchDecoder(checks, n_qubits=5)
corrections = cpu.parallel_batch_decode(syndromes)

if CUDABatchDecoder.is_available():
    gpu = CUDABatchDecoder(checks, n_qubits=5)
    corrections = gpu.batch_decode(syndromes)

Pass the DEM's weights to the GPU. Without edge_weights the GPU kernels run unweighted cluster growth, which cannot distinguish a p = 1e-4 mechanism from a p = 1e-2 one; on circuit-level noise that costs several times the logical error rate, no matter how fast the GPU is:

from qector_decoder_v3 import dem

model = dem.from_stim(circuit.detector_error_model(decompose_errors=True))
graph = model.collapse_to_graph()

gpu = CUDABatchDecoder(
    graph.check_to_qubits(),
    graph.num_errors,
    graph.weights().tolist(),   # log((1-p)/p) per mechanism
)

What it costs: the unweighted GPU kernels trade logical accuracy for throughput. They decode faster than the weighted CPU core, at a materially higher logical error rate that throughput does not buy back. Pass edge_weights when accuracy matters.

The weighted GPU kernel is the accuracy option: weighting restores distance scaling, at a higher per-shot cost. Both configurations are exposed for qector_cuda and qector_opencl so you can measure the trade-off on your own hardware and noise model. No benchmark figures are published for this release: decoder throughput and logical error rate depend on your hardware, code family, distance and noise model, so any table printed here would describe a machine that is not yours. See docs/GPU_AND_CUPY.md.

AutoDecoder: 7-tier self-debugging fallback

from qector_decoder_v3 import AutoDecoder

decoder = AutoDecoder(checks, n_qubits=5)
corrections = decoder.batch_decode(syndromes)

# Inspect backend health
print(decoder._diag.backend_health)
print(decoder._diag.active_backend)

Stim workflow

import stim
from qector_decoder_v3 import BlossomDecoder
from qector_decoder_v3.stim_compat import from_stim_detector_error_model

circuit = stim.Circuit.generated(
    "surface_code:rotated_memory_z", distance=5, rounds=5,
    after_clifford_depolarization=0.005,
)
dem = circuit.detector_error_model(decompose_errors=True)
checks, n_qubits = from_stim_detector_error_model(dem)
decoder = BlossomDecoder(checks, n_qubits)

DemModel.make_decoder builds any shipped decoder family straight from the model, already carrying its weights. Enumerate them with DemModel.DECODER_KINDS:

from qector_decoder_v3 import dem

graph = dem.from_stim(circuit.detector_error_model(decompose_errors=True)).collapse_to_graph()

for kind in ("union_find", "fast_union_find", "blossom", "sparse_blossom",
             "bp_osd", "lookup_table", "hybrid_cascade", "ambiguity_cluster"):
    decoder = graph.make_decoder(kind)

# two_stage decodes the X and Z sectors separately, so it needs the sector of
# each detector -- a DEM does not record it:
#   graph.make_decoder("two_stage", check_types=[...])

BP-OSD for LDPC / qLDPC codes

from qector_decoder_v3 import codes
from qector_decoder_v3.bposd import BpOsdDecoder

cx, cz = codes.bivariate_bicycle_code(6, 6, ...)
decoder = BpOsdDecoder(cx.parity_check_matrix(), error_rate=0.05, osd_order=0)
correction = decoder.decode(syndrome)

License verification

import os
from qector_decoder_v3.license import verify_license_token

token = os.environ.get("QECTOR_LICENSE", "")
is_valid = verify_license_token(token)
# Or with explicit email check:
is_valid = verify_license_token(token, customer_email="user@example.com")

License Keys (v1.0.0)

from qector_decoder_v3 import set_license_key, set_license_key_file, get_license_info

set_license_key("QECT-PRO-your-key")        # raises ValueError if the key is rejected
set_license_key_file("/path/to/license.key")  # or load it from a file

info = get_license_info()
print(f"Tier: {info['tier']}  status: {info['key_status']}")

The core also resolves a key on its own, in this order: QECTOR_LICENSE_KEY, then QECTOR_LICENSE_FILE, then ~/.qector/license.key. Prefer a file in deployments: the key then never appears in a process listing or shell history. Check info["key_status"] == "valid", not just the tier: a QECTOR_LICENSE_FILE that is set but unreadable is reported as an invalid key rather than silently falling back to Community.

Sinter integration

import sinter
from qector_decoder_v3.sinter_compat import qector_sinter_decoders

samples = sinter.collect(
    num_workers=4, tasks=tasks,
    decoders=["qector_belief", "qector_blossom", "qector_unionfind"],
    custom_decoders=qector_sinter_decoders(),
)

Decoder families

Module Best use Status
UnionFindDecoder Low-latency approximate decoding Stable
FastUnionFindDecoder Optimized Union-Find hot path Stable
BlossomDecoder Exact MWPM / PyMatching-parity validation Stable
SparseBlossomDecoder Faster near-optimal matching Experimental
BeliefMatching Correlated-noise accuracy experiments Research
BpOsdDecoder LDPC / qLDPC decoding Experimental
BatchDecoder / CPUBatchDecoder CPU batch Monte Carlo sweeps Stable
CUDABatchDecoder CUDA batch decoding (optional edge_weights) Build/runtime dependent
CUDABpOsdDecoder CUDA BP-OSD batch decoding Build/runtime dependent
OpenCLBatchDecoder OpenCL batch decoding (optional edge_weights) Build/runtime dependent
SpaceTimeDecoder 3D space-time (multi-round) decoding Experimental
AutoDecoder 7-tier self-debugging backend fallback Stable
PredecodedDecoder Easy-syndrome prefiltering Experimental
DecoderPool Multi-process batch decoding Stable
get_decoder / clear_decoder_cache Cached decoder factory Stable
decode_mmap Out-of-core memmap decoding Stable
DecodeResult / decode_with_diagnostics Structured decode results Stable
Workbench High-level orchestration Stable
SlidingWindowDecoder Multi-round streaming Experimental
StreamingDecoder Continuous streaming sessions Experimental
HybridDecoder Union-Find + Blossom fallback routing Experimental
LookupTableDecoder Precomputed small-code lookup Experimental
NeuralPredecoder Learned predecoder front-end Research
GNNPredecoder Graph neural network predecoder Research
GNNTrainer Training harness for GNNPredecoder Research
stim_compat Stim circuit / DEM conversion Stable utility
sinter_compat Sinter custom decoder integration Stable utility
rest_api Local decoding service Local/partner review

Self-Auto-Debug Backend Architecture (v0.6.8)

AutoDecoder implements a 7-tier fault-tolerant self-debugging fallback engine that automatically selects, monitors, and recovers from hardware failures:

Tier Backend Description
1 CUDA Batch GPU batch decoding via NVRTC-compiled kernels
2 OpenCL Batch Cross-vendor GPU batch decoding
3 CPU Rayon Multi-threaded parallel CPU batch decoding
4 CPU Batch Single-threaded CPU batch decoding
5 CPU Single Per-syndrome CPU decoding
6 Blossom Exact MWPM fallback (guaranteed correctness)
7 Lookup Table / Python Pure-Python last-resort fallback

Key features:

  • Automatic error trapping: Hardware exceptions (CUDA OOM, driver crashes, memory limits) are caught, logged, and bypassed transparently.
  • Health scoring: Each backend tracks its health status. Failed backends are automatically suspended.
  • Seamless recovery: reset_backend_health() re-enables all backends for dynamic recovery.
  • Diagnostic logging: All fallback events and error details are recorded for debugging.

Licensing & Activation (v1.0.0)

Ed25519 Cryptographic License Verification

QECTOR uses offline Ed25519 signature verification for license tokens. No network calls required.

Token format: Self-contained 3-part tokens ({receipt_id}.{email_b64}.{signature_b64}) embed the customer email and cryptographic signature for fully offline verification.

Variable Description
QECTOR_LICENSE Set to a valid Ed25519-signed license token to activate
QECTOR_SILENT Set to 1 to suppress the startup licensing notice

Override tokens: academic and commercial accepted for development and testing.

Tuning environment variables

These change decoder behaviour at construction time. Two of them affect matching quality, and therefore logical error rate; set them deliberately, and record them alongside any measurement you publish.

Variable Default Effect
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.
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.
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.
QECTOR_CUDA_DEVICE_ID 0 Which CUDA device the native batch/BP-OSD decoders bind to.
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.

Only QECTOR_BLOSSOM_K_MULT and QECTOR_OPENCL_DEVICE_ALLOW can change results (matching quality and device selection respectively); the rest are purely throughput knobs.

Stripe Integration

Commercial licenses are issued automatically via Stripe Checkout:

  1. Customer completes payment at qector.store
  2. Stripe fires a checkout.session.completed webhook
  3. The server generates an Ed25519-signed license token
  4. Token is delivered to the customer

Direct purchase: Buy Commercial License


v1.0.0 highlights

Area Description
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
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=
pymatching shim from qector_decoder_v3.pymatching import Matching, the submodule spelling, not only the attribute
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)
Relay-BP Layered serial BP schedule for qLDPC (bp_method="relay"); each check sees the freshest messages
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
DemModel.make_decoder Covers all nine shipped families, not five; a DEM is the entry point real circuit-level workloads use
Belief matching from_numpy_h decoders no longer return empty corrections; output is a faithful length-n_qubits vector (H @ corr == syndrome)
BP-OSD accuracy Exact log-domain sum-product BP by default; true combination-sweep OSD-1/2 via osd_order
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
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
Benchmark honesty The pre-v0.7.0 comparison tables are withdrawn; ler.assert_comparable now blocks cross-noise-model comparisons at the source

v0.6.8 highlights

Area Description
Self-Auto-Debug Backend 7-tier fault-tolerant fallback engine with automatic error trapping and health scoring
Ed25519 License Verification Offline cryptographic license token validation
Stripe License Fulfillment Automated commercial license issuance via Stripe Checkout
SparseBlossom bugfix All decoded syndromes now bit-identical to MWPM
BPOSD timeout bugfix Wall-clock deadline now honored from the first iteration
OpenCL health check fix Child-process NameError in _opencl_health_check() fixed
k_nearest_via_radix Public event-driven candidate-edge discovery
MCP server expansion 5 new tools, expanded decoder info
Cross-decoder test suite Covers all 11 decoder families
SafeTensors round-trip tests Full dtype, shape, and error-path coverage
Dead-code elimination 8 warnings eliminated across the crate

Benchmarks

No benchmark figures are published for this release. Decoder throughput and logical error rate are hardware-, driver-, compiler-, code-family-, distance- and noise-model-dependent; any table printed here would only describe a machine that is not yours. The pre-v0.7.0 comparison tables that previously stood in this file are withdrawn and must not be cited.

What ships with the package instead:

  • The measurement harness (qector benchmark --verify or python -m qector.validate) drives every decoder through one circuit-level pipeline and writes JSON stamped with its own environment, git commit, parameters and dependency versions, so results are traceable to the machine that produced them.
  • ler.assert_comparable refuses cross-noise-model comparisons at the source, so a methodology-incompatible table cannot be produced by accident.
  • Unweighted GPU kernels trade logical accuracy for throughput: pass the DEM's edge_weights when accuracy matters (see the quick-start above).

Run the harness on your own hardware, and state the noise model and environment alongside any number you publish. See docs/BENCHMARK_COMPETITIVE.md and docs/GPU_AND_CUPY.md.


Architecture

qector_decoder_v3/
+-- Rust core (proprietary, injected during CI build or under license)
|   +-- Union-Find / Blossom / SparseBlossom engines
|   +-- CPU batch engine (SIMD-accelerated on x86)
|   +-- CUDA / OpenCL batch paths
|   +-- DEM collapse and Stim integration
|
+-- Python layer (open source in this repository)
    +-- __init__.py, backend.py, dem.py
    +-- belief_matching.py, bposd.py
    +-- predecoder.py, codes.py
    +-- stim_compat.py, sinter_compat.py
    +-- qiskit_plugin.py, rest_api.py
    +-- workbench.py

REST API (local use only)

pip install "qector-decoder-v3[stim]" fastapi uvicorn
python -m qector_decoder_v3.rest_api
curl -X POST http://localhost:8000/decode \
  -H "Content-Type: application/json" \
  -d '{"check_to_qubits":[[0,1],[1,2],[2,3],[3,4]],"syndrome":[0,1,0,0]}'

For local experiments and controlled deployments only. Not hardened for public SaaS.


MCP server (stdio)

The package ships an MCP server (JSON-RPC 2.0 over stdio) in every published wheel, no extra feature flag or install is needed:

python -c "import qector_decoder_v3; qector_decoder_v3.run_mcp_server()"

A ready-made client configuration lives in mcp.json at the repository root (it launches python -c "import qector_decoder_v3; qector_decoder_v3.run_mcp_server()" with QECTOR_SILENT=1). Point your MCP client at that file, e.g. Claude Code supports mcp.add with the qector server name. The server advertises 13 tools, all verified on the released wheel:

Tool Purpose
decode_syndrome Decode a syndrome with any decoder family (Union-Find, Blossom, SparseBlossom, BP-OSD, Cascade, Hybrid, and more)
batch_decode Batch-decode multiple syndromes in parallel
decode_hyperedge Hyperedge / qLDPC decoding (bypasses graphlike Union-Find restrictions)
decode_syndrome_blossom / batch_decode_blossom Exact Blossom (MWPM) single and batch
decode_syndrome_cascade Hybrid cascading decoder (UF pre-filter escalating to Blossom)
benchmark_decoder Run a performance benchmark for a decoder family
run_ler_benchmark LER benchmark across code distances
get_decoder_info Decoder configuration, version info, family listing
get_backend_health Backend health status across the 7 fallback tiers
clear_decoder_cache Clear the decoder factory cache
get_server_env Effective QECTOR environment variables
recommend_decoder Decoder recommendation by code topology and priority

The stdio reader enforces a 10 MB content limit and validates syndrome lengths and decoder types, returning JSON-RPC errors instead of crashing. For local and controlled use; like REST/gRPC, it is not hardened for public SaaS exposure.


Limits and boundaries

Area Boundary
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
Belief-matching Accuracy/research mode; can improve LER but much slower
GPU accuracy Unweighted GPU kernels trade logical accuracy for throughput; pass edge_weights or accept that
GPU performance Speedup is not universal, and the weighted kernel is currently slower than the weighted CPU path
Benchmark figures Not published for this release (hardware-, code- and noise-dependent). The pre-v0.7.0 comparison tables are withdrawn and must not be cited
OpenCL Depends on build configuration; confirm locally
SparseBlossom Near-optimal, not exact MWPM; use BlossomDecoder for exact
UnionFind Fast approximate path; not universal for arbitrary graphs
REST/gRPC/MCP Not hardened as public SaaS without separate security review

Licensing

QECTOR Decoder v3 is source-available under the PolyForm Noncommercial License 1.0.0 (see LICENSE). Personal, academic, educational, and non-commercial research use is allowed. Company use, funded institutional work, SaaS, hosted API deployment, OEM integration, redistribution, paid consulting, or commercial benchmarking requires a commercial license.

DOI references

@software{lessard2026qector,
  author  = {Guillaume Lessard},
  title   = {{QECTOR Decoder v3}: Rust/Python Quantum Error Correction Decoding Platform},
  year    = {2026},
  version = {1.0.0},
  url     = {https://www.qector.store},
  note    = {Source-available under PolyForm Noncommercial 1.0.0. Commercial license required for commercial use.}
}

Contact

Website www.qector.store
Commercial Licensing admin@qector.store
Support admin@qector.store
Pricing qector.store/pricing
QECTOR Decoder Workbench (Windows / Linux / macOS) Releases
QECTOR Claude Plugin Repository

Copyright © 2026 Guillaume Lessard / iD01t Productions. All rights reserved.

https://www.qector.store · admin@qector.store

About

Production-grade Rust/Python quantum error correction decoder. 25+ decoder families: MWPM Blossom, Union-Find, BP-OSD, LDPC/qLDPC, belief-matching, CUDA/GPU batch decoding, AutoDecoder 7-tier fallback. PyMatching/Stim/Sinter compatible. Ed25519 license verification. Benchmark evidence included.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages