Skip to content

Commit 1c040d1

Browse files
committed
Merge branch 'main' into realtime_docs
2 parents 92ebdf3 + 69e651a commit 1c040d1

File tree

9 files changed

+367
-33
lines changed

9 files changed

+367
-33
lines changed

docs/sphinx/api/qec/cpp_api.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ NVIDIA QLDPC Decoder
5151

5252
.. include:: nv_qldpc_decoder_api.rst
5353

54+
Sliding Window Decoder
55+
----------------------
56+
57+
.. include:: sliding_window_api.rst
58+
5459
Real-Time Decoding
5560
==================
5661

docs/sphinx/api/qec/nv_qldpc_decoder_api.rst

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,16 +100,53 @@
100100
- `clip_value` (float): Value to clip the BP messages to. Should be a
101101
non-negative value (defaults to 0.0, which disables clipping). Introduced in
102102
0.4.0.
103-
- `bp_method` (int): The BP method to use. 0 for sum-product, 1 for min-sum.
104-
Defaults to 0. Introduced in 0.4.0.
103+
- `bp_method` (int): Core BP algorithm to use (defaults to 0). Introduced in 0.4.0,
104+
expanded in 0.5.0:
105+
106+
- 0: sum-product
107+
- 1: min-sum (introduced in 0.4.0)
108+
- 2: min-sum+mem (uniform memory strength, introduced in 0.5.0)
109+
- 3: min-sum+dmem (disordered memory strength, introduced in 0.5.0)
110+
- `composition` (int): Iteration strategy (defaults to 0). Introduced in 0.5.0:
111+
112+
- 0: Standard (single run)
113+
- 1: Sequential relay (multiple gamma legs). Requires: `bp_method=3`, `srelay_config`
105114
- `scale_factor` (float): The scale factor to use for min-sum. Defaults to 1.0.
106115
When set to 0.0, the scale factor is dynamically computed based on the
107116
number of iterations. Introduced in 0.4.0.
117+
- `proc_float` (string): The processing float type to use. Defaults to
118+
"fp64". Valid values are "fp32" and "fp64". Introduced in 0.5.0.
119+
- `gamma0` (float): Memory strength parameter. Required for `bp_method=2`, and for
120+
`composition=1` (sequential relay). Introduced in 0.5.0.
121+
- `gamma_dist` (vector<float>): Gamma distribution interval [min, max] for disordered
122+
memory strength. Required for `bp_method=3` if `explicit_gammas` not provided.
123+
Introduced in 0.5.0.
124+
- `explicit_gammas` (vector<vector<float>>): Explicit gamma values for each variable node.
125+
For `bp_method=3` with `composition=0`, provide a 2D vector where each row has
126+
`block_size` columns. For `composition=1` (Sequential relay), provide `num_sets` rows
127+
(one per relay leg). Overrides `gamma_dist` if provided. Introduced in 0.5.0.
128+
- `srelay_config` (heterogeneous_map): Sequential relay configuration (required for
129+
`composition=1`). Contains the following parameters. Introduced in 0.5.0:
130+
131+
- `pre_iter` (int): Number of pre-iterations to run before relay legs
132+
- `num_sets` (int): Number of relay sets (legs) to run
133+
- `stopping_criterion` (string): When to stop relay legs:
134+
135+
- "All": Run all legs
136+
- "FirstConv": Stop relay after first convergence
137+
- "NConv": Stop after N convergences (requires `stop_nconv` parameter)
138+
- `stop_nconv` (int): Number of convergences to wait for before stopping
139+
(required only when `stopping_criterion="NConv"`)
140+
- `bp_seed` (int): Seed for random number generation used in `bp_method=3` (disordered
141+
memory BP). Optional parameter, defaults to 42 if not provided. Introduced in 0.5.0.
108142
- `opt_results` (heterogeneous_map): Optional results to return. This field can be
109143
left empty if no additional results are desired. Choices are:
110-
- `bp_llr_history` (int): Return the last `bp_llr_history` iterations
111-
of the BP LLR history. Minimum value is 0 and maximum value is
112-
max_iterations. The actual number of returned iterations might be fewer
113-
than `bp_llr_history` if BP converges before the requested number of
114-
iterations. Introduced in 0.4.0.
144+
145+
- `bp_llr_history` (int): Return the last `bp_llr_history` iterations
146+
of the BP LLR history. Minimum value is 0 and maximum value is
147+
max_iterations. The actual number of returned iterations might be fewer
148+
than `bp_llr_history` if BP converges before the requested number of
149+
iterations. Introduced in 0.4.0. Note: Not supported for `composition=1`.
150+
- `num_iter` (bool): If true, return the number of BP iterations run.
151+
Introduced in 0.5.0.
115152

