Skip to content

Dynamic DEM Initial Infrastructure - #759

Merged
tlshannon merged 14 commits into
NVIDIA:mainfrom
tlshannon:dyn_dem
Aug 13, 2026
Merged

Dynamic DEM Initial Infrastructure#759
tlshannon merged 14 commits into
NVIDIA:mainfrom
tlshannon:dyn_dem

Conversation

@tlshannon

@tlshannon tlshannon commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Dynamic DEM construction for streaming decoders

css_code_matrices / css_noise_params (code_matrices.h) — types that encode a CSS code's parity-check and logical-operator matrices plus a depolarizing (optionally phenomenological) noise model as plain sparse-binary structs, decoupled from the code base class.

dem_from_css_matrices() (dem_construction.h) — builds a T-round detector_error_model directly from CSS matrices and noise, no stabilizer circuit or Stim round-trip required. A code-object overload (dem_construction_code.h) wraps the matrix version for callers that already have a code instance.

seam_id / phase_id (extended_dem.h) — lightweight uint32_t identifiers whose value is the FNV1a-32 hash of a name string, computed at compile time. The same string always produces the same ID; no manual numbering required. A runtime name registry (seam_id::register_name / seam_id::name()) provides human-readable error messages. Standard memory-experiment names:

seam_name::prev_round   // incoming syndrome boundary
seam_name::next_round   // outgoing syndrome boundary
phase_name::dem_init    // string "init"
phase_name::dem_bulk    // string "bulk"
phase_name::dem_final   // string "final"

extended_dem (extended_dem.h) — a single H matrix holding all detector rows, plus a flat list of named seam descriptors that identify which row bands participate in stitching. Interior rows are the complement. O (observables) is separate.

struct extended_dem {
  sparse_binary_matrix H;           // seam bands + interior rows
  sparse_binary_matrix O;           // observable-flip rows
  std::vector<double> error_rates;
  std::vector<seam> seams;          // {id, row_begin, row_end}
  std::vector<uint64_t> tags;
};

Supports an explicit stitching algebra:

  • extended_dem_from_css_matrices() — build a one-round chunk.
  • dem_stitch(a, b, from_seam, to_seam) / dem_stitch_all(chunks) — left-fold chunk composition, contracting named seam row bands.
  • dem_merge_duplicate_columns() — collapse fault columns with identical support using either exact XOR-probability or linear-sum combination.
  • dem_close(dem, to_seam) / dem_close_all(chunks) — convert a stitched chunk to a flat detector_error_model in O(T) time.
  • dem_chunks_spec / dem_chunk_spec — declarative named phase specs (YAML-serialisable); num_rounds is optional and absent for streaming.
  • Streaming helpers: dem_chunks_to_pcm(), dem_chunks_to_o_sparse(), dem_chunks_to_d_sparse(), dem_chunks_to_detector_round() — produce the exact inputs decoder::set_O_sparse() / set_D_sparse() expect, so no decoder plugin needs to know about extended_dem internals.

decoder_config additions (realtime/decoding_config.h) — the flat-form fields (H_sparse, O_sparse, D_sparse, block_size, syndrome_size) are complemented by an optional dem_chunks field. num_rounds moves inside dem_chunks and is optional (omit for streaming). expand_dem_chunks() rewrites a chunk-form config into the equivalent flat form at decoder construction time, so the rest of the realtime pipeline is unchanged.


New YAML format

Decoders may now be configured with a compact phase description instead of pre-expanded flat matrices. The round count is optional — omit it for streaming decoders where the total is not known at configuration time.

dem_chunks:
  seam: {from: next_round, to: prev_round}
  connections:
    - {from: init, to: bulk}
    - {from: bulk, to: bulk}     # self-loop → repeating phase
    - {from: bulk, to: final}
  num_rounds: 5                  # omit for streaming
  phases:
    - name: init
      spec:
        num_faults: 9
        H_sparse: [0, 1, 5, -1, 1, 2, 6, -1, 2, 3, 7, -1, 3, 4, 8, -1]
        O_sparse: [0, -1]
        error_rates: [0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02]
    - name: bulk
      spec:
        num_faults: 9
        H_sparse: [0, 1, 5, -1, 1, 2, 6, -1, 2, 3, 7, -1, 3, 4, 8, -1]
        O_sparse: [0, -1]
        error_rates: [0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02]
    - name: final
      spec:
        num_faults: 5
        H_sparse: [0, 1, -1, 1, 2, -1, 2, 3, -1, 3, 4, -1]
        O_sparse: [0, -1]
        error_rates: [0.02, 0.02, 0.02, 0.02, 0.02]

