Add GARI and generic detector layout support to decoder CLIs - #277
Add GARI and generic detector layout support to decoder CLIs #277arshpreetmaan wants to merge 39 commits into
Conversation
LalehB
left a comment
There was a problem hiding this comment.
can you also make sure that you update the README with examples as well please?
|
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: This keeps the other caches enabled while ensuring native binaries are rebuilt on each runner. |
@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? |
|
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 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.
|
Hi @arshpreetmaan @LalehB , WDYT about this alternative API: |
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
@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? |
|
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.) |
Overview
This PR makes the GARI transformed matrices introduced in #273 directly usable with the Tesseract and Simplex command-line decoders.
The main design change is that a GARI matrix DEM now preserves the original circuit detector IDs as a prefix and appends its virtual detectors as a suffix. Source-circuit shots can therefore be decoded without a GARI-specific remapping file: the physical syndrome occupies the prefix, while the virtual suffix is initialized to zero.
This PR also adds a generic
--detector-ordersoption to the Tesseract CLI. This brings the C++ CLI closer to the Python API, where explicit detector orders can already be supplied throughTesseractConfig.det_orders. The option is not specific to GARI and can be used with any compatible DEM.Problems addressed
This PR addresses two related limitations.
1. Source circuits and GARI matrix DEMs have different detector counts
A GARI matrix DEM contains the original physical detectors followed by additional virtual detectors. Previously, the command-line decoders assumed that circuit shots and the decoding DEM used the same detector width.
That prevented safe decoding of sampled or saved source-circuit syndromes against a larger GARI matrix DEM, particularly for fixed-width formats such as
b8.2. The Tesseract CLI could not accept explicit detector orders
The Python API accepts detector-order permutations through
TesseractConfig.det_orders, but the C++ CLI could only generate orders internally.This PR adds a generic JSON input for explicit detector orders, allowing the same order lists to be used through either interface.
Source-aligned GARI matrix DEMs
By default,
demutil.gari.circuit_to_garinow serializes detector rows as:A syndrome produced by the source circuit can therefore be placed at the beginning of a zero-filled GARI syndrome without changing its detector IDs.
No GARI-specific layout or remapping JSON file is required.
The internal research-oriented block layout remains available through:
That form uses the physical-X, physical-Z, virtual-Z, virtual-X row ordering from the matrix construction and is written with a
_block.demsuffix. It is intended for matrix analysis and does not accept source syndromes directly as a prefix.Source-width input handling
When both
--circuitand--demare supplied, Tesseract and Simplex:This applies to sampled shots and saved detection-event files, including fixed-width
b8data.When
--demis supplied without--circuit, input records continue to use the full DEM detector count. Therefore, a source-width saved shot file should be decoded by supplying both its source circuit and its larger GARI matrix DEM.The GARI matrix DEM is a decoding representation and must not be sampled directly. Shots must be sampled from the original circuit.
Explicit Tesseract detector orders
Tesseract now accepts:
The file uses the same list-of-lists representation as Python’s
TesseractConfig.det_orders. Each inner list contains detector IDs in traversal order and must be a complete permutation of all detector IDs in the decoding DEM.For example:
The implementation rejects:
--detector-orderscannot be combined with the internally generated detector-order options:--num-det-orders--det-order-seed--det-order-bfs--det-order-index--det-order-coordinateSimplex does not use detector traversal orders, so it does not receive this option.
This PR deliberately leaves the existing BFS and coordinate detector-order generation behavior unchanged. Any correction to those existing generators can be handled in a separate focused PR.
Statistics
The existing statistics include the circuit and DEM paths used for the run.
Tesseract statistics now additionally record:
detector_orders_pathnum_det_ordersThis records whether an explicit detector-order file was used and how many orders were decoded.
Generating a GARI matrix DEM
From a Python environment containing Stim, NumPy, SciPy, and the Tesseract Decoder Python package, generate a source-aligned GARI matrix DEM with:
python src/py/_tesseract_py_util/gari.py \ --circuit circuit_file.stim \ --prior xor \ --out-dir gari_outputThis writes:
The available prior policies are:
paperxorlp-max-barred-costThe same conversion is available through the public Python API:
Optional detector-order file
Explicit detector orders are optional. Without
--detector-orders, Tesseract continues to use its existing internally generated orders.For a source-aligned GARI matrix DEM, the Python helper can generate index-based source orders and append the virtual detector IDs:
The resulting file can be passed directly to
--detector-orders.Tesseract example
Build Tesseract:
Sample from the original circuit and decode with the GARI matrix DEM:
./bazel-bin/src/tesseract \ --circuit circuit_file.stim \ --dem gari_output/circuit_file_gari_xor.dem \ --detector-orders gari_orders.json \ --sample-num-shots 100 \ --sample-seed 1234 \ --threads 1 \ --pqlimit 1000000 \ --beam 5 \ --beam-climbing \ --no-revisit-dets \ --print-stats \ --stats-out tesseract_gari_stats.jsonTo use Tesseract’s existing internally generated detector orders, omit
--detector-ordersand use the usual detector-order options.Simplex example
Build Simplex:
Sample from the original circuit and decode with the same GARI matrix DEM:
./bazel-bin/src/simplex \ --circuit circuit_file.stim \ --dem gari_output/circuit_file_gari_xor.dem \ --sample-num-shots 100 \ --sample-seed 1234 \ --threads 1 \ --print-stats \ --stats-out simplex_gari_stats.jsonSimplex follows the same source-prefix syndrome convention but does not require a detector-order file.
Saved source-shot data
A source-width detection-event file can also be decoded against a larger GARI matrix DEM:
./bazel-bin/src/tesseract \ --circuit circuit_file.stim \ --dem gari_output/circuit_file_gari_xor.dem \ --in source_shots.b8 \ --in-format b8 \ --threads 1 \ --beam 5 \ --beam-climbing \ --no-revisit-dets \ --print-statsProviding the circuit is important because it defines the width of each source-shot record. With
--demalone, the reader expects full GARI-width records.