docs/sphinx/api/qec/python_api.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ NVIDIA QLDPC Decoder
3939

4040
.. include:: nv_qldpc_decoder_api.rst
4141

42+
Sliding Window Decoder
43+
----------------------
44+
45+
.. include:: sliding_window_api.rst
46+
4247
.. _tensor_network_decoder_api_python:
4348

4449
Tensor Network Decoder

docs/sphinx/components/qec/introduction.rst

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,13 +672,29 @@ The Quantum Low-Density Parity-Check (QLDPC) decoder leverages GPU-accelerated b
672672
Since belief propagation is an iterative method which may not converge, decoding can be improved with a second-stage post-processing step. The `nv-qldpc-decoder`
673673
API provides various post-processing options, which can be selected through its parameters.
674674

675+
**Belief Propagation Methods:**
676+
677+
The decoder supports multiple BP algorithms (configured via ``bp_method``):
678+
679+
* **Sum-Product BP** (``bp_method=0``, default): Classic belief propagation algorithm that computes exact probabilities.
680+
* **Min-Sum BP** (``bp_method=1``): Approximation to sum-product that uses min operations instead of sum. Optionally accepts ``scale_factor``.
681+
* **Memory-based BP** (``bp_method=2``): Min-sum with uniform memory strength across all variable nodes. **Requires:** ``gamma0``.
682+
* **Disordered Memory BP** (``bp_method=3``): Min-sum with per-variable memory strengths. **Requires:** ``gamma_dist`` [min, max] OR ``explicit_gammas`` (2D vector).
683+
684+
**Sequential Relay Decoding:**
685+
686+
Starting with version 0.5.0, the decoder supports Sequential Relay BP (configured via ``composition=1``), which combines disordered memory BP
687+
with multiple "relay legs" - sequential runs with different gamma configurations. **Requires:** ``bp_method=3``, ``gamma0``, ``srelay_config``, and either ``gamma_dist`` OR ``explicit_gammas``.
688+
675689
The QLDPC decoder `nv-qldpc-decoder` requires a CUDA-Q compatible GPU. See the list below for dependencies and compatibility:
676690
https://nvidia.github.io/cuda-quantum/latest/using/install/local_installation.html#dependencies-and-compatibility
677691

678692
The decoder is based on the following references:
679693

680694
* https://arxiv.org/pdf/2005.07016
681-
* https://github.com/quantumgizmos/ldpc
695+
* https://github.com/quantumgizmos/ldpc
696+
* https://arxiv.org/pdf/2506.01779
697+
* https://github.com/trmue/relay
682698

683699

684700
Usage:

docs/sphinx/components/solvers/introduction.rst

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,6 @@ The :code:`molecule_options` structure provides extensive configuration for mole
7575
+---------------------+---------------+------------------+------------------------------------------+
7676
| integrals_casscf | bool | false | Use CASSCF orbitals for integrals |
7777
+---------------------+---------------+------------------+------------------------------------------+
78-
| potfile | optional | nullopt | Path to external potential file |
79-
| | <string> | | |
80-
+---------------------+---------------+------------------+------------------------------------------+
8178
| verbose | bool | false | Enable detailed output logging |
8279
+---------------------+---------------+------------------+------------------------------------------+
8380

docs/sphinx/examples/qec/python/nv-qldpc-decoder.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,154 @@ def run_decoder(filename, num_shots, run_as_batched):
199199
)
200200

