|
| 1 | +.. _python_realtime_decoding_api: |
| 2 | + |
| 3 | + |
| 4 | +The Real-Time Decoding API enables low-latency error correction on quantum hardware by allowing CUDA-Q quantum kernels to interact with decoders during circuit execution. This API is designed for use cases where corrections must be calculated and applied within qubit coherence times. |
| 5 | + |
| 6 | +The real-time decoding system supports simulation environments for local testing and hardware integration (e.g., on |
| 7 | +`Quantinuum's Helios QPU |
| 8 | +<https://www.quantinuum.com/products-solutions/quantinuum-systems/helios>`_). |
| 9 | + |
| 10 | +Core Decoding Functions |
| 11 | +------------------------ |
| 12 | + |
| 13 | +These functions can be called from within CUDA-Q quantum kernels (``@cudaq.kernel`` decorated functions) to interact with real-time decoders. |
| 14 | + |
| 15 | +.. py:function:: cudaq_qec.qec.enqueue_syndromes(decoder_id, syndromes, tag=0) |
| 16 | +
|
| 17 | + Enqueue syndrome measurements for decoding. |
| 18 | + |
| 19 | + :param decoder_id: Unique identifier for the decoder instance (matches configured decoder ID) |
| 20 | + :param syndromes: List of syndrome measurement results from stabilizer measurements |
| 21 | + :param tag: Optional tag for logging and debugging (default: 0) |
| 22 | + |
| 23 | + **Example:** |
| 24 | + |
| 25 | + .. code-block:: python |
| 26 | +
|
| 27 | + import cudaq |
| 28 | + import cudaq_qec as qec |
| 29 | + from cudaq_qec import patch |
| 30 | +
|
| 31 | + @cudaq.kernel |
| 32 | + def measure_and_decode(logical: patch, decoder_id: int): |
| 33 | + syndromes = measure_stabilizers(logical) |
| 34 | + qec.enqueue_syndromes(decoder_id, syndromes, 0) |
| 35 | +
|
| 36 | +.. py:function:: cudaq_qec.qec.get_corrections(decoder_id, return_size, reset=False) |
| 37 | +
|
| 38 | + Retrieve calculated corrections from the decoder. |
| 39 | + |
| 40 | + :param decoder_id: Unique identifier for the decoder instance |
| 41 | + :param return_size: Number of correction bits to return (typically equals number of logical observables) |
| 42 | + :param reset: Whether to reset accumulated corrections after retrieval (default: False) |
| 43 | + :returns: List of boolean values indicating detected bit flips for each logical observable |
| 44 | + |
| 45 | + **Example:** |
| 46 | + |
| 47 | + .. code-block:: python |
| 48 | +
|
| 49 | + @cudaq.kernel |
| 50 | + def apply_corrections(logical: patch, decoder_id: int): |
| 51 | + corrections = qec.get_corrections(decoder_id, 1, False) |
| 52 | + if corrections[0]: |
| 53 | + x(logical.data) # Apply transversal X correction |
| 54 | +
|
| 55 | +.. py:function:: cudaq_qec.qec.reset_decoder(decoder_id) |
| 56 | +
|
| 57 | + Reset decoder state, clearing all queued syndromes and accumulated corrections. |
| 58 | + |
| 59 | + :param decoder_id: Unique identifier for the decoder instance to reset |
| 60 | + |
| 61 | + **Example:** |
| 62 | + |
| 63 | + .. code-block:: python |
| 64 | +
|
| 65 | + @cudaq.kernel |
| 66 | + def run_experiment(decoder_id: int): |
| 67 | + qec.reset_decoder(decoder_id) # Reset at start of each shot |
| 68 | + # ... perform experiment ... |
| 69 | +
|
| 70 | +Configuration API |
| 71 | +----------------- |
| 72 | + |
| 73 | +The configuration API enables setting up decoders before circuit execution. Decoders are configured using YAML files or programmatically constructed configuration objects. |
| 74 | + |
| 75 | +.. py:function:: cudaq_qec.configure_decoders(config) |
| 76 | +
|
| 77 | + Configure decoders from a multi_decoder_config object. |
| 78 | + |
| 79 | + :param config: multi_decoder_config object containing decoder specifications |
| 80 | + :returns: 0 on success, non-zero error code on failure |
| 81 | + |
| 82 | +.. py:function:: cudaq_qec.configure_decoders_from_file(config_file) |
| 83 | +
|
| 84 | + Configure decoders from a YAML file. |
| 85 | + |
| 86 | + :param config_file: Path to YAML configuration file |
| 87 | + :returns: 0 on success, non-zero error code on failure |
| 88 | + |
| 89 | +.. py:function:: cudaq_qec.configure_decoders_from_str(config_str) |
| 90 | +
|
| 91 | + Configure decoders from a YAML string. |
| 92 | + |
| 93 | + :param config_str: YAML configuration as a string |
| 94 | + :returns: 0 on success, non-zero error code on failure |
| 95 | + |
| 96 | +.. py:function:: cudaq_qec.finalize_decoders() |
| 97 | +
|
| 98 | + Finalize and clean up decoder resources. Should be called before program exit. |
| 99 | + |
| 100 | +Helper Functions |
| 101 | +---------------- |
| 102 | + |
| 103 | +Real-time decoding requires converting matrices to sparse format for efficient decoder configuration. The following utility functions are essential: |
| 104 | + |
| 105 | +.. py:function:: cudaq_qec.pcm_to_sparse_vec(pcm) |
| 106 | +
|
| 107 | + Convert a parity check matrix (PCM) to sparse vector representation for decoder configuration. |
| 108 | + |
| 109 | + :param pcm: Dense binary matrix as numpy array (e.g., ``dem.detector_error_matrix`` or ``dem.observables_flips_matrix``) |
| 110 | + :returns: Sparse vector (list of integers) where -1 separates rows |
| 111 | + |
| 112 | + **Usage in real-time decoding:** |
| 113 | + |
| 114 | + .. code-block:: python |
| 115 | +
|
| 116 | + config.H_sparse = qec.pcm_to_sparse_vec(dem.detector_error_matrix) |
| 117 | + config.O_sparse = qec.pcm_to_sparse_vec(dem.observables_flips_matrix) |
| 118 | +
|
| 119 | +.. py:function:: cudaq_qec.pcm_from_sparse_vec(sparse_vec, num_rows, num_cols) |
| 120 | +
|
| 121 | + Convert sparse vector representation back to a dense parity check matrix. |
| 122 | + |
| 123 | + :param sparse_vec: Sparse representation (from YAML or decoder config) |
| 124 | + :param num_rows: Number of rows in the output matrix |
| 125 | + :param num_cols: Number of columns in the output matrix |
| 126 | + :returns: Dense binary matrix as numpy array |
| 127 | + |
| 128 | +.. py:function:: cudaq_qec.generate_timelike_sparse_detector_matrix(num_syndromes_per_round, num_rounds, include_first_round) |
| 129 | +
|
| 130 | + Generate the D_sparse matrix that encodes how detectors relate across syndrome measurement rounds. |
| 131 | + |
| 132 | + :param num_syndromes_per_round: Number of syndrome measurements per round (typically code distance squared) |
| 133 | + :param num_rounds: Total number of syndrome measurement rounds |
| 134 | + :param include_first_round: Boolean (False for standard memory experiments) or list for custom first round |
| 135 | + :returns: Sparse matrix encoding detector relationships |
| 136 | + |
| 137 | + **Usage in real-time decoding:** |
| 138 | + |
| 139 | + .. code-block:: python |
| 140 | +
|
| 141 | + config.D_sparse = qec.generate_timelike_sparse_detector_matrix( |
| 142 | + numSyndromesPerRound, numRounds, False) |
| 143 | +
|
| 144 | +See also :ref:`Parity Check Matrix Utilities <python_api:Parity Check Matrix Utilities>` for additional PCM manipulation functions. |
0 commit comments