Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions docs/sphinx/api/qec/cpp_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,70 @@ Detector Error Model
.. doxygenfunction:: cudaq::qec::decoder_context_from_memory_circuit(const code &, operation, std::size_t, cudaq::noise_model &, bool)
.. doxygenfunction:: cudaq::qec::dem_from_stim_text(const std::string &, bool)

.. _dyn_dem_cpp_api:

Dynamic DEM Construction
========================

Build a code-capacity or phenomenological DEM from CSS generator matrices
(no Stim circuit required), or compose per-round DEM chunks that can be
stitched and closed into a flat :cpp:struct:`cudaq::qec::detector_error_model`.
See :doc:`/examples_rst/qec/dyn_dem` for a walkthrough.

CSS matrices and noise
----------------------

.. doxygenstruct:: cudaq::qec::css_code_matrices
:members:

.. doxygenstruct:: cudaq::qec::css_noise_params
:members:

.. doxygenfunction:: cudaq::qec::css_matrices_from_code
.. doxygenfunction:: cudaq::qec::dem_from_css_matrices(const css_code_matrices &, const css_noise_params &, std::size_t)
.. doxygenfunction:: cudaq::qec::dem_from_css_matrices(const code &, const css_noise_params &, std::size_t)

Extended DEM chunks
-------------------

.. doxygenstruct:: cudaq::qec::extended_dem
:members:

.. doxygenfunction:: cudaq::qec::extended_dem_from_css_matrices

.. doxygenstruct:: cudaq::qec::dem_chunk_spec
:members:

.. doxygenstruct:: cudaq::qec::dem_chunks_spec
:members:

.. doxygenfunction:: cudaq::qec::dem_chunk_from_spec
.. doxygenfunction:: cudaq::qec::dem_chunks_from_spec

Stitch, close, and merge
------------------------

.. doxygenenum:: cudaq::qec::prior_combine_mode

.. doxygenfunction:: cudaq::qec::dem_stitch
.. doxygenfunction:: cudaq::qec::dem_stitch_all
.. doxygenfunction:: cudaq::qec::dem_stitch_merged
.. doxygenfunction:: cudaq::qec::dem_close
.. doxygenfunction:: cudaq::qec::dem_close_all
.. doxygenfunction:: cudaq::qec::dem_merge_duplicate_columns
.. doxygenfunction:: cudaq::qec::are_dem_columns_unique
.. doxygenfunction:: cudaq::qec::assert_dem_columns_unique

Streaming decoder maps
----------------------

.. doxygenfunction:: cudaq::qec::dem_chunk_rounds
.. doxygenfunction:: cudaq::qec::dem_chunks_to_rounds
.. doxygenfunction:: cudaq::qec::dem_chunks_to_detector_round
.. doxygenfunction:: cudaq::qec::dem_chunks_to_d_sparse
.. doxygenfunction:: cudaq::qec::dem_chunks_to_o_sparse
.. doxygenfunction:: cudaq::qec::dem_chunks_to_pcm

.. _dem_sampling_cpp_api:

Detector Error Model (DEM) Sampling
Expand Down
1 change: 1 addition & 0 deletions docs/sphinx/api/qec/cpp_realtime_decoding_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ The configuration API enables setting up decoders before circuit execution. Deco
.. doxygenfunction:: cudaq::qec::decoding::config::configure_decoders_from_file
.. doxygenfunction:: cudaq::qec::decoding::config::configure_decoders_from_str
.. doxygenfunction:: cudaq::qec::decoding::config::finalize_decoders
.. doxygenfunction:: cudaq::qec::decoding::config::expand_dem_chunks

Helper Functions
----------------
Expand Down
63 changes: 63 additions & 0 deletions docs/sphinx/api/qec/python_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,69 @@ Detector Error Model
.. autofunction:: cudaq_qec.dem_from_stim_text
.. autofunction:: cudaq_qec.d_sparse

.. _dyn_dem_python_api:

Dynamic DEM Construction
========================

Build a code-capacity or phenomenological DEM from CSS generator matrices
(no Stim circuit required), or compose per-round DEM *chunks* that can be
stitched and closed into a flat :class:`~cudaq_qec.DetectorErrorModel`.
See :doc:`/examples_rst/qec/dyn_dem` for a walkthrough.

