backlog-qec 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+
5
+ # build outputs
6
+ cpp/build/
7
+ cpp/build-tsan/
8
+ hardware/build/
9
+ *.o
10
+ *.cf
11
+
12
+ # regenerated by the scripts
13
+ cpp/testdata*/
14
+ results/quick/
15
+ results/scaling/
16
+ results/sweep_log.txt
@@ -0,0 +1,50 @@
1
+ # Changelog
2
+
3
+ ## 0.5.0 (2026-11-05)
4
+
5
+ - Correlated (two-pass) decoding in the whole-shot, sliding-window and
6
+ parallel-window decoders, exact against the reference decoder on the
7
+ reweighted graph. `correlated=True`, `alpha=`, `dem_correlations`,
8
+ `regularization_strength`, sinter decoder `backlog-uf-corr`.
9
+ - The regularized reweighting rule of Hernando de la Fuente et al.
10
+ (arXiv:2610.26785), and an exhaustive check of what it buys: every pair of
11
+ faults at d = 5 decoded by every decoder.
12
+ - `decompose_by_basis`: every error split into its X part and its Z part.
13
+ Correlated decoding needs it: on Stim's own decomposition it is worse than
14
+ plain decoding at d = 3, for PyMatching too (reported upstream as
15
+ [PyMatching#193](https://github.com/oscarhiggott/PyMatching/issues/193)).
16
+ - Parallel windows: a seam starts as soon as its two cores are done (no
17
+ barrier), PAUSE in spin loops, no spinning on hyperthreads, exceptions on
18
+ worker threads carried back to the caller. `make scaling` splits the
19
+ speedup into work inflation and idle time.
20
+ - Benchmarks: correlated accuracy and speed against PyMatching (same shots),
21
+ error suppression factor, fault enumeration, laptop scaling analysis.
22
+ - Quickstart notebook, wheels workflow for PyPI, citation file, contributing
23
+ notes, related-work survey, 26 mutants.
24
+ - Builds with Apple Clang and MSVC as well as GCC, and CI runs the C++ and
25
+ Python test suites on macOS and Windows on every push.
26
+
27
+ ## 0.4.0 (2026-11-04)
28
+
29
+ - Parallel window decoding (core windows, then seams) on a thread pool, same
30
+ answer for any number of threads, clean under ThreadSanitizer.
31
+ - Scheduling model and projection of the cores needed for real time; real
32
+ speedup measured on 2 cores, then up to 8 threads (`make scaling`).
33
+
34
+ ## 0.3.0 (2026-11-04)
35
+
36
+ - Sliding-window decoder for streaming, windows with the same structure
37
+ sharing one decoder; the backlog measured with 1 µs rounds.
38
+
39
+ ## 0.2.0 (2026-11-04)
40
+
41
+ - Weighted, event-driven Union-Find (exact equivalent of synchronous rounds),
42
+ a reference decoder and differential fuzzing between them.
43
+ - Python package (pybind11), Stim error model conversion, sinter decoders.
44
+ - Accuracy gates and benchmarks against PyMatching, mutation testing.
45
+
46
+ ## 0.1.0 (2026-11-04)
47
+
48
+ - Stim + PyMatching baseline and threshold plot, a first C++ Union-Find
49
+ decoder with a command-line tool, a 1D Union-Find core in VHDL checked bit
50
+ for bit, CI.
@@ -0,0 +1,25 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use backlog in your work, please cite it as below."
3
+ title: "backlog: a real-time Union-Find decoder for quantum error correction, from simulation to FPGA"
4
+ abstract: >-
5
+ An open-source weighted Union-Find decoder for the surface code, exact to a
6
+ synchronous reference, with correlated (two-pass) decoding and the
7
+ regularized reweighting rule, sliding and parallel window decoding for
8
+ streaming, Stim and sinter integration, and a VHDL implementation checked
9
+ bit for bit against the C++ model.
10
+ authors:
11
+ - family-names: "Dorélas"
12
+ given-names: "Jean-Cédrik"
13
+ type: software
14
+ license: MIT
15
+ version: "0.5.0"
16
+ date-released: "2026-11-05"
17
+ repository-code: "https://github.com/jcedrik/backlog"
18
+ keywords:
19
+ - quantum error correction
20
+ - surface code
21
+ - decoder
22
+ - union-find
23
+ - correlated decoding
24
+ - real-time decoding
25
+ - FPGA
@@ -0,0 +1,53 @@
1
+ # Contributing to backlog
2
+
3
+ Issues and pull requests are welcome: bug reports, new noise models or codes,
4
+ faster decoding, hardware work.
5
+
6
+ ## Set up
7
+
8
+ ```bash
9
+ git clone https://github.com/jcedrik/backlog && cd backlog
10
+ python3 -m venv .venv && source .venv/bin/activate
11
+ make install # builds the C++ core, installs the package with test extras
12
+ make test # C++ fuzzing against the reference, pytest, CLI checks
13
+ ```
14
+
15
+ You need a C++17 compiler, CMake 3.18+ and Python 3.10+. `make help` lists
16
+ every target.
17
+
18
+ ## What a change needs to pass
19
+
20
+ The CI runs all of these on every push; run them locally first.
21
+
22
+ | Check | Command | What it guards |
23
+ |---|---|---|
24
+ | C++ tests | `make test-cpp` | the fast decoder equals the reference decoder edge for edge, on 75,000 random cases per fuzzer, including correlated decoding and both window decoders |
25
+ | Python tests | `make test-py` | accuracy gates against PyMatching on real Stim circuits, sinter integration, exhaustive fault checks |
26
+ | ThreadSanitizer | `make tsan` | no data race in the parallel window decoder |
27
+ | Mutation testing | `make mutants` | every injected bug (26 of them) makes the suite fail; a new feature should come with a mutant its tests kill |
28
+ | VHDL | `make hw-sim` | the hardware decoder agrees with the C++ model bit for bit |
29
+
30
+ The decoder has a specification: `ReferenceDecoder` (synchronous rounds,
31
+ written to be obviously correct). A change to the fast decoder must keep the
32
+ two identical; a change to the semantics changes the reference first.
33
+
34
+ ## Benchmarks
35
+
36
+ Benchmark scripts write their CSVs and figures to `results/`. If a change
37
+ moves a published number, rerun the script that produced it and commit the
38
+ new results with the change, with the machine it ran on.
39
+
40
+ ## Releasing (maintainer)
41
+
42
+ Wheels for Linux, macOS and Windows are built by `.github/workflows/wheels.yml`.
43
+ To publish to PyPI without storing a token, once:
44
+
45
+ 1. on pypi.org, Account settings > Publishing > Add a new pending publisher:
46
+ project `backlog-qec`, owner `jcedrik`, repository `backlog`, workflow
47
+ `wheels.yml`, environment `pypi`;
48
+ 2. on GitHub, Settings > Environments > New environment `pypi`.
49
+
50
+ Then a release is: bump the version in `pyproject.toml` and
51
+ `src/backlog/__init__.py`, add its entry to `CHANGELOG.md`, commit, then push a
52
+ signed tag (`git tag -s v0.5.0 -m "backlog 0.5.0" && git push origin v0.5.0`).
53
+ The PyPI page shows `docs/pypi.md`, so its links must be absolute.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jean-Cédrik Dorélas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,101 @@
1
+ PY ?= python3
2
+
3
+ .PHONY: help deps install cpp test test-cpp test-py test-cli mutants tsan quick baseline plot \
4
+ compare plots streaming streaming-plot parallel parallel-plot scaling latency correlated \
5
+ correlated-speed correlated-plot faults faults-plot quickstart hw hw-sim all clean
6
+
7
+ help: ## list targets
8
+ @grep -E '^[a-z-]+:.*##' $(MAKEFILE_LIST) | sed -E 's/:.*## /\t/'
9
+
10
+ deps: ## install the Python dependencies of the experiments
11
+ $(PY) -m pip install -r requirements.txt
12
+
13
+ install: ## build the C++ core and install the backlog Python package (use a virtualenv)
14
+ $(PY) -m pip install ".[test]"
15
+
16
+ cpp: ## build the C++ command-line decoder and the C++ test suite
17
+ cmake -S cpp -B cpp/build -DCMAKE_BUILD_TYPE=Release
18
+ cmake --build cpp/build -j
19
+
20
+ test: test-cpp test-py test-cli ## all tests except the slow sweeps (run make install first)
21
+
22
+ test-cpp: cpp ## C++ unit tests + 75,000 fuzzed cases, fast decoder == reference decoder
23
+ cd cpp/build && ctest --output-on-failure
24
+
25
+ test-py: ## pytest: accuracy gates against PyMatching, sinter integration
26
+ $(PY) -m pytest -q
27
+
28
+ test-cli: cpp ## command-line decoder on graphs exported from Stim, gated against PyMatching
29
+ ./scripts/run_tests.sh
30
+
31
+ mutants: ## mutation testing: each of 26 injected bugs must make the test suite fail (~10 min)
32
+ $(PY) scripts/mutation_test.py
33
+
34
+ tsan: ## C++ test suite under ThreadSanitizer: any data race fails the run (~5 min)
35
+ cmake -S cpp -B cpp/build-tsan -DCMAKE_BUILD_TYPE=Debug -DBACKLOG_TSAN=ON
36
+ cmake --build cpp/build-tsan -j --target backlog_tests
37
+ TSAN_OPTIONS=halt_on_error=1 ./cpp/build-tsan/backlog_tests
38
+
39
+ quick: ## tiny PyMatching threshold sweep into results/quick/ (smoke test, seconds)
40
+ cd python && $(PY) baseline_threshold.py --quick && $(PY) plot_threshold.py --results-dir ../results/quick
41
+
42
+ baseline: ## PyMatching-only threshold sweep (a few minutes), see results/threshold.png
43
+ cd python && $(PY) baseline_threshold.py --max-shots 300000 --max-errors 1000
44
+
45
+ plot: ## redraw results/threshold.png from results/threshold_data.csv
46
+ cd python && $(PY) plot_threshold.py
47
+
48
+ compare: ## sinter sweep, PyMatching vs weighted and unweighted UF (long, resumable)
49
+ cd python && $(PY) threshold_comparison.py collect && $(PY) threshold_comparison.py plot
50
+
51
+ plots: ## redraw the comparison figures from results/threshold_comparison.csv
52
+ cd python && $(PY) threshold_comparison.py plot
53
+
54
+ streaming: ## sliding windows: accuracy vs buffer, per-window latency, backlog (minutes, idle machine)
55
+ cd python && $(PY) streaming_benchmark.py accuracy && $(PY) streaming_benchmark.py latency \
56
+ && $(PY) streaming_benchmark.py plot
57
+
58
+ streaming-plot: ## redraw results/streaming.png from the CSVs
59
+ cd python && $(PY) streaming_benchmark.py plot
60
+
61
+ parallel: ## parallel windows: accuracy, 1 vs 2 thread speedup, cores needed (minutes, idle machine)
62
+ cd python && $(PY) parallel_benchmark.py accuracy && $(PY) parallel_benchmark.py speedup \
63
+ && $(PY) parallel_benchmark.py project && $(PY) parallel_benchmark.py plot
64
+
65
+ parallel-plot: ## redraw results/parallel.png from the saved data
66
+ cd python && $(PY) parallel_benchmark.py plot
67
+
68
+ scaling: ## real speedup with 1, 2, 4, ... threads up to every core here, into results/scaling/
69
+ cd python && $(PY) parallel_benchmark.py scaling
70
+
71
+ correlated: ## correlated decoding vs plain and vs PyMatching, same shots (~15 min on 2 cores)
72
+ $(PY) python/correlated_benchmark.py accuracy && $(PY) python/correlated_benchmark.py decomposition
73
+
74
+ correlated-speed: ## decoding time of plain and correlated decoders (idle machine)
75
+ $(PY) python/correlated_benchmark.py speed
76
+
77
+ correlated-plot: ## redraw results/correlated.png and print the Lambda table
78
+ $(PY) python/correlated_benchmark.py plot
79
+
80
+ faults: ## exhaustive fault enumeration, d = 3 and 5: which pairs each decoder gets wrong (~6 min)
81
+ $(PY) python/fault_distance.py
82
+
83
+ faults-plot: ## redraw results/fault_distance.png
84
+ $(PY) python/fault_distance.py --plot
85
+
86
+ quickstart: ## rebuild and run examples/quickstart.ipynb (needs nbformat, nbclient, ipykernel)
87
+ $(PY) examples/make_quickstart.py
88
+
89
+ latency: ## decoding time vs PyMatching, d = 3 to 13 (run on an idle machine)
90
+ cd python && $(PY) latency_benchmark.py
91
+
92
+ hw: ## VHDL: bit-exact simulation, synthesis, place and route
93
+ ./hardware/run_hw.sh
94
+
95
+ hw-sim: ## VHDL: simulation only
96
+ ./hardware/run_hw.sh sim
97
+
98
+ all: test tsan mutants quick hw-sim ## everything CI runs
99
+
100
+ clean: ## remove build outputs
101
+ rm -rf cpp/build cpp/build-tsan hardware/build cpp/testdata* results/quick build _skbuild
@@ -0,0 +1,67 @@
1
+ Metadata-Version: 2.2
2
+ Name: backlog-qec
3
+ Version: 0.5.0
4
+ Summary: Real-time Union-Find decoder for quantum error correction: correlated, streaming, parallel, with Stim and sinter integration
5
+ Keywords: quantum error correction,decoder,union-find,correlated decoding,real-time decoding,stim,sinter,surface code,fpga
6
+ Author: Jean-Cédrik Dorélas
7
+ License: MIT
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: C++
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Scientific/Engineering :: Physics
14
+ Project-URL: Homepage, https://github.com/jcedrik/backlog
15
+ Project-URL: Documentation, https://github.com/jcedrik/backlog/blob/main/docs/decoder.md
16
+ Project-URL: Issues, https://github.com/jcedrik/backlog/issues
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: numpy>=1.24
19
+ Requires-Dist: stim>=1.14
20
+ Requires-Dist: sinter>=1.14
21
+ Provides-Extra: test
22
+ Requires-Dist: pytest>=7; extra == "test"
23
+ Requires-Dist: pymatching>=2.3; extra == "test"
24
+ Description-Content-Type: text/markdown
25
+
26
+ # backlog
27
+
28
+ **A real-time quantum error correction decoder: weighted Union-Find for the
29
+ surface code, with correlated decoding, streaming window decoders and Stim and
30
+ sinter integration.**
31
+
32
+ - As fast as PyMatching on one core, within 0 to 20% of its accuracy.
33
+ - Correlated (two-pass) decoding, with the regularized rule of
34
+ [arXiv:2610.26785](https://arxiv.org/abs/2610.26785): 32 to 67% fewer
35
+ logical errors than plain Union-Find at d = 7, within a few percent of
36
+ PyMatching's correlated matching, faster than it from d = 13.
37
+ - Sliding-window and parallel-window decoders for streaming.
38
+ - Tested edge for edge against a reference implementation, with exhaustive
39
+ fault enumeration, ThreadSanitizer and mutation testing.
40
+
41
+ ```bash
42
+ pip install backlog-qec
43
+ ```
44
+
45
+ ```python
46
+ import backlog, stim
47
+
48
+ circuit = stim.Circuit.generated("surface_code:rotated_memory_z", distance=5, rounds=5,
49
+ after_clifford_depolarization=0.003)
50
+ dets, obs = circuit.compile_detector_sampler().sample(100_000, separate_observables=True)
51
+
52
+ decoder = backlog.UnionFindDecoder.from_circuit(circuit, correlated=True)
53
+ print("logical error rate:", (decoder.decode_batch(dets) != obs).any(axis=1).mean())
54
+ ```
55
+
56
+ As sinter decoders: `backlog-uf`, `backlog-uf-corr` (pass
57
+ `custom_decoders=backlog.sinter_decoders()`).
58
+
59
+ ![Correlated decoding against plain decoding, same shots](https://raw.githubusercontent.com/jcedrik/backlog/main/results/correlated.png)
60
+
61
+ Results, how it works and how to reproduce everything:
62
+ [github.com/jcedrik/backlog](https://github.com/jcedrik/backlog) ·
63
+ [quickstart notebook](https://github.com/jcedrik/backlog/blob/main/examples/quickstart.ipynb) ·
64
+ [how the decoder works](https://github.com/jcedrik/backlog/blob/main/docs/decoder.md) ·
65
+ [state of the art](https://github.com/jcedrik/backlog/blob/main/docs/related-work.md)
66
+
67
+ MIT license. To cite: [CITATION.cff](https://github.com/jcedrik/backlog/blob/main/CITATION.cff).