Skip to content

Add GARI support via file-specified detector orders to decoder CLI - #277

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

Add GARI support via file-specified detector orders to decoder CLI#277
arshpreetmaan wants to merge 18 commits into
quantumlib:mainfrom
arshpreetmaan:gari-pr269-B-cpp

Conversation

@arshpreetmaan

@arshpreetmaan arshpreetmaan commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

This connects the existing Python GARI transform to the Tesseract CLI. It also introduces DetectorOrder, so we can specify how to construct an order before the decoding DEM is known. This is useful here and for the component decoders in #256.

Detector orders

One DetectorOrder represents one permutation. It either contains a literal permutation (Method::Literal) or a method (BFS, Index, or Coordinate) and seed. resolve(dem) fills in the order in place; for literal orders it validates the supplied permutation. Callers do not need separate handling for the two cases.

TesseractConfig holds a vector of these objects. Generated orders are resolved against the actual decoding DEM, with graph/coordinate preparation shared across the batch. Order k uses seed + k, rather than depending on a shared random-number stream. Every order must be a complete permutation of the DEM's detector IDs.

The Tesseract CLI can combine generated methods and JSON order files, in command-line order:

./tesseract --circuit source.stim --dem transformed.dem \
    --num-det-orders 3 --det-order-bfs \
    --detector-orders gari-orders.json --det-order-coordinate

Each generated source contributes --num-det-orders orders, using --det-order-seed as its base seed. --detector-orders FILE can be repeated and contributes every permutation in that file. The format is a JSON list of lists, just like Python's det_orders.

With no source flags, the default is Index. A file-only invocation stays file-only; add --det-order-index to combine it with Index orders. Count/seed flags with files but no generated method are rejected. The bookkeeping for these CLI sources stays local to the CLI, not in the library API.

GARI workflow

GARI transformation and GARI-aware order construction stay in Python. demutil.gari.circuit_to_gari(...) returns the transformed DEM directly, with source detector IDs first and virtual detectors appended. No layout sidecar is needed.

demutil.gari.build_detector_orders(...) constructs orders from the source DEM, appends virtual detector IDs, and checks that the decoding DEM has the expected GARI check and logical matrices. Probability-only reweighting is allowed.

When given both a circuit and a larger decoding DEM, the Tesseract and Simplex CLIs read/sample the circuit-width syndrome and leave the extra DEM detectors zero. The observable counts must agree. The order-file option is specific to the Tesseract CLI.

Python keeps the list-of-lists interface and existing detector-order aliases. Ordinary TesseractSinterDecoder construction and registry names are unchanged; generated orders resolve when the compilation DEM is available. This does not add a GARI-specific Sinter frontend.

GARI requires undecomposed source errors: ^ groups and logical-only errors are rejected. Its basis convention here is fourth coordinate 0/1/2 for X and 3/4/5 for Z. GARI-aware orders require the default source-aligned layout; row_order="block" remains available for matrix work. The transformed DEM is for decoding, not sampling.

Tests

Coverage includes generated/literal resolution, per-order seeds, permutation and file validation, Python compatibility, deferred Sinter orders, GARI layouts and matrix checks, and source-width shots decoded against a larger DEM. The full bazel test --jobs=1 src/... suite passed during implementation.

@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 Outdated

@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.

@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.

@arshpreetmaan arshpreetmaan changed the title Add GARI support to decoder CLIs Add GARI and generic detector layout support to decoder CLIs Aug 21, 2026
@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@LalehB

LalehB commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

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.

@noajshu I think your proposed alternative API would be a good addition. I dunno if @arshpreetmaan addressed that.

@arshpreetmaan

Copy link
Copy Markdown
Collaborator Author

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.

@noajshu I think your proposed alternative API would be a good addition. I dunno if @arshpreetmaan addressed that.

Hi @LalehB @noajshu , I have applied the suggested API changes. Can you PTAL?

Comment thread src/simplex_main.cc Outdated
@noajshu

noajshu commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

I think this is becoming more complicated than necessary. In particular, I don't think detector remapping and detector ordering need to be coupled into a new detector_layout schema.

