Skip to content

Commit 7a2d108

Browse files
ChanceSiyuanclaude
andauthored
fix: handle disconnected components in tropical TN contraction (#70)
* feat: add tropical tensor network threshold analysis script Add scripts/analyze_tropical_threshold.py for analyzing the threshold of tropical tensor network MAP decoder on rotated surface codes. Key features: - Builds UAI factor graph from DEM parity check matrix - Uses tropical tensor network contraction for exact MAP inference - Computes observable prediction using mod-2 arithmetic with obs_flip thresholding - Generates threshold plots comparing LER across error rates Known limitation: MAP decoding finds the single most likely error pattern, but QEC requires the most likely observable value. This causes ~2x higher LER compared to BP+OSD which uses marginal probabilities. See issue for discussion of potential improvements. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: handle disconnected components in tropical TN contraction The tropical TN decoder was producing incorrect results because omeco.optimize_code only processes one connected component of the factor graph. When prior factors (single-variable) were disconnected from constraint factors, they were being dropped from the contraction tree. Changes: - Add _find_connected_components() using union-find algorithm - Modify get_omeco_tree() to handle multiple disconnected components - Update analyze_tropical_threshold.py to use pymatching graph structure - Add comprehensive tests for connected components handling - Add tests verifying Tropical TN matches MWPM on surface codes Fixes #68 * refactor: use bpdecoderplus.dem instead of pymatching for tropical TN Update analyze_tropical_threshold.py and tests to use build_parity_check_matrix from bpdecoderplus.dem instead of pymatching's graph structure: - Use merge_hyperedges=True for efficient computation (smaller matrix) - Threshold obs_flip at 0.5 for soft values from hyperedge merging - Remove pymatching dependency from core decoder (optional for comparison) - Update tests to use bpdecoderplus.dem functions The connected components fix ensures all factors are included in the contraction tree regardless of the matrix construction method. * Debug the tropical tensor network * docs: improve documentation with LaTeX math and benchmark results - Add MathJax support via pymdownx.arithmatex extension - Create mathjax.js config for proper math rendering - Convert mathematical_description.md to use proper LaTeX notation - Add benchmark results section to getting_started.md - Include threshold plots and decoder comparison images Closes #69 * fix: address PR review comments for tropical TN - Fix empty detector handling in test_tropical_fix.py to check syndrome - Convert combine_trees from recursive to iterative to avoid recursion limits - Add validation to get_output_vars for better error messages - Remove unused imports (pytest, torch) in test files - Remove unused observables variable in test_tropical_mwpm_match.py All 123 tests pass. * test: add tests for build_decoding_uai to improve coverage Add TestBuildDecodingUAI class with 6 tests: - test_basic_uai_structure: verify UAI header format - test_prior_factors: check prior probability values - test_constraint_factors_syndrome_zero: even parity constraints - test_constraint_factors_syndrome_one: odd parity constraints - test_empty_detector: handle detectors with no connected errors - test_real_surface_code: integration test with real DEM This improves code coverage for the new build_decoding_uai function. * test: increase code coverage from 95% to 97% Add additional tests for better coverage: - test_dem.py: Add tests for zero-probability errors and no-split mode - test_cli.py: Add tests for --generate-dem and --generate-syndromes flags - test_syndrome.py: Add tests for metadata edge cases (0-dim array, dict) - test_uai_parser.py: Add tests for Factor/UAIModel repr and empty evidence Total: 141 tests passing with 97% coverage. --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 7d3d79f commit 7a2d108

28 files changed

+3810
-498
lines changed

docs/getting_started.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,48 @@ A: Use UAI format if you want to:
428428
- Perform exact inference or marginal probability calculations
429429
- Use tensor network methods for decoding
430430

431+
## Benchmark Results
432+
433+
This section shows the performance benchmarks for the decoders included in BPDecoderPlus.
434+
435+
### Decoder Threshold Comparison
436+
437+
The threshold is the physical error rate below which increasing the code distance reduces the logical error rate. Our benchmarks compare BP and BP+OSD decoders:
438+
439+
![Threshold Plot](images/threshold_plot.png)
440+
441+
The threshold plot shows logical error rate vs physical error rate for different code distances. Lines that cross indicate the threshold point.
442+
443+
### BP vs BP+OSD Comparison
444+
445+
![Threshold Comparison](images/threshold_comparison.png)
446+
447+
BP+OSD (Ordered Statistics Decoding) significantly improves upon standard BP, especially near the threshold region.
448+
449+
### Decoding Examples
450+
451+
**BP Failure Case:**
452+
453+
![BP Failure Demo](images/bp_failure_demo.png)
454+
455+
This shows a case where standard BP fails to find the correct error pattern.
456+
457+
**OSD Success Case:**
458+
459+
![OSD Success Demo](images/osd_success_demo.png)
460+
461+
The same syndrome decoded successfully with BP+OSD post-processing.
462+
463+
### Benchmark Summary
464+
465+
| Decoder | Threshold (approx.) | Notes |
466+
|---------|---------------------|-------|
467+
| BP (damped) | ~8% | Fast, but limited by graph loops |
468+
| BP+OSD | ~10% | Higher threshold, slightly slower |
469+
| MWPM (reference) | ~10.3% | Gold standard for comparison |
470+
471+
The BP+OSD decoder achieves near-MWPM performance while being more scalable to larger codes.
472+
431473
## Next Steps
432474

433475
1. **Generate your first dataset** using the Quick Start command

docs/images/bp_failure_demo.png

116 KB
Loading

docs/images/osd_success_demo.png

127 KB
Loading
159 KB
Loading

docs/images/threshold_plot.png

104 KB
Loading

docs/javascripts/mathjax.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
window.MathJax = {
2+
tex: {
3+
inlineMath: [["\\(", "\\)"]],
4+
displayMath: [["\\[", "\\]"]],
5+
processEscapes: true,
6+
processEnvironments: true
7+
}
8+
};

docs/mathematical_description.md

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,53 @@ See https://github.com/TensorBFS/TensorInference.jl for the Julia reference.
77

88
### Factor Graph Notation
99

10-
- Variables are indexed by x_i with domain size d_i.
11-
- Factors are indexed by f and connect a subset of variables.
12-
- Each factor has a tensor (potential) phi_f defined over its variables.
10+
- Variables are indexed by \(x_i\) with domain size \(d_i\).
11+
- Factors are indexed by \(f\) and connect a subset of variables.
12+
- Each factor has a tensor (potential) \(\phi_f\) defined over its variables.
1313

1414
### Messages
1515

16-
Factor to variable message:
16+
**Factor to variable message:**
1717

18-
mu_{f->x}(x) = sum_{all y in ne(f), y != x} phi_f(x, y, ...) * product_{y != x} mu_{y->f}(y)
18+
\[
19+
\mu_{f \to x}(x) = \sum_{\{y \in \text{ne}(f), y \neq x\}} \phi_f(x, y, \ldots) \prod_{y \neq x} \mu_{y \to f}(y)
20+
\]
1921

20-
Variable to factor message:
22+
**Variable to factor message:**
2123

22-
mu_{x->f}(x) = product_{g in ne(x), g != f} mu_{g->x}(x)
24+
\[
25+
\mu_{x \to f}(x) = \prod_{g \in \text{ne}(x), g \neq f} \mu_{g \to x}(x)
26+
\]
2327

2428
### Damping
2529

2630
To improve stability on loopy graphs, a damping update is applied:
2731

28-
mu_new = damping * mu_old + (1 - damping) * mu_candidate
32+
\[
33+
\mu_{\text{new}} = \alpha \cdot \mu_{\text{old}} + (1 - \alpha) \cdot \mu_{\text{candidate}}
34+
\]
35+
36+
where \(\alpha\) is the damping factor (typically between 0 and 1).
2937

3038
### Convergence
3139

32-
We use an L1 difference threshold between consecutive factor->variable
33-
messages to determine convergence.
40+
We use an \(L_1\) difference threshold between consecutive factor-to-variable
41+
messages to determine convergence:
42+
43+
\[
44+
\max_{f,x} \| \mu_{f \to x}^{(t)} - \mu_{f \to x}^{(t-1)} \|_1 < \epsilon
45+
\]
3446

3547
### Marginals
3648

3749
After convergence, variable marginals are computed as:
3850

39-
b(x) = (1 / Z) * product_{f in ne(x)} mu_{f->x}(x)
51+
\[
52+
b(x) = \frac{1}{Z} \prod_{f \in \text{ne}(x)} \mu_{f \to x}(x)
53+
\]
54+
55+
The normalization constant \(Z\) is obtained by summing the unnormalized vector:
4056

41-
The normalization constant Z is obtained by summing the unnormalized vector.
57+
\[
58+
Z = \sum_x \prod_{f \in \text{ne}(x)} \mu_{f \to x}(x)
59+
\]

mkdocs.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ markdown_extensions:
4747
- pymdownx.details
4848
- attr_list
4949
- md_in_html
50+
- pymdownx.arithmatex:
51+
generic: true
52+
53+
extra_javascript:
54+
- javascripts/mathjax.js
55+
- https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js
5056

5157
nav:
5258
- Home: index.md

0 commit comments

Comments
 (0)