201201

202+
def demonstrate_bp_methods():
203+
"""
204+
Demonstrate different BP methods available in nv-qldpc-decoder.
205+
Shows configurations for: sum-product, min-sum, memory BP,
206+
disordered memory BP, and sequential relay BP.
207+
"""
208+
# Simple 3x7 parity check matrix for demonstration
209+
H_list = [[1, 0, 0, 1, 0, 1, 1], [0, 1, 0, 1, 1, 0, 1],
210+
[0, 0, 1, 0, 1, 1, 1]]
211+
H = np.array(H_list, dtype=np.uint8)
212+
213+
print("=" * 60)
214+
print("Demonstrating BP Methods in nv-qldpc-decoder")
215+
print("=" * 60)
216+
217+
# Method 0: Sum-Product BP (default)
218+
print("\n1. Sum-Product BP (bp_method=0, default):")
219+
try:
220+
decoder_sp = qec.get_decoder("nv-qldpc-decoder",
221+
H,
222+
bp_method=0,
223+
max_iterations=30)
224+
except Exception as e:
225+
print(
226+
'The nv-qldpc-decoder is not available with your current CUDA-Q ' +
227+
'QEC installation.')
228+
exit(0)
229+
print(" Created decoder with sum-product BP")
230+
231+
# Method 1: Min-Sum BP
232+
print("\n2. Min-Sum BP (bp_method=1):")
233+
decoder_ms = qec.get_decoder("nv-qldpc-decoder",
234+
H,
235+
bp_method=1,
236+
max_iterations=30,
237+
scale_factor=1.0)
238+
print(" Created decoder with min-sum BP")
239+
240+
# Method 2: Min-Sum with uniform Memory (Mem-BP)
241+
print("\n3. Mem-BP (bp_method=2, uniform memory strength):")
242+
decoder_mem = qec.get_decoder("nv-qldpc-decoder",
243+
H,
244+
bp_method=2,
245+
max_iterations=30,
246+
gamma0=0.5)
247+
print(" Created decoder with Mem-BP (gamma0=0.5)")
248+
249+
# Method 3: Min-Sum with Disordered Memory (DMem-BP)
250+
print("\n4. DMem-BP (bp_method=3, disordered memory strength):")
251+
# Option A: Using gamma_dist (random gammas in range)
252+
decoder_dmem = qec.get_decoder("nv-qldpc-decoder",
253+
H,
254+
bp_method=3,
255+
max_iterations=30,
256+
gamma_dist=[0.1, 0.5],
257+
bp_seed=42)
258+
print(" Created decoder with DMem-BP (gamma_dist=[0.1, 0.5])")
259+
260+
# Option B: Using explicit_gammas (specify exact gamma for each variable)
261+
block_size = H.shape[1]
262+
explicit_gammas = [[0.1 + 0.05 * i for i in range(block_size)]]
263+
decoder_dmem_explicit = qec.get_decoder("nv-qldpc-decoder",
264+
H,
265+
bp_method=3,
266+
max_iterations=30,
267+
explicit_gammas=explicit_gammas)
268+
print(" Created decoder with DMem-BP (explicit gammas)")
269+
270+
# Method 4: Sequential Relay BP (composition=1)
271+
print("\n5. Sequential Relay BP (composition=1):")
272+
print(" Requires bp_method=3 and srelay_config")
273+
274+
# Configure relay parameters
275+
srelay_config = {
276+
'pre_iter': 5, # Run 5 iterations with gamma0 before relay legs
277+
'num_sets': 3, # Use 3 relay legs
278+
'stopping_criterion': 'FirstConv' # Stop after first convergence
279+
}
280+
281+
# Option A: Using gamma_dist for relay legs
282+
decoder_relay = qec.get_decoder("nv-qldpc-decoder",
283+
H,
284+
bp_method=3,
285+
composition=1,
286+
max_iterations=50,
287+
gamma0=0.3,
288+
gamma_dist=[0.1, 0.5],
289+
srelay_config=srelay_config,
290+
bp_seed=42)
291+
print(" Created decoder with Relay-BP (gamma_dist, FirstConv stopping)")
292+
293+
# Option B: Using explicit gammas for each relay leg
294+
num_relay_legs = 3
295+
explicit_relay_gammas = [
296+
[0.1 + 0.02 * i for i in range(block_size)], # First relay leg
297+
[0.2 + 0.03 * i for i in range(block_size)], # Second relay leg
298+
[0.3 + 0.04 * i for i in range(block_size)] # Third relay leg
299+
]
300+
301+
srelay_config_all = {
302+
'pre_iter': 10,
303+
'num_sets': 3,
304+
'stopping_criterion': 'All' # Run all relay legs
305+
}
306+
307+
decoder_relay_explicit = qec.get_decoder(
308+
"nv-qldpc-decoder",
309+
H,
310+
bp_method=3,
311+
composition=1,
312+
max_iterations=50,
313+
gamma0=0.3,
314+
explicit_gammas=explicit_relay_gammas,
315+
srelay_config=srelay_config_all)
316+
print(" Created decoder with Relay-BP (explicit gammas, All legs)")
317+
318+
# Option C: NConv stopping criterion
319+
srelay_config_nconv = {
320+
'pre_iter': 5,
321+
'num_sets': 10,
322+
'stopping_criterion': 'NConv',
323+
'stop_nconv': 3 # Stop after 3 convergences
324+
}
325+
326+
decoder_relay_nconv = qec.get_decoder("nv-qldpc-decoder",
327+
H,
328+
bp_method=3,
329+
composition=1,
330+
max_iterations=50,
331+
gamma0=0.3,
332+
gamma_dist=[0.1, 0.6],
333+
srelay_config=srelay_config_nconv,
334+
bp_seed=42)
335+
print(" Created decoder with Relay-BP (NConv stopping after 3)")
336+
337+
print("\n" + "=" * 60)
338+
print("All decoder configurations created successfully!")
339+
print("=" * 60)
340+
341+
202342
if __name__ == "__main__":
343+
# Demonstrate different BP methods (introduced in v0.5.0)
344+
print("\n### PART 1: BP Methods Demonstration ###\n")
345+
demonstrate_bp_methods()
346+
347+
# Full decoding with test data
348+
print("\n\n### PART 2: Full Decoding Example with Test Data ###\n")
349+
203350
# See other test data options in https://github.com/NVIDIA/cudaqx/releases/tag/0.2.0
204351
filename = 'osd_1008_8785_0.001.json'
205352
bz2filename = filename + '.bz2'

