Add chromobius decoder to the decoder plugins#546
Conversation
Add a QEC decoder plugin wrapping Chromobius through the existing decoder factory API. The wrapper accepts a Stim DEM via params, packs detector syndromes for Chromobius, and returns predicted observable flips. Also add Chromobius plugin build wiring and focused unit tests covering construction, decoding, DEM path loading, and validation failures. Fix a PyMatching pointer member access that broke the plugin build. Signed-off-by: Scott Thornton <wsttiger@gmail.com>
- Register the Chromobius decoder with the CUDA-QX extension-point macro - Add small upstream-derived DEM/reference shot data for observable predictions - Add C++ and Python tests that validate single-shot and batched Chromobius decode results - Keep the GCC 12 GTest workaround private so it does not leak into CUDA test builds - Apply minor formatting cleanups in touched tests/headers Signed-off-by: Scott Thornton <wsttiger@gmail.com>
Signed-off-by: Scott Thornton <wsttiger@gmail.com>
fc04644 to
5587a30
Compare
Signed-off-by: Scott Thornton <wsttiger@gmail.com>
| std::string get_dem_text(const cudaqx::heterogeneous_map ¶ms) { | ||
| if (params.contains("dem")) | ||
| return params.get<std::string>("dem"); | ||
| if (params.contains("dem_str")) |
There was a problem hiding this comment.
dem_str is a functional duplicate of dem — same getstd::string lookup, same return, no transformation, and dem wins if both are passed.
Grepping the repo turns up zero callers of dem_stras a parameter key: neither test_chromobius.cpp nor test_chromobius.py exercises it, and there are no examples or docs that pass it.
Suggest dropping dem_str from get_dem_text and keeping just dem / dem_path
| } | ||
|
|
||
| TEST(ChromobiusDecoder, checkDemPath) { | ||
| const std::string dem_path = "/tmp/cudaq_qec_chromobius_test.dem"; |
There was a problem hiding this comment.
I'm generally wary of hardcoded path
| @@ -0,0 +1,8 @@ | |||
| # Reference case from quantumlib/chromobius: | |||
There was a problem hiding this comment.
Does this mean that this file and the .tsv are both straight from the quantumlib/chromobius repo? If so, I think we need to add a readme or a license file/header. @bmhowe23 What's the general rule of thumb on this?
| std::fill(packed_detection_events.begin(), packed_detection_events.end(), | ||
| uint8_t{0}); | ||
| for (std::size_t i = 0; i < syndrome.size(); ++i) { | ||
| if (syndrome[i] >= 0.5) |
There was a problem hiding this comment.
Here we are doing the comparison directly. I think in the base class header decoder.h, we have helpers that does this. (call cudaq::qec::convert_vec_soft_to_hard(syndrome, hard_buf)). Using the helper will prevent future drift and match the pattern that both the sliding_window and the nv-qldpc decoder use.
I'm aware that there are other instances in our repo currently that still do this manual comparison. I'll make a new issue to track those.
Signed-off-by: Scott Thornton <wsttiger@gmail.com>
| chromobius(const cudaqx::tensor<uint8_t> &H, | ||
| const cudaqx::heterogeneous_map ¶ms) | ||
| : decoder(H), dem(get_dem_text(params)) { | ||
| auto H_shape = H.shape(); |
There was a problem hiding this comment.
Is H actually used anywhere?
| FetchContent_Declare( | ||
| chromobius | ||
| GIT_REPOSITORY https://github.com/quantumlib/chromobius.git | ||
| GIT_TAG efae0325e4a8fc13be981434d38e499aa06b989f # v1.1.1 |
There was a problem hiding this comment.
Please make sure to file the OSRB paperwork for this.
## Description Adds unified decoder initialization from either a parity-check matrix or raw Stim detector error model text. This supports both existing PCM-based decoders and DEM-native decoders needed by #546. PCM-based decoders can parse DEM text into `H`, `O`, and `error_rate_vec` defaults, while DEM-native decoders can consume the raw DEM text without going through a lossy matrix conversion. ### API (`cudaq/qec/decoder.h`) - Adds `decoder_init = std::variant<sparse_binary_matrix, std::string>` as the decoder registry construction input. - Keeps existing PCM construction paths: - `get_decoder(name, H, options)` - `decoder::get(name, H, options)` - Adds DEM string construction through the same entry points: - `get_decoder(name, dem_text, options)` - `decoder::get(name, dem_text, options)` - Adds `dem_from_stim_text(dem_text)` to parse Stim DEM text into `detector_error_model`. - Adds helper routing for PCM-based decoders so DEM-derived `O` and `error_rate_vec` are supplied as defaults when not explicitly provided by the user. The DEM-to-detector_error_model parser is lossy: it extracts detector flips, observable flips, and per-error probabilities, but drops detector coordinates and separator-encoded correlation structure. DEM-native decoders should consume the raw string alternative in decoder_init. Python: `cudaq_qec.get_decoder(...)` now accepts Stim DEM strings. Python-registered decoders currently receive parsed `H` plus DEM-derived `O` / `error_rate_vec` defaults, not raw DEM text. ### Dependency / build QEC now provides its own Stim dependency via `FetchContent` when `libstim` is not already available, so standalone QEC builds do not depend on parent CUDA-Q interim build artifacts. ### Tests C++ gtests and Python tests cover: - DEM string construction through `get_decoder(...)` - PCM construction still working - user-provided options overriding DEM-derived defaults - DEM parse edge cases - DEMs without observables - `stim::DemTarget` category assumptions ### Out of scope / follow-ups Chromobius plugin integration itself; detector-coordinate storage on `detector_error_model`; optional PyMatching-specific improvements; user-facing Sphinx/RST docs. ## Runtime / performance impact N/A ## Self-review checklist Please confirm each item before requesting review. Check `[x]` or strike through and explain. ### Before requesting review - [x] I reviewed my own full diff in GitHub or my editor. - [x] PR is in Draft if it is not yet ready for review. - [x] Temporary / debugging changes have been removed. - [x] Local test logs reviewed; no unexplained warnings or errors. - [x] CI logs reviewed; no unexplained warnings or errors. - [x] Full CI has been run. ### Scope and size - [x] PR is under ~1000 lines, or an exception is justified in the description. - [x] Refactoring-only changes are isolated in their own PR(s). - [x] No existing tests were disabled or modified just to make this PR pass (if so, an issue has been raised). ### Tests - [x] New functionality has new tests. - [x] Tests fail if the new functionality is broken (including crashes), not just when it is missing. - [x] Negative tests added where exceptions are expected. - [x] Truth data added where simple `EXPECT_*` / `assert` checks are insufficient for algorithmic correctness. - [x] CI runtime impact considered; team notified if significant. ### Documentation - [x] Public-facing APIs have Doxygen docs. - [x] User-visible behavior changes have public docs, or a follow-up is tracked. - [x] User-facing docs for new features are in a **separate PR** held until release (the docs site publishes immediately on merge to the default branch, so feature docs must not land before the feature ships). ### Code style - [x] Naming follows the existing convention (`snake_case` vs `camelCase`) for the area being modified. ### Dependencies - [x] No new third-party dependencies, **or** the team has been notified and OSRB tickets filed. --------- Signed-off-by: vedika-saravanan <vsaravanan@nvidia.com>
Summary
Adds a CUDA-QX QEC decoder plugin for Chromobius and wires it into the existing decoder factory/plugin flow.
The wrapper accepts a Stim detector error model through decoder params, compiles a Chromobius decoder from that DEM, packs detector syndromes into Chromobius’ expected bit-packed format, and returns predicted observable flips directly.
Changes
chromobiusdecoder plugin underlibs/qec/lib/decoders/plugins/chromobiusdem,dem_str, ordem_pathCUDAQ_EXT_PT_REGISTER_TYPETesting
ninja -j16ninja installninja test_chromobius_correctnessctest -R Chromobius --output-on-failurectest -R ChromobiusCorrectness --output-on-failurePYTHONPATH=/usr/local/cudaq:/scratch/cudaqx-realtime/build/python pytest -q ../libs/qec/python/tests/test_chromobius.py