Add a surface code example to demonstrate NVQLink#647
Open
melody-ren wants to merge 13 commits into
Open
Conversation
…erop Bring in PR NVIDIA#637's C++ surface-code orientation support (sc_orientation XV/XH/ZV/ZH; orientation-aware role and observable geometry) and its unit tests, so the realtime example can build the surface code at code_rotation XV to match the Ising-trained predecoder. Vendored verbatim; temporary until NVIDIA#637 merges upstream. Python bindings/exports omitted (this branch's consumer is the C++ example). Signed-off-by: Melody Ren <melodyr@nvidia.com>
Add surface_code-4-yaml, a YAML-switchable realtime surface-code decoder example (pymatching / trt+pymatching / nv-qldpc relay-bp over inproc_rpc), and build the code at code_rotation XV for both the stabilizer CNOT schedule and the logical observables. Over inproc_rpc the trt path loads an Ising-trained d7/T7 CNN predecoder ONNX and runs end-to-end; pymatching decodes at 0 LER and the example ctests pass at XV. Signed-off-by: Melody Ren <melodyr@nvidia.com>
Rework the surface_code-4-yaml DEM-generation kernel to emit the detector layout an Ising-trained predecoder expects (prep-basis single-term detectors + paired rounds + data-derived boundary detectors, X-then-Z), so the Ising CNN model decodes cudaqx's live syndromes. The trt+Ising config loads H/O/priors from the Ising bundle (Ising detector order) and a D_sparse that maps the cudaqx live measurement buffer onto Ising's detector rows (cudaqx's m2d with the Z-ancillas permuted to Ising order; X-ancillas and data identity); the final data measurements are enqueued so the boundary detectors close. End-to-end over inproc_rpc, trt + the Ising d7/T7 model decodes at 0/200 residual; pymatching and nv-qldpc keep cudaqx's own DEM (D = m2d). The example is single-volume (decoding one num_rounds-round volume; the sliding-window machinery is removed). --save_syndrome and --load_syndrome record the heterogeneous final data round so replay round-trips exactly. gen_dsparse.py prepares the bundle's D_sparse.txt from a local Ising checkout (--ising-repo); the trt+Ising path needs that external model and bundle and is not exercised in CI. The TensorRT predecoder runs with its internal CUDA graph enabled. Signed-off-by: Melody Ren <melodyr@nvidia.com>
…ance Bind a loaded YAML config to the experiment geometry: the load path validates the detector count and the measurement-buffer span (max(D_sparse)+1) against the run, which together pin distance and num_rounds; it also checks the observable count, and the trt+Ising path reads and enforces the bundle's metadata.txt (basis=Z, code_rotation=XV, distance, n_rounds). --load_syndrome now requires --yaml, and configure_decoders' return status is checked. Drop the num_rounds-multiple-of-distance constraint (single-volume decoding needs only num_rounds >= 1); num_rounds < distance warns rather than errors. Reject even or below-3 distance up front. Validation failures surface as a clean 'Error: ...' with a nonzero exit. Signed-off-by: Melody Ren <melodyr@nvidia.com>
Validate every decoder config in a loaded YAML (one observable each, consistent detector count and measurement-buffer span), supporting num_logical > 1 independent patches. Replay requires a structurally complete capture -- a present CORRECTIONS_START/END footer, one correction per shot, and per-shot round counts and widths matching the geometry -- and exits nonzero on a missing, truncated, or correction-mismatched file. Add native ctests covering the validation and boundary behavior: distance and round guards, geometry-bound YAML loading, X-basis bundle rejection, replay guards, and multi-logical generate+reload. Each negative case asserts both a nonzero exit and the expected diagnostic. Signed-off-by: Melody Ren <melodyr@nvidia.com>
- Neutralize internal-note and "for-Ising" comment framing; fix copyright year. - Rename gen_dsparse.py -> gen_dsparse_from_memory_circuit.py. - trt+Ising path: when the locally-generated predecoder bundle is absent, print the exact generation recipe and exit rather than failing deeper in. - Order the example after surface_code-3 in CMake; drop cross-example comments. Signed-off-by: Melody Ren <melodyr@nvidia.com>
…e-realtime-yaml-ising
Brings in NVIDIA#637 (surface-code orientation XV/XH/ZV/ZH). The stale vendored C++-only copy is replaced by upstream's version, which also adds the Python bindings the vendored copy omitted. Signed-off-by: Melody Ren <melodyr@nvidia.com>
Fold the d5t6 and multilogical generate/reload pairs into single driver runs (the driver already does generate + reload + decode and adds a residual-LER check), and drop the undersized-distance case (same guard and diagnostic as the even-distance case). 18 -> 15 tests, all passing; coverage unchanged. Signed-off-by: Melody Ren <melodyr@nvidia.com>
kvmto
requested changes
Jul 3, 2026
kvmto
left a comment
Collaborator
There was a problem hiding this comment.
Nice example and the negative-test harness is careful. Two blocking questions on what the positive tests can actually detect, plus four smaller inline comments.
Signed-off-by: Melody Ren <melodyr@nvidia.com>
…eplay test, flag/arg guards, dead debug) Signed-off-by: Melody Ren <melodyr@nvidia.com>
eliotheinrich
left a comment
Collaborator
There was a problem hiding this comment.
Looks nice, but it looks like there are a few spots which are hand-rolling sections that we should be able to support using existing components (and since this is a demo, it seems prudent to use our nice features). I could be missing some context, please let me know if that's the case.
Signed-off-by: Melody Ren <melodyr@nvidia.com>
…_*_syndrome Signed-off-by: Melody Ren <melodyr@nvidia.com>
tlshannon
reviewed
Jul 7, 2026
| } | ||
| } | ||
|
|
||
| __qpu__ std::int64_t |
Collaborator
There was a problem hiding this comment.
Should this be uint64_t to match ret below?
tlshannon
reviewed
Jul 7, 2026
| if (numLogical != config.decoders.size()) { | ||
| printf("ERROR: numLogical [%ld] != config.decoders.size() [%ld]\n", | ||
| numLogical, config.decoders.size()); | ||
| exit(1); |
Collaborator
There was a problem hiding this comment.
Do we want to use exit(), or throw exceptions?
melody-ren
added a commit
that referenced
this pull request
Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds a YAML-configurable realtime surface-code example that streams CUDA-QX measurement data.
It supports:
The TensorRT path interoperates with the Ising basis-Z,
XVsurface-code predecoder by aligning the surface-code geometry, measurement order, detector layout, and logical observable convention.Depends on #637 for surface code orientation.
Ising predecoder interoperability
The Ising bundle is an external asset and is not committed. When the TensorRT+Ising path is requested without it, the example prints the exact local-generation recipe and exits.
This PR has no runtime impact.
Justification for > 1k lines PR: the example requires its own
.cppfile, driver script and helper python script. Additionally, it also carries the unmerged content from #637 .