The connections list encodes the phase graph. A self-loop (from: bulk, to: bulk) identifies the repeating phase; num_rounds controls how many copies are inserted. H_sparse at chunk level is the memory-experiment shorthand (all seams share the same rows); a seam_specs list gives per-seam rows for non-memory circuits.

expand_dem_chunks() is called during finalize_decoders() and rewrites the chunk form into flat fields in-place; all downstream decoder construction sees the familiar flat representation. A config that already carries a nonempty H_sparse is left untouched.


Future PR: decoder plugin updates

This PR does not modify any decoder plugin. A follow-up PR will wire dem_chunks awareness directly into individual decoders where it adds value.

Lines of code

This PR exceeds 1000 lines due new functionality and its test suite. Tests are roughly half the line count.

Runtime / performance impact

N/A

Self-review checklist

Before requesting review

  • I reviewed my own full diff in GitHub or my editor.
  • PR is in Draft if it is not yet ready for review.
  • Temporary / debugging changes have been removed.
  • Local test logs reviewed; no unexplained warnings or errors.
  • CI logs reviewed; no unexplained warnings or errors.
  • Full CI has been run.

Scope and size

  • PR is under ~1000 lines, or an exception is justified in the description.
  • Refactoring-only changes are isolated in their own PR(s).
  • No existing tests were disabled or modified just to make this PR pass.

Tests

  • New functionality has new tests.
  • Tests fail if the new functionality is broken, not just when it is missing.
  • Negative tests added where exceptions are expected.
  • Truth data added where simple `EXPECT_*` checks are insufficient.
  • CI runtime impact considered.

Documentation

  • Public-facing APIs have Doxygen docs.
  • User-visible behavior changes have public docs.

Code style

  • Naming follows the existing convention for the area being modified.

Dependencies

  • No new third-party dependencies.

@tlshannon
tlshannon marked this pull request as ready for review August 3, 2026 14:33
@tlshannon
tlshannon force-pushed the dyn_dem branch 2 times, most recently from 3d5a616 to 6cf24cd Compare August 10, 2026 20:48
@tlshannon
tlshannon requested review from bmhowe23, justinlietz and melody-ren and removed request for justinlietz and melody-ren August 11, 2026 15:51

@bmhowe23 bmhowe23 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, Tracy. I think this is looking great. Just a few comments below.

Comment thread libs/qec/include/cudaq/qec/code_matrices.h Outdated
Comment thread libs/qec/lib/CMakeLists.txt
Comment thread libs/qec/lib/extended_dem.cpp Outdated

@bmhowe23 bmhowe23 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, Tracy.

Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
…out of public header

Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
Signed-off-by: Tracy Shannon <tshannon@nvidia.com>
@tlshannon
tlshannon merged commit 67ecce9 into NVIDIA:main Aug 13, 2026
26 checks passed
melody-ren added a commit to melody-ren/cudaqx that referenced this pull request Aug 14, 2026
No conflicts. The nine commits since the last merge touch the realtime path
again -- NVIDIA#769 serves HOST_CALL inline and retires the worker threads, queues,
and CqrTransceiver; NVIDIA#759 adds the dynamic-DEM infrastructure that reshapes
create_realtime_decoder around chunk expansion -- but none of it reaches the
inproc_rpc path this branch removes: no reference to inproc_rpc,
qec_realtime_session, or rpc_producer comes back, and none of the deleted
sources reappear.

NVIDIA#778 moves the CUDA-Q pin to 28f195f4, so verification needs a toolchain
rebuilt at that commit.

Signed-off-by: Melody Ren <melodyr@nvidia.com>
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.

2 participants