CSS matrices and noise
----------------------

.. autoclass:: cudaq_qec.CssCodes
:members:

.. autoclass:: cudaq_qec.CssNoise
:members:

.. autofunction:: cudaq_qec.css_matrices_from_code
.. autofunction:: cudaq_qec.dem_from_css_matrices

Extended DEM chunks
-------------------

.. autoclass:: cudaq_qec.ExtendedDem
:members:

.. autofunction:: cudaq_qec.extended_dem_from_css_matrices

.. autoclass:: cudaq_qec.DemChunkSpec
:members:

.. autoclass:: cudaq_qec.DemChunksSpec
:members:

.. autofunction:: cudaq_qec.dem_chunk_from_spec
.. autofunction:: cudaq_qec.dem_chunks_from_spec

Stitch, close, and merge
------------------------

.. autoclass:: cudaq_qec.PriorCombineMode
:members:

.. autofunction:: cudaq_qec.dem_stitch
.. autofunction:: cudaq_qec.dem_stitch_all
.. autofunction:: cudaq_qec.dem_stitch_merged
.. autofunction:: cudaq_qec.dem_close
.. autofunction:: cudaq_qec.dem_close_all
.. autofunction:: cudaq_qec.dem_merge_duplicate_columns
.. autofunction:: cudaq_qec.are_dem_columns_unique
.. autofunction:: cudaq_qec.assert_dem_columns_unique

Streaming decoder maps
----------------------

.. autofunction:: cudaq_qec.dem_chunk_rounds
.. autofunction:: cudaq_qec.dem_chunks_to_rounds
.. autofunction:: cudaq_qec.dem_chunks_to_detector_round
.. autofunction:: cudaq_qec.dem_chunks_to_d_sparse
.. autofunction:: cudaq_qec.dem_chunks_to_o_sparse

Decoder Interfaces
==================

Expand Down
40 changes: 40 additions & 0 deletions docs/sphinx/components/qec/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,46 @@ backend selection details, see the
:doc:`DEM Sampling example </examples_rst/qec/dem_sampling>`.


Dynamic DEM Construction
^^^^^^^^^^^^^^^^^^^^^^^^

When a Stim circuit is not available — or when the round count must stay
flexible until decoder construction — build DEMs from CSS generator matrices
and compose them as per-round chunks:

* ``dem_from_css_matrices`` — :math:`T`-round code-capacity / phenomenological
DEM from ``CssCodes`` / ``css_code_matrices`` and ``CssNoise`` /
``css_noise_params``.
* ``extended_dem_from_css_matrices``, ``dem_stitch`` / ``dem_close_all`` —
one-round chunks that stitch and close to the same flat DEM.
* YAML ``dem_chunks`` + ``num_rounds`` — declarative init / bulk / final
phases for real-time decoder configs; expanded by ``expand_dem_chunks``.

.. tab:: Python

.. literalinclude:: ../../examples/qec/python/dyn_dem.py
:language: python
:start-after: [Begin Documentation]
:end-before: [End Documentation]

.. tab:: C++

.. literalinclude:: ../../examples/qec/cpp/dyn_dem.cpp
:language: cpp
:start-after: [Begin Documentation]
:end-before: [End Documentation]

Compile and run with

.. code-block:: bash

nvq++ -lcudaq-qec -lcudaq-qec-decoders dyn_dem.cpp
./a.out

See the :doc:`Dynamic DEM Construction example </examples_rst/qec/dyn_dem>`
for phase specs, YAML ``dem_chunks``, merge semantics, and closing rules.


Pre-built QEC Decoders
----------------------

Expand Down
60 changes: 60 additions & 0 deletions docs/sphinx/examples/qec/cpp/dyn_dem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*******************************************************************************
* Copyright (c) 2026 NVIDIA Corporation & Affiliates. *
* All rights reserved. *
* *
* This source code and the accompanying materials are made available under *
* the terms of the Apache License 2.0 which accompanies this distribution. *
******************************************************************************/
// [Begin Documentation]
// Dynamic DEM construction from CSS matrices and composable DEM chunks.
//
// Compile and run with:
// nvq++ -lcudaq-qec -lcudaq-qec-decoders dyn_dem.cpp
// ./a.out

#include "cudaq/qec/code_matrices.h"
#include "cudaq/qec/dem_construction.h"
#include "cudaq/qec/extended_dem.h"

#include <iostream>
#include <vector>

int main() {
// d=3 repetition code (Z-basis): H_Z = [[1,1,0],[0,1,1]], L_Z = [[1,0,0]].
cudaq::qec::css_code_matrices code;
code.hz = cudaq::qec::sparse_binary_matrix::from_nested_csc(
2, 3, {{0}, {0, 1}, {1}});
code.lz =
cudaq::qec::sparse_binary_matrix::from_nested_csc(1, 3, {{0}, {}, {}});

cudaq::qec::css_noise_params noise;
noise.px = 0.01;
noise.pm = 0.005;

constexpr std::size_t num_rounds = 5;

// Monolithic T-round DEM (code-capacity + measurement errors).
auto flat = cudaq::qec::dem_from_css_matrices(code, noise, num_rounds);
std::cout << "flat DEM: " << flat.num_detectors() << " detectors, "
<< flat.num_error_mechanisms() << " faults, "
<< flat.num_observables() << " observables\n";

// Same experiment as T one-round chunks closed in one O(T) pass.
auto chunk = cudaq::qec::extended_dem_from_css_matrices(code, noise);
std::vector<cudaq::qec::extended_dem> chunks(num_rounds, chunk);
auto closed = cudaq::qec::dem_close_all(chunks);

if (closed.num_detectors() != flat.num_detectors() ||
closed.num_error_mechanisms() != flat.num_error_mechanisms()) {
std::cerr << "dem_close_all does not match dem_from_css_matrices\n";
return 1;
}
std::cout << "dem_close_all matches dem_from_css_matrices\n";

auto detector_round = cudaq::qec::dem_chunks_to_detector_round(chunks);
auto d_sparse = cudaq::qec::dem_chunks_to_d_sparse(chunks);
std::cout << "detector_round length " << detector_round.size()
<< ", D_sparse rows " << d_sparse.size() << "\n";
return 0;
}
// [End Documentation]
42 changes: 42 additions & 0 deletions docs/sphinx/examples/qec/python/dyn_dem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# ============================================================================ #
# Copyright (c) 2026 NVIDIA Corporation & Affiliates. #
# All rights reserved. #
# #
# This source code and the accompanying materials are made available under #
# the terms of the Apache License 2.0 which accompanies this distribution. #
# ============================================================================ #

# [Begin Documentation]
import cudaq_qec as qec

# Build a T-round DEM from a CSS code and phenomenological noise — no Stim
# circuit required.
code = qec.get_code("repetition", distance=3)
noise = qec.CssNoise()
noise.px = 0.01
noise.pm = 0.005

num_rounds = 5
flat = qec.dem_from_css_matrices(code, noise, num_rounds)
print(f"flat DEM: {flat.num_detectors()} detectors, "
f"{flat.num_error_mechanisms()} faults, "
f"{flat.num_observables()} observables")

# The same experiment as composable one-round chunks. Stitch-and-close (or
# dem_close_all) recovers the flat DEM, which is useful when rounds are
# streamed or when init/bulk/final phases differ.
matrices = qec.css_matrices_from_code(code)
chunk = qec.extended_dem_from_css_matrices(matrices, noise)
chunks = [chunk] * num_rounds
closed = qec.dem_close_all(chunks)

assert closed.num_detectors() == flat.num_detectors()
assert closed.num_error_mechanisms() == flat.num_error_mechanisms()
print("dem_close_all matches dem_from_css_matrices")

# Streaming helpers: detector→round map and D_sparse for realtime configs.
detector_round = qec.dem_chunks_to_detector_round(chunks)
d_sparse = qec.dem_chunks_to_d_sparse(chunks)
print(f"detector_round length {len(detector_round)}, "
f"D_sparse rows {len(d_sparse)}")
# [End Documentation]
Loading
Loading