For GARI, can we instead have the generated DEM preserve the original detector IDs for the physical detectors and append the virtual detectors as a suffix? Then shots from the source circuit need no remapping at all: the first circuit.num_detectors entries are the physical syndrome and the remaining DEM detectors are implicitly zero. The C++ CLI would only need to support this source-prefix/augmented-DEM case when reading or sampling shots, rather than introducing a general mapping format.

Separately, if we want the C++ CLI to support explicit detector orders, I think that should just be a detector-orders file mirroring TesseractConfig.det_orders in the Python API.

Also, there is currently an inconsistency in what a “detector order” means between build_det_orders, the C++ decoder, and the Python-facing API. I think we should fix that first and use one representation everywhere (matching the current python API.)

noajshu pushed a commit to arshpreetmaan/tesseract-decoder that referenced this pull request Aug 25, 2026
Rebase the final PR quantumlib#277 feature onto detector traversal semantics from PR quantumlib#306. Remove the obsolete GARI order inversion so generated physical detector prefixes use detector_at_position directly.

Co-authored-by: Aria Shahingohar <ariash@google.com>
noajshu pushed a commit to arshpreetmaan/tesseract-decoder that referenced this pull request Aug 26, 2026
Rebase the final PR quantumlib#277 feature onto detector traversal semantics from PR quantumlib#306. Remove the obsolete GARI order inversion so generated physical detector prefixes use detector_at_position directly.

Co-authored-by: Aria Shahingohar <ariash@google.com>
noajshu pushed a commit to arshpreetmaan/tesseract-decoder that referenced this pull request Aug 26, 2026
Rebase the final PR quantumlib#277 feature onto detector traversal semantics from PR quantumlib#306. Remove the obsolete GARI order inversion so generated physical detector prefixes use detector_at_position directly.

Co-authored-by: Aria Shahingohar <ariash@google.com>
noajshu pushed a commit to arshpreetmaan/tesseract-decoder that referenced this pull request Aug 26, 2026
Rebase the final PR quantumlib#277 feature onto detector traversal semantics from PR quantumlib#306. Remove the obsolete GARI order inversion so generated physical detector prefixes use detector_at_position directly.

Co-authored-by: Aria Shahingohar <ariash@google.com>
noajshu pushed a commit to arshpreetmaan/tesseract-decoder that referenced this pull request Aug 26, 2026
Rebase the final PR quantumlib#277 feature onto detector traversal semantics from PR quantumlib#306. Remove the obsolete GARI order inversion so generated physical detector prefixes use detector_at_position directly.

Co-authored-by: Aria Shahingohar <ariash@google.com>
@noajshu
noajshu changed the base branch from main to codex/fix-detector-order-semantics August 26, 2026 17:26
@noajshu
noajshu force-pushed the codex/fix-detector-order-semantics branch from bb26f60 to edda6f0 Compare August 26, 2026 17:26
Rebase the final PR quantumlib#277 feature onto detector traversal semantics from PR quantumlib#306. Remove the obsolete GARI order inversion so generated physical detector prefixes use detector_at_position directly.

Co-authored-by: Aria Shahingohar <ariash@google.com>
@noajshu noajshu changed the title Add GARI and generic detector layout support to decoder CLIs Add GARI support via file-specified detector orders to decoder CLI Aug 26, 2026
@noajshu
noajshu force-pushed the codex/fix-detector-order-semantics branch from 1bbd3ff to 02b7c04 Compare September 1, 2026 15:00
@noajshu
noajshu deleted the branch quantumlib:main September 1, 2026 15:17
@noajshu noajshu closed this Sep 1, 2026
# Conflicts:
#	src/py/tesseract_test.py
#	src/tesseract.cc
#	src/tesseract.test.cc
#	src/utils.cc
@noajshu noajshu reopened this Sep 2, 2026
@noajshu
noajshu changed the base branch from codex/fix-detector-order-semantics to main September 2, 2026 04:39
@noajshu noajshu mentioned this pull request Sep 7, 2026
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