docs/sphinx/examples/solvers/python/generate_molecular_hamiltonians.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
# [Begin Documentation]
1010
import cudaq_solvers as solvers
1111

12-
# Generate active space Hamiltonian using HF molecular orbitals
12+
# Generate active space Hamiltonian using RHF molecular orbitals
1313

1414
geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
1515
molecule = solvers.create_molecule(geometry,
@@ -20,7 +20,24 @@
2020
norb_cas=3,
2121
verbose=True)
2222

23-
print('N2 HF Hamiltonian')
23+
print('N2 RHF Hamiltonian')
24+
print('Energies : ', molecule.energies)
25+
print('No. of orbitals: ', molecule.n_orbitals)
26+
print('No. of electrons: ', molecule.n_electrons)
27+
28+
# Generate active space Hamiltonian using UHF molecular orbitals
29+
30+
geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
31+
molecule = solvers.create_molecule(geometry,
32+
'sto-3g',
33+
0,
34+
0,
35+
nele_cas=2,
36+
norb_cas=3,
37+
UR=True,
38+
verbose=True)
39+
40+
print('N2 UHF Hamiltonian')
2441
print('Energies : ', molecule.energies)
2542
print('No. of orbitals: ', molecule.n_orbitals)
2643
print('No. of electrons: ', molecule.n_electrons)
@@ -83,3 +100,36 @@
83100
print('Energies: ', molecule.energies)
84101
print('No. of orbitals: ', molecule.n_orbitals)
85102
print('No. of electrons: ', molecule.n_electrons)
103+
104+
# For open-shell systems: Generate active space Hamiltonian using ROHF molecular orbitals
105+
geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
106+
molecule = solvers.create_molecule(geometry,
107+
'sto-3g',
108+
1,
109+
1,
110+
nele_cas=3,
111+
norb_cas=3,
112+
ccsd=True,
113+
verbose=True)
114+
115+
print('N2+ ROHF Hamiltonian')
116+
print('Energies : ', molecule.energies)
117+
print('No. of orbitals: ', molecule.n_orbitals)
118+
print('No. of electrons: ', molecule.n_electrons)
119+
120+
# For open-shell systems: Generate active space Hamiltonian using UHF molecular orbitals
121+
geometry = [('N', (0.0, 0.0, 0.5600)), ('N', (0.0, 0.0, -0.5600))]
122+
molecule = solvers.create_molecule(geometry,
123+
'sto-3g',
124+
1,
125+
1,
126+
nele_cas=3,
127+
norb_cas=3,
128+
ccsd=True,
129+
UR=True,
130+
verbose=True)
131+
132+
print('N2+ UHF Hamiltonian')
133+
print('Energies : ', molecule.energies)
134+
print('No. of orbitals: ', molecule.n_orbitals)
135+
print('No. of electrons: ', molecule.n_electrons)

