Skip to content

Add GARI support to decoder CLIs - #277

Open
arshpreetmaan wants to merge 23 commits into
quantumlib:mainfrom
arshpreetmaan:gari-pr269-B-cpp
Open

Add GARI support to decoder CLIs#277
arshpreetmaan wants to merge 23 commits into
quantumlib:mainfrom
arshpreetmaan:gari-pr269-B-cpp

Conversation

@arshpreetmaan

@arshpreetmaan arshpreetmaan commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR adds C++ CLI support for consuming the GARI matrix and layout files produced by the Python utilities in #273.

  • Add --gari-layout support to Tesseract and Simplex.
  • Validate the GARI layout schema, detector counts, detector mapping, and observable counts.
  • Map physical detector events from circuits or shot files into the corresponding GARI matrix rows.
  • Treat virtual detector rows as zero when constructing decoder shots.
  • Use physical-then-virtual detector traversal by default in Tesseract.
  • Generate explicit index, BFS, or coordinate detector orderings from the original source circuit, map the resulting physical detector order through the GARI layout, and append virtual detectors in their natural order.

Simplex applies the source-to-GARI detector mapping but does not otherwise interpret detector ordering.

Example

Generate a GARI matrix and layout from a circuit:

python src/py/_tesseract_py_util/gari.py \
    --circuit circuit_file.stim \
    --prior xor \
    --out-dir gari_output

This produces:

gari_output/circuit_file_gari_xor.dem
gari_output/circuit_file_gari_xor_layout.json

Tesseract can sample from the original circuit and decode using the GARI matrix:

./bazel-bin/src/tesseract \
    --circuit circuit_file.stim \
    --dem gari_output/circuit_file_gari_xor.dem \
    --gari-layout gari_output/circuit_file_gari_xor_layout.json \
    --sample-num-shots 100 \
    --sample-seed 1234 \
    --threads 1 \
    --pqlimit 1000000 \
    --beam 5 \
    --beam-climbing \
    --no-revisit-dets \
    --print-stats \
    --stats-out gari-stats.json

We recommend using a smaller beam size (5 or 10 than usual longbeam 20) which provides a useful runtime/accuracy tradeoff while decoding with GARI dem as GARI reduces the row (check) weight by roughly 10 times for the tested BB codes and color codes circuits.

Detector-order options are omitted above, so Tesseract processes the GARI rows in their stored physical-then-virtual order. If explicit detector ordering is requested, Tesseract constructs the order from the source circuit, maps only the physical detector portion, and keeps the virtual detector portion in its natural order.

The same files can be used with Simplex:

./bazel-bin/src/simplex \
    --circuit circuit_file.stim \
    --dem gari_output/circuit_file_gari_xor.dem \
    --gari-layout gari_output/circuit_file_gari_xor_layout.json \
    --sample-num-shots 100 \
    --sample-seed 1234 \
    --threads 1 \
    --stats-out simplex_gari_stats.json

Note: The GARI DEM is a decoding representation and is never sampled. Detection-event data must either be sampled from the original source circuit or loaded from a file containing detector events in the original source-circuit detector order. The companion layout maps those source detector events into the physical GARI rows; virtual GARI rows are initialized to zero. When decoding source-circuit detection-event files against a GARI DEM, --gari-layout must be supplied. Without the layout, the CLI interprets the records in the loaded DEM's detector space and cannot infer the source-to-GARI permutation. The .dem and _layout.json files must be the pair generated from the same source circuit.

@arshpreetmaan
arshpreetmaan requested review from LalehB and noajshu July 27, 2026 07:58
@arshpreetmaan
arshpreetmaan requested a review from a team as a code owner July 27, 2026 07:58
Comment thread src/tesseract_main.cc

@LalehB LalehB left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you also make sure that you update the README with examples as well please?

Comment thread src/utils.cc Outdated
@arshpreetmaan

Copy link
Copy Markdown
Collaborator Author

The CI failure appears unrelated to the GARI changes. It seems to come from Bazel reusing cached binaries built on a different CPU. A possible fix is to disable only the Bazel disk cache:
In [.github/workflows/ci.yml (line 67)]

with:
  bazelisk-cache: true
  disk-cache: false
  repository-cache: true

This keeps the other caches enabled while ensuring native binaries are rebuilt on each runner.

@mhucka

mhucka commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

The CI failure appears unrelated to the GARI changes. It seems to come from Bazel reusing cached binaries built on a different CPU.

@arshpreetmaan Can you provide more info about the "different CPU" part? Since the GitHub workflows always run on the same type of runner, one would expect the CPU to be the same. Do you suspect a difference in the CPU feature sets?

@mhucka

mhucka commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

One thing I do see, though, is that the disk-cache should be further parametrized by the matrix OS. I'll do a quick PR.

@mhucka mhucka closed this Aug 10, 2026
@mhucka mhucka reopened this Aug 10, 2026
@arshpreetmaan

Copy link
Copy Markdown
Collaborator Author

One thing I do see, though, is that the disk-cache should be further parametrized by the matrix OS. I'll do a quick PR.

Thanks, PR #295 might fix the issue. By “different CPU,” I meant that separate GitHub-hosted ubuntu-latest VMs may expose different CPU instruction features, even though they are all Linux x64 runners. Since the build uses -march=native, cached binaries can depend on those exact features.
The new per-OS cache name should clear the existing cache and likely fix the current failure in #277. We can rerun #277 after #295 is merged; if the Illegal instruction failure returns later, we may need to consider other options (perhaps making -march=native optional or using -march=x86-64 for CI).

LalehB pushed a commit that referenced this pull request Aug 10, 2026
The Bazel disk cache should probably be scoped by the `matrix.os` value
and the Python version in matrix jobs. This observation was spurred by
#277 (comment),
although it is not yet clear whether narrowing the scope will in fact
fix the failure in that PR.

@LalehB LalehB left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Arshpreet!

@noajshu

noajshu commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Hi @arshpreetmaan @LalehB , WDYT about this alternative API:
just like how tesseract accepts detector orders via its python module API, we could accept one or more detector orders via the CLI. And the GARI code in demutil code can generate the gari-aware detector orders too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants