Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
99de4ef
Add validated GARI matrix transformation
arshpreetmaan Jul 26, 2026
8b7a68a
Add canonical Stim adapter for GARI
arshpreetmaan Jul 26, 2026
9f742a6
Add documented GARI prior policies
arshpreetmaan Jul 26, 2026
e7fd38c
Add GARI converter and layout artifact
arshpreetmaan Jul 26, 2026
0de20c5
Add GARI decoding example and documentation
arshpreetmaan Jul 26, 2026
e50c834
Simplify GARI source DEM pipeline
arshpreetmaan Jul 27, 2026
47c0568
Further simplify GARI implementation
arshpreetmaan Jul 27, 2026
5f1533c
Clarify and simplify GARI prior policies
arshpreetmaan Jul 27, 2026
f0dc7f0
Replace GARI maximin with max-barred-cost prior
arshpreetmaan Jul 27, 2026
c5abf7f
Simplify GARI helpers and use short-beam example
arshpreetmaan Jul 27, 2026
2eec303
Add GARI transform block metadata
arshpreetmaan Jul 27, 2026
4fb2c78
Simplify GARI decoding example
arshpreetmaan Jul 27, 2026
ec06ca0
Remove unused GARI layout row blocks
arshpreetmaan Jul 27, 2026
6bc5788
Fix GARI utility package initialization
arshpreetmaan Jul 27, 2026
7d9f97c
Add compact GARI circuit conversion entry point
arshpreetmaan Jul 27, 2026
0dc3721
Remove standalone GARI scripts
arshpreetmaan Jul 27, 2026
09bd58e
Simplify GARI matrix construction
arshpreetmaan Jul 27, 2026
0563392
Merge remote-tracking branch 'upstream/main' into gari-pr269-A-python
arshpreetmaan Jul 27, 2026
812dfda
Package GARI Python utilities
arshpreetmaan Jul 27, 2026
8b97661
Add GARI decoding tutorial
arshpreetmaan Jul 27, 2026
54f6365
Merge remote-tracking branch 'upstream/main' into gari-pr269-A-python
arshpreetmaan Jul 27, 2026
e660dd5
Trim GARI prior test coverage
arshpreetmaan Jul 27, 2026
59076b0
Relocate and expand GARI tutorial
arshpreetmaan Jul 27, 2026
d6ee6e9
Rename correlated-decoding tutorial section
arshpreetmaan Jul 27, 2026
db102c7
Reuse tutorial color-code data for GARI
arshpreetmaan Jul 27, 2026
d32af3b
Simplify GARI tutorial variable names
arshpreetmaan Jul 27, 2026
8d50842
Remove unrelated Python BUILD formatting diff
arshpreetmaan Jul 27, 2026
dbf8b89
Simplify GARI utility integration
arshpreetmaan Jul 31, 2026
09f5b0b
Simplify GARI module loading
arshpreetmaan Jul 31, 2026
77f52e6
Refine GARI DEM utility interface
arshpreetmaan Jul 31, 2026
839b17b
Simplify generalized DEM CLI paths
arshpreetmaan Jul 31, 2026
91f5d2e
Improve GARI conversion safety and output naming
arshpreetmaan Jul 31, 2026
4542f77
cleanup
arshpreetmaan Jul 31, 2026
0d3739e
Clarify GARI public API
arshpreetmaan Jul 31, 2026
43380a7
Merge branch 'main' into gari-pr269-A-python
LalehB Jul 31, 2026
d9f2615
Update test assertions for gari
arshpreetmaan Jul 31, 2026
e2f8990
Refactor GARI utility integration
arshpreetmaan Aug 3, 2026
8e78688
Add license headers
arshpreetmaan Aug 3, 2026
e5cf735
Simplify GARI CLI and test public conversion
arshpreetmaan Aug 3, 2026
cbaa9a6
Address GARI dependency and test feedback
arshpreetmaan Aug 3, 2026
d4bdcf4
Add Dependabot cooldowns
arshpreetmaan Aug 3, 2026
26ab580
Avoid repository-wide dependency changes
arshpreetmaan Aug 4, 2026
b725861
Define LP prior
arshpreetmaan Aug 4, 2026
e4987d6
Document GARI circuit requirements
arshpreetmaan Aug 4, 2026
58b1bce
Handle canceled GARI source errors
arshpreetmaan Aug 5, 2026
612603c
Merge branch 'main' into gari-pr269-A-python
arshpreetmaan Aug 5, 2026
7727e37
Document GARI Python API
arshpreetmaan Aug 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ py_wheel(
],
version = "$(VERSION)",
requires=[
"numpy",
"scipy",
"stim",
],
python_tag="$(TARGET_VERSION)",
Expand Down
93 changes: 93 additions & 0 deletions docs/tutorial.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -906,6 +906,99 @@
"print_results(results)"
]
},
{
"cell_type": "markdown",
"id": "2b9319e5",
"metadata": {
"id": "gari-correlated-decoding"
},
"source": [
"# Faster Methods of Decoding Correlated Errors with Tesseract\n",
"\n",
"## GARI\n",
"\n",
"Graph augmentation and rewiring for inference (GARI) transforms a correlated\n",
"CSS detector matrix into a block form for Tesseract; see [Decoding correlated\n",
"errors in quantum LDPC codes](https://doi.org/10.1038/s41467-026-70556-3).\n",
"This example reuses the superdense color-code memory-Z circuit and sampled\n",
"data from above, and applies the XOR prior policy."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fd1644de",
"metadata": {
"id": "gari-transform-example"
},
"outputs": [],
"source": [
"gari = tesseract_decoder.demutil.gari\n",
"\n",
"gari_dem, gari_layout = gari.circuit_to_gari(\n",
" circuit,\n",
" prior_function=gari.tesseract_xor_prior_probabilities,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "34e07e3a",
"metadata": {
"id": "gari-syndrome-layout"
},
"source": [
"Sample detection events only from the original circuit. The GARI matrix DEM\n",
"stores the transformed matrices for decoding and is not sampled. Copy the\n",
"source syndrome into its physical rows; the added virtual entries stay zero."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d22c7d2c",
"metadata": {
"id": "gari-sample-example"
},
"outputs": [],
"source": [
"num_shots = 10\n",
"gari_dets = np.zeros((num_shots, gari_dem.num_detectors), dtype=bool)\n",
"gari_dets[:, gari_layout[\"source_to_gari\"]] = dets[:num_shots]"
]
},
{
"cell_type": "markdown",
"id": "abc39564",
"metadata": {
"id": "gari-detector-order"
},
"source": [
"The layout is physical-then-virtual. Setting `num_det_orders=0` selects one\n",
"ascending detector order, so Tesseract processes the rows in that order."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bc0c802c",
"metadata": {
"id": "gari-decode-example"
},
"outputs": [],
"source": [
"short_beam = tesseract_decoder.make_tesseract_sinter_decoders_dict()[\n",
" \"tesseract-short-beam\"\n",
"]\n",
"short_beam.num_det_orders = 0\n",
"gari_decoder = short_beam.compile_decoder_for_dem(dem=gari_dem).decoder\n",
"predicted_observables = gari_decoder.decode_batch(gari_dets)\n",
"logical_failures = np.count_nonzero(\n",
" np.any(predicted_observables != obs[:num_shots], axis=1)\n",
")\n",
"print(f\"Logical failures: {logical_failures}/{num_shots}\")"
]
},
{
"cell_type": "markdown",
"metadata": {
Expand Down
45 changes: 45 additions & 0 deletions docs/tutorial.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,51 @@ def run_tesseract_decoder(decoder, dets, obs):
results = run_tesseract_decoder(tesseract_config2.compile_decoder(), dets, obs)
print_results(results)

# %% [markdown] id="gari-correlated-decoding"
# # Faster Methods of Decoding Correlated Errors with Tesseract
#
# ## GARI
#
# Graph augmentation and rewiring for inference (GARI) transforms a correlated
# CSS detector matrix into a block form for Tesseract; see [Decoding correlated
# errors in quantum LDPC codes](https://doi.org/10.1038/s41467-026-70556-3).
# This example reuses the superdense color-code memory-Z circuit and sampled
# data from above, and applies the XOR prior policy.

# %% id="gari-transform-example"
gari = tesseract_decoder.demutil.gari

gari_dem, gari_layout = gari.circuit_to_gari(
circuit,
prior_function=gari.tesseract_xor_prior_probabilities,
)

# %% [markdown] id="gari-syndrome-layout"
# Sample detection events only from the original circuit. The GARI matrix DEM
# stores the transformed matrices for decoding and is not sampled. Copy the
# source syndrome into its physical rows; the added virtual entries stay zero.

# %% id="gari-sample-example"
num_shots = 10
gari_dets = np.zeros((num_shots, gari_dem.num_detectors), dtype=bool)
gari_dets[:, gari_layout["source_to_gari"]] = dets[:num_shots]

# %% [markdown] id="gari-detector-order"
# The layout is physical-then-virtual. Setting `num_det_orders=0` selects one
# ascending detector order, so Tesseract processes the rows in that order.

# %% id="gari-decode-example"
short_beam = tesseract_decoder.make_tesseract_sinter_decoders_dict()[
"tesseract-short-beam"
]
short_beam.num_det_orders = 0
gari_decoder = short_beam.compile_decoder_for_dem(dem=gari_dem).decoder
predicted_observables = gari_decoder.decode_batch(gari_dets)
logical_failures = np.count_nonzero(
np.any(predicted_observables != obs[:num_shots], axis=1)
)
print(f"Logical failures: {logical_failures}/{num_shots}")

# %% [markdown] id="BoEALeo3OYGp"
# # Decoding Wild Stabilizer Codes under Code Capacity Noise with Tesseract
#
Expand Down
45 changes: 45 additions & 0 deletions src/py/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -678,3 +678,48 @@ nice_calibrated_dem = demutil.regeneralize_spatial_dem(
)
# Result will have error probability (0.1 + 0.2) / 2 = 0.15
```

#### GARI transformed matrices

`demutil.gari.circuit_to_gari` converts a supported correlated CSS Stim
circuit into a GARI matrix DEM and companion layout for Tesseract. It
generates a flattened source DEM with `decompose_errors=False`. Detectors must
follow the repository's fourth-coordinate convention: values `0`–`2` identify
X detectors and `3`–`5` identify Z detectors.

```python
import stim
from tesseract_decoder import demutil

circuit = stim.Circuit.from_file("circuitFile.stim")
gari_dem, gari_layout = demutil.gari.circuit_to_gari(
circuit,
prior_function=demutil.gari.tesseract_xor_prior_probabilities,
)
```

`circuit_to_gari` returns:

* `gari_dem`: the augmented detector and logical matrices stored using Stim
DEM syntax.
* `gari_layout`: a `tesseract.gari_layout.v1` dictionary containing the source
and GARI detector counts, the `source_to_gari` detector mapping, and the
`physical_then_virtual` detector order.

Related public APIs:

* `demutil.gari.dem_to_matrices(dem)` returns the sparse detector matrix,
sparse logical matrix, and one probability per source error column.
* `demutil.gari.GariTransform` is passed to prior-policy callbacks. It exposes
the transformed detector and logical matrices, the `U` and `V` projection
matrices, the source `e_Z`, `e_X`, and `e_Y` column indices, and the source
detector mapping.
* `paper_prior_probabilities`, `tesseract_xor_prior_probabilities`, and
`tesseract_lp_max_barred_cost_prior_probabilities` return one probability for
each transformed GARI column. A user-defined prior can follow the same
callable interface.

The returned GARI matrix DEM stores transformed matrices for decoding and must
not be sampled. Sample from the original circuit and use the companion layout
to place its physical syndrome. See the
[GARI tutorial](../../docs/tutorial.ipynb) for a complete decoding example.
15 changes: 15 additions & 0 deletions src/py/_tesseract_py_util/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ py_library(
deps = [
"@pypi//stim",
"@pypi//numpy",
"@pypi//scipy",
],
)

py_test(
name = "gari_test",
srcs = ["gari_test.py"],
imports = ["..", ".", "../.."],
visibility = ["//:__subpackages__"],
deps = [
":_tesseract_py_util",
"@pypi//numpy",
"@pypi//pytest",
"@pypi//stim",
"//src:lib_tesseract_decoder",
],
)

Expand Down
1 change: 1 addition & 0 deletions src/py/_tesseract_py_util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
and related utilities, in `decompose_errors.py` and `generalize_dem.py`.
"""

from _tesseract_py_util import gari as gari
from _tesseract_py_util.demutil import decompose_errors
from _tesseract_py_util.generalize_dem import \
generalize as regeneralize_spatial_dem
1 change: 1 addition & 0 deletions src/py/_tesseract_py_util/demutil_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def test_import_exposes_demutil_submodule():
assert hasattr(tesseract_decoder, "demutil")
assert hasattr(demutil, "regeneralize_spatial_dem")
assert hasattr(demutil, "decompose_errors")
assert hasattr(demutil.gari, "circuit_to_gari")


def test_decompose_errors_rejects_unknown_method():
Expand Down
Loading
Loading