docs/sphinx/examples_rst/qec/decoders.rst

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,33 @@ CUDA-Q QEC library. The library follows the CUDA-Q decoder Python and C++ interf
7575
:cpp:class:`cudaq::qec::decoder` for C++), but as documented in the API sections
7676
(:ref:`nv_qldpc_decoder_api_python` for Python and
7777
:ref:`nv_qldpc_decoder_api_cpp` for C++), there are many configuration options
78-
that can be passed to the constructor. The following example shows how to
79-
exercise the decoder using non-trivial pre-generated test data. The test data
80-
was generated using scripts originating from the GitHub repo for
81-
`BivariateBicycleCodes
82-
<https://github.com/sbravyi/BivariateBicycleCodes>`_ [#f1]_; it includes parity
83-
check matrices (PCMs) and test syndromes to exercise a decoder.
78+
that can be passed to the constructor.
79+
80+
Belief Propagation Methods
81+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
82+
83+
The ``nv-qldpc-decoder`` supports multiple belief propagation (BP) algorithms, each with different trade-offs
84+
between accuracy, convergence, and speed:
85+
86+
* **Sum-Product BP** (``bp_method=0``): The standard BP algorithm. Good baseline performance.
87+
* **Min-Sum BP** (``bp_method=1``): Faster approximation to sum-product. Can be tuned with ``scale_factor``.
88+
* **Memory-based BP** (``bp_method=2``): Adds uniform memory (``gamma0``) to help escape local minima. Useful when standard BP fails to converge.
89+
* **Disordered Memory BP** (``bp_method=3``): Uses per-variable memory strengths for better adaptability to code structure.
90+
* **Sequential Relay BP** (``composition=1``): Advanced method that runs multiple "relay legs" with different gamma configurations. See examples below for configuration.
91+
92+
Usage Example
93+
~~~~~~~~~~~~~
94+
95+
The following example shows how to exercise the decoder using non-trivial pre-generated test data.
96+
The test data was generated using scripts originating from the GitHub repo for
97+
`BivariateBicycleCodes <https://github.com/sbravyi/BivariateBicycleCodes>`_ [#f1]_;
98+
it includes parity check matrices (PCMs) and test syndromes to exercise a decoder.
99+
100+
The example demonstrates:
101+
102+
1. **Basic decoder configuration** with OSD post-processing
103+
2. **All BP methods** including Sequential Relay BP
104+
3. **Batched decoding** for improved performance
84105

85106
.. literalinclude:: ../../examples/qec/python/nv-qldpc-decoder.py
86107
:language: python

0 commit comments

Comments
 (0)