CUDA-Q QEC C++ API

Code

class code : public cudaqx::extension_point<code, const heterogeneous_map&>

Base class for quantum error correcting codes in CUDA-Q.

This class provides the core interface and functionality for implementing quantum error correcting codes in CUDA-Q. It defines the basic operations that any QEC code must support and provides infrastructure for syndrome measurement and error correction experiments.

To implement a new quantum error correcting code:

  1. Create a new class that inherits from code

  2. Implement the protected virtual methods:

  3. Define quantum kernels for each required logical operation (these are the fault tolerant logical operation implementations)

  4. Register the operations in your constructor using the operation_encodings map on the base class

  5. Register your new code type using CUDAQ_REGISTER_TYPE

Example implementation:

__qpu__ void x_kernel(patch p);
__qpu__ void z_kernel(patch p);
class my_code : public qec::code {
protected:
  std::size_t get_num_data_qubits() const override { return 7; }
  std::size_t get_num_ancilla_qubits() const override { return 6; }
  std::size_t get_num_ancilla_x_qubits() const override { return 3; }
  std::size_t get_num_ancilla_z_qubits() const override { return 3; }

public:
  my_code(const heterogeneous_map& options) : code() {
    // Can use user-specified options, e.g. auto d =
    options.get<int>("distance");
    operation_encodings.insert(std::make_pair(operation::x, x_kernel));
    operation_encodings.insert(std::make_pair(operation::z, z_kernel));
    // Register other required operations...

    // Define the default stabilizers!
    m_stabilizers = qec::stabilizers({"XXXX", "ZZZZ"});
  }

  CUDAQ_EXTENSION_CUSTOM_CREATOR_FUNCTION(
    my_code,
    static std::unique_ptr<qec::code> create(const heterogeneous_map
&options) { return std::make_unique<my_code>(options);
    }
  )
};

CUDAQ_REGISTER_TYPE(my_code)

Supported quantum operations for error correcting codes

Subclassed by cudaq::qec::repetition::repetition, cudaq::qec::steane::steane, cudaq::qec::surface_code::surface_code

Public Types

using one_qubit_encoding = cudaq::qkernel<void(patch)>

Type alias for single qubit quantum kernels.

using two_qubit_encoding = cudaq::qkernel<void(patch, patch)>

Type alias for two qubit quantum kernels.

using stabilizer_round = cudaq::qkernel<std::vector<cudaq::measure_result>(patch, const std::vector<std::size_t>&, const std::vector<std::size_t>&)>

Type alias for stabilizer measurement kernels.

using encoding = std::variant<one_qubit_encoding, two_qubit_encoding, stabilizer_round>

Type alias for quantum operation encodings.

Public Functions

virtual std::size_t get_num_data_qubits() const = 0

Get the number of physical data qubits needed for the code.

Returns:

Number of data qubits

virtual std::size_t get_num_ancilla_qubits() const = 0

Get the total number of ancilla qubits needed.

Returns:

Total number of ancilla qubits

virtual std::size_t get_num_ancilla_x_qubits() const = 0

Get number of ancilla qubits needed for X stabilizer measurements.

Returns:

Number of X-type ancilla qubits

virtual std::size_t get_num_ancilla_z_qubits() const = 0

Get number of ancilla qubits needed for Z stabilizer measurements.

Returns:

Number of Z-type ancilla qubits

cudaqx::tensor<uint8_t> get_parity() const

Get the full parity check matrix H = (Hx | Hz)

Returns:

Tensor representing the parity check matrix

cudaqx::tensor<uint8_t> get_parity_x() const

Get the X component of the parity check matrix.

Returns:

Tensor representing Hx

cudaqx::tensor<uint8_t> get_parity_z() const

Get the Z component of the parity check matrix.

Returns:

Tensor representing Hz

cudaqx::tensor<uint8_t> get_pauli_observables_matrix() const

Get Lx stacked on Lz.

Returns:

Tensor representing pauli observables

cudaqx::tensor<uint8_t> get_observables_x() const

Get the Lx observables.

Returns:

Tensor representing Lx

cudaqx::tensor<uint8_t> get_observables_z() const

Get the Lz observables.

Returns:

Tensor representing Lz

inline const std::vector<cudaq::spin_op_term> &get_stabilizers() const

Get the stabilizer generators.

Returns:

Reference to stabilizers

inline bool contains_operation(operation op) const

Return true if this code contains the given operation encoding.

Public Static Functions

static std::unique_ptr<code> get(const std::string &name, const std::vector<cudaq::spin_op_term> &stabilizers, const heterogeneous_map options = {})

Factory method to create a code instance with specified stabilizers.

Parameters:
  • name – Name of the code to create

  • stabilizers – Stabilizer generators for the code

  • options – Optional code-specific configuration options

Returns:

Unique pointer to created code instance

static std::unique_ptr<code> get(const std::string &name, const heterogeneous_map options = {})

Factory method to create a code instance.

Parameters:
  • name – Name of the code to create

  • options – Optional code-specific configuration options

Returns:

Unique pointer to created code instance

struct patch

Represents a logical qubit patch for quantum error correction.

This type is for CUDA-Q kernel code only.

This structure defines a patch of qubits used in quantum error correction codes. It consists of data qubits and ancilla qubits for X and Z stabilizer measurements.

Public Members

cudaq::qview data

View of the data qubits in the patch.

cudaq::qview ancx

View of the ancilla qubits used for X stabilizer measurements.

cudaq::qview ancz

View of the ancilla qubits used for Z stabilizer measurements.

class repetition : public cudaq::qec::code

Implementation of the repetition quantum error correction code.

Public Functions

repetition(const heterogeneous_map&)

Constructs a repetition code instance.

class steane : public cudaq::qec::code

Steane code implementation.

Public Functions

steane(const heterogeneous_map&)

Constructor for the Steane code.

class stabilizer_grid

Generates and keeps track of the 2d grid of stabilizers in the rotated surface code. Following same layout convention as in: https://arxiv.org/abs/2311.10687 Grid layout is arranged from left to right, top to bottom (row major storage) grid_length = 4 example:

(0,0)   (0,1)   (0,2)   (0,3)
(1,0)   (1,1)   (1,2)   (1,3)
(2,0)   (2,1)   (2,2)   (2,3)
(3,0)   (3,1)   (3,2)   (3,3)
Each entry on the grid can be an X stabilizer, Z stabilizer, or empty, as is needed on the edges. The grid length of 4 corresponds to a distance 3 surface code, which results in:
e(0,0)  e(0,1)  Z(0,2)  e(0,3)
X(1,0)  Z(1,1)  X(1,2)  e(1,3)
e(2,0)  X(2,1)  Z(2,2)  X(2,3)
e(3,0)  Z(3,1)  e(3,2)  e(3,3)

This is seen through the print_stabilizer_grid() member function. To get rid of the empty sites, the print_stabilizer_coords() function is used:

                Z(0,2)
X(1,0)  Z(1,1)  X(1,2)
        X(2,1)  Z(2,2)  X(2,3)
        Z(3,1)

and to get the familiar visualization of the distance three surface code, the print_stabilizer_indices results in:

        Z0
X0  Z1  X1
    X2  Z2  X3
    Z3

The data qubits are located at the four corners of each of the weight-4 stabilizers. They are also organized with index increasing from left to right, top to bottom:

d0  d1  d2
d3  d4  d5
d6  d7  d8

Public Functions

stabilizer_grid(uint32_t distance)

Construct the grid from the code’s distance.

stabilizer_grid()

Empty constructor.

void print_stabilizer_grid() const

Print a 2d grid of stabilizer roles.

void print_stabilizer_coords() const

Print a 2d grid of stabilizer coords.

void print_stabilizer_indices() const

Print a 2d grid of stabilizer indices.

void print_data_grid() const

Print a 2d grid of data qubit indices.

void print_stabilizer_maps() const

Print the coord <–> indices maps.

void print_stabilizers() const

Print the stabilizers in sparse pauli format.

std::vector<cudaq::spin_op_term> get_spin_op_stabilizers() const

Get the stabilizers as a vector of cudaq::spin_op_terms.

std::vector<cudaq::spin_op_term> get_spin_op_observables() const

Get the observables as a vector of cudaq::spin_op_terms.

Public Members

uint32_t distance = 0

The distance of the code determines the number of data qubits per dimension.

uint32_t grid_length = 0

length of the stabilizer grid for distance = d data qubits, the stabilizer grid has length d+1

std::vector<surface_role> roles

flattened vector of the stabilizer grid sites roles’ grid idx -> role stored in row major order

std::vector<vec2d> x_stab_coords

x stab index -> 2d coord

std::vector<vec2d> z_stab_coords

z stab index -> 2d coord

std::map<vec2d, size_t> x_stab_indices

2d coord -> z stab index

std::map<vec2d, size_t> z_stab_indices

2d coord -> z stab index

std::vector<vec2d> data_coords

data index -> 2d coord data qubits are in an offset 2D coord system from stabilizers

std::map<vec2d, size_t> data_indices

2d coord -> data index

std::vector<std::vector<size_t>> x_stabilizers

Each element is an X stabilizer specified by the data qubits it has support on In surface code, can have weight 2 or weight 4 stabs So {x,z}_stabilizer[i].size() == 2 || 4.

std::vector<std::vector<size_t>> z_stabilizers

Each element is an Z stabilizer specified by the data qubits it has support on.

class surface_code : public cudaq::qec::code

surface_code implementation

Public Functions

surface_code(const heterogeneous_map&)

Constructor for the surface_code.

CUDAQ_EXTENSION_CUSTOM_CREATOR_FUNCTION (surface_code, static std::unique_ptr< cudaq::qec::code > create(const cudaqx::heterogeneous_map &options) { return std::make_unique< surface_code >(options);}) stabilizer_grid grid

Extension creator function for the surface_code.

Grid to keep track of topological arrangement of qubits.

Detector Error Model

struct detector_error_model

A detector error model (DEM) for a quantum error correction circuit. A DEM can be created from a QEC circuit and a noise model. It contains information about which errors flip which detectors. This is used by the decoder to help make predictions about observables flips.

Shared size parameters among the matrix types.

  • detector_error_matrix: num_detectors x num_error_mechanisms [d, e]

  • error_rates: num_error_mechanisms

  • observables_flips_matrix: num_observables x num_error_mechanisms [k, e]

Note

The C++ API for this class may change in the future. The Python API is more likely to be backwards compatible.

Public Functions

std::size_t num_detectors() const

Return the number of rows in the detector_error_matrix.

std::size_t num_error_mechanisms() const

Return the number of columns in the detector_error_matrix, error_rates, and observables_flips_matrix.

std::size_t num_observables() const

Return the number of rows in the observables_flips_matrix.

void canonicalize_for_rounds(uint32_t num_syndromes_per_round)

Put the detector_error_matrix into canonical form, where the rows and columns are ordered in a way that is amenable to the round-based decoding process.

Public Members

cudaqx::tensor<uint8_t> detector_error_matrix

The detector error matrix is a specific kind of circuit-level parity-check matrix where each row represents a detector, and each column represents an error mechanism. The entries of this matrix are H[i,j] = 1 if detector i is triggered by error mechanism j, and 0 otherwise.

std::vector<double> error_rates

The list of weights has length equal to the number of columns of detector_error_matrix, which assigns a likelihood to each error mechanism.

cudaqx::tensor<uint8_t> observables_flips_matrix

The observables flips matrix is a specific kind of circuit-level parity- check matrix where each row represents a Pauli observable, and each column represents an error mechanism. The entries of this matrix are O[i,j] = 1 if Pauli observable i is flipped by error mechanism j, and 0 otherwise.

std::optional<std::vector<std::size_t>> error_ids

Error mechanism ID. From a probability perspective, each error mechanism ID is independent of all other error mechanism ID. For all errors with the same ID, only one of them can happen. That is - the errors containing the same ID are correlated with each other.

cudaq::qec::detector_error_model cudaq::qec::dem_from_memory_circuit(const code &code, operation statePrep, std::size_t numRounds, cudaq::noise_model &noise)

Given a memory circuit setup, generate a DEM.

Parameters:
  • code – QEC Code to sample

  • statePrep – Initial state preparation operation

  • numRounds – Number of stabilizer measurement rounds

  • noise – Noise model to apply

Returns:

Detector error model

detector_error_model cudaq::qec::x_dem_from_memory_circuit(const code &code, operation statePrep, std::size_t numRounds, cudaq::noise_model &noise)

Given a memory circuit setup, generate a DEM for X stabilizers.

Parameters:
  • code – QEC Code to sample

  • statePrep – Initial state preparation operation

  • numRounds – Number of stabilizer measurement rounds

  • noise – Noise model to apply

Returns:

Detector error model

detector_error_model cudaq::qec::z_dem_from_memory_circuit(const code &code, operation statePrep, std::size_t numRounds, cudaq::noise_model &noise)

Given a memory circuit setup, generate a DEM for Z stabilizers.

Parameters:
  • code – QEC Code to sample

  • statePrep – Initial state preparation operation

  • numRounds – Number of stabilizer measurement rounds

  • noise – Noise model to apply

Returns:

Detector error model

Decoder Interfaces

class decoder : public cudaqx::extension_point<decoder, const cudaqx::tensor<uint8_t>&, const cudaqx::heterogeneous_map&>

The decoder base class should be subclassed by specific decoder implementations. The heterogeneous_map provides a placeholder for arbitrary constructor parameters that can be unique to each specific decoder.

Public Functions

decoder(const cudaqx::tensor<uint8_t> &H)

Constructor.

Parameters:

H – Decoder’s parity check matrix represented as a tensor. The tensor is required be rank 2 and must be of dimensions syndrome_size x block_size. will use the same H.

virtual decoder_result decode(const std::vector<float_t> &syndrome) = 0

Decode a single syndrome.

Parameters:

syndrome – A vector of syndrome measurements where the floating point value is the probability that the syndrome measurement is a |1>. The length of the syndrome vector should be equal to syndrome_size.

Returns:

Vector of length block_size with soft probabilities of errors in each index.

virtual decoder_result decode(const cudaqx::tensor<uint8_t> &syndrome)

Decode a single syndrome.

Parameters:

syndrome – An order-1 tensor of syndrome measurements where a 1 bit represents that the syndrome measurement is a |1>. The length of the syndrome vector should be equal to syndrome_size.

Returns:

Vector of length block_size of errors in each index.

virtual std::future<decoder_result> decode_async(const std::vector<float_t> &syndrome)

Decode a single syndrome.

Parameters:

syndrome – A vector of syndrome measurements where the floating point value is the probability that the syndrome measurement is a |1>.

Returns:

std::future of a vector of length block_size with soft probabilities of errors in each index.

virtual std::vector<decoder_result> decode_batch(const std::vector<std::vector<float_t>> &syndrome)

Decode multiple independent syndromes (may be done in serial or parallel depending on the specific implementation)

Parameters:

syndrome – A vector of N syndrome measurements where the floating point value is the probability that the syndrome measurement is a |1>.

Returns:

2-D vector of size N x block_size with soft probabilities of errors in each index.

inline virtual ~decoder()

Destructor.

virtual std::string get_version() const

Get the version of the decoder. Subclasses that are not part of the standard GitHub repo should override this to provide a more tailored version string.

Returns:

A string containing the version of the decoder

Public Static Functions

static std::unique_ptr<decoder> get(const std::string &name, const cudaqx::tensor<uint8_t> &H, const cudaqx::heterogeneous_map &param_map = cudaqx::heterogeneous_map())

This get overload supports default values.

struct decoder_result

Decoder results.

Public Members

bool converged = false

Whether or not the decoder converged.

std::vector<float_t> result

Vector of length block_size with soft probabilities of errors in each index.

std::optional<cudaqx::heterogeneous_map> opt_results

Optional additional results from the decoder stored in a heterogeneous map. For equality comparison, this field is treated as a boolean flag - two decoder_results are considered equal only if both have empty opt_results (either std::nullopt or an empty map). If either result has non-empty opt_results, they are considered not equal.

Built-in Decoders

NVIDIA QLDPC Decoder

class nv_qldpc_decoder

A general purpose Quantum Low-Density Parity-Check Decoder (QLDPC) decoder based on GPU accelerated belief propagation (BP). Since belief propagation is an iterative method, decoding can be improved with a second-stage post-processing step. Optionally, ordered statistics decoding (OSD) can be chosen to perform the second stage of decoding.

An [[n,k,d]] quantum error correction (QEC) code encodes k logical qubits into an n qubit data block, with a code distance d. Quantum low-density parity-check (QLDPC) codes are characterized by sparse parity-check matrices (or Tanner graphs), corresponding to a bounded number of parity checks per data qubit.

Requires a CUDA-Q compatible GPU. See the CUDA-Q GPU Compatibility List for a list of valid GPU configurations.

References: Decoding Across the Quantum LDPC Code Landscape

Note

It is required to create decoders with the get_decoder API from the CUDA-QX extension points API, such as

import cudaq_qec as qec
import numpy as np
H = np.array([[1, 0, 0, 1, 0, 1, 1],
              [0, 1, 0, 1, 1, 0, 1],
              [0, 0, 1, 0, 1, 1, 1]], dtype=np.uint8) # sample 3x7 PCM
opts = dict() # see below for options
# Note: H must be in row-major order. If you use
# `scipy.sparse.csr_matrix.todense()` to get the parity check
# matrix, you must specify todense(order='C') to get a row-major
# matrix.
nvdec = qec.get_decoder('nv-qldpc-decoder', H, **opts)
std::size_t block_size = 7;
std::size_t syndrome_size = 3;
cudaqx::tensor<uint8_t> H;

std::vector<uint8_t> H_vec = {1, 0, 0, 1, 0, 1, 1,
                              0, 1, 0, 1, 1, 0, 1,
                              0, 0, 1, 0, 1, 1, 1};
H.copy(H_vec.data(), {syndrome_size, block_size});

cudaqx::heterogeneous_map nv_custom_args;
nv_custom_args.insert("use_osd", true);
// See below for options

auto nvdec = cudaq::qec::get_decoder("nv-qldpc-decoder", H, nv_custom_args);

Note

The "nv-qldpc-decoder" implements the cudaq_qec.Decoder interface for Python and the cudaq::qec::decoder interface for C++, so it supports all the methods in those respective classes.

Parameters:
  • H – Parity check matrix (tensor format)

  • params

    Heterogeneous map of parameters:

    • use_sparsity (bool): Whether or not to use a sparse matrix solver

    • error_rate (double): Probability of an error (in 0-1 range) on a block data bit (defaults to 0.001)

    • error_rate_vec (double): Vector of length “block size” containing the probability of an error (in 0-1 range) on a block data bit (defaults to 0.001). This overrides error_rate.

    • max_iterations (int): Maximum number of BP iterations to perform (defaults to 30)

    • n_threads (int): Number of CUDA threads to use for the GPU decoder (defaults to smart selection based on parity matrix size)

    • use_osd (bool): Whether or not to use an OSD post processor if the initial BP algorithm fails to converge on a solution

    • osd_method (int): 1=OSD-0, 2=Exhaustive, 3=Combination Sweep (defaults to 1). Ignored unless use_osd is true.

    • osd_order (int): OSD postprocessor order (defaults to 0). Ref: Decoding Across the Quantum LDPC Code Landscape

      • For osd_method=2 (Exhaustive), the number of possible permutations searched after OSD-0 grows by 2^osd_order.

      • For osd_method=3 (Combination Sweep), this is the λ parameter. All weight 1 permutations and the first λ bits worth of weight 2 permutations are searched after OSD-0. This is (syndrome_length - block_size + λ * (λ - 1) / 2) additional permutations.

      • For other osd_method values, this is ignored.

    • bp_batch_size (int): Number of syndromes that will be decoded in parallel for the BP decoder (defaults to 1)

    • osd_batch_size (int): Number of syndromes that will be decoded in parallel for OSD (defaults to the number of concurrent threads supported by the hardware)

Parity Check Matrix Utilities

std::vector<std::vector<std::uint32_t>> cudaq::qec::dense_to_sparse(const cudaqx::tensor<uint8_t> &pcm)

Return a sparse representation of the PCM.

Parameters:

pcm – The PCM to convert to a sparse representation.

Returns:

A vector of vectors that sparsely represents the PCM. The size of the outer vector is the number of columns in the PCM, and the i-th element contains an inner vector of the row indices of the non-zero elements in the i-th column of the PCM.

cudaqx::tensor<uint8_t> cudaq::qec::generate_random_pcm(std::size_t n_rounds, std::size_t n_errs_per_round, std::size_t n_syndromes_per_round, int weight, std::mt19937_64 &&rng)

Generate a random PCM with the given parameters.

Parameters:
  • n_rounds – The number of rounds in the PCM.

  • n_errs_per_round – The number of errors per round in the PCM.

  • n_syndromes_per_round – The number of syndromes per round in the PCM.

  • weight – The column weight of the PCM.

  • rng – The random number generator to use (e.g. std::mt19937_64(your_seed))

Returns:

A random PCM with the given parameters.

std::tuple<cudaqx::tensor<uint8_t>, std::uint32_t, std::uint32_t> cudaq::qec::get_pcm_for_rounds(const cudaqx::tensor<uint8_t> &pcm, std::uint32_t num_syndromes_per_round, std::uint32_t start_round, std::uint32_t end_round, bool straddle_start_round = false, bool straddle_end_round = false)

Get a sub-PCM for a range of rounds. It is recommended (but not required) that you call sort_pcm_columns() before calling this function.

Parameters:
  • pcm – The PCM to get a sub-PCM for.

  • num_syndromes_per_round – The number of syndromes per round.

  • start_round – The start round (0-based).

  • end_round – The end round (0-based).

  • straddle_start_round – Whether to include columns that straddle the start_round (defaults to false)

  • straddle_end_round – Whether to include columns that straddle the end_round (defaults to false)

Returns:

A tuple with the new PCM with the columns in the range [start_round, end_round], the first column included, and the last column included.

std::vector<std::uint32_t> cudaq::qec::get_sorted_pcm_column_indices(const std::vector<std::vector<std::uint32_t>> &row_indices, std::uint32_t num_syndromes_per_round = 0)

Return a vector of column indices that would sort the PCM columns in topological order.

This function tries to make a matrix that is close to a block diagonal matrix from its input. Columns are first sorted by the index of the first non-zero entry in the column, and if those match, then they are sorted by the index of the last non-zero entry in the column. This ping pong continues for the indices of the second non-zero element and the second-to-last non-zero element, and so forth.

Parameters:
  • row_indices – For each column, a vector of row indices that have a non-zero value in that column.

  • num_syndromes_per_round – The number of syndromes per round. (Defaults to 0, which means that no secondary per-round sorting will occur.)

std::vector<std::uint32_t> cudaq::qec::get_sorted_pcm_column_indices(const cudaqx::tensor<uint8_t> &pcm, std::uint32_t num_syndromes_per_round = 0)

Return a vector of column indices that would sort the PCM columns in topological order.

Parameters:

num_syndromes_per_round – The number of syndromes per round. (Defaults to 0, which means that no secondary per-round sorting will occur.)

std::pair<cudaqx::tensor<uint8_t>, std::vector<std::uint32_t>> cudaq::qec::pcm_extend_to_n_rounds(const cudaqx::tensor<uint8_t> &pcm, std::size_t num_syndromes_per_round, std::uint32_t n_rounds)

Extend a PCM to the given number of rounds.

Parameters:
  • pcm – The PCM to extend.

  • num_syndromes_per_round – The number of syndromes per round.

  • n_rounds – The number of rounds to extend the PCM to.

Returns:

A pair of the new PCM and the list of column indices from the original PCM that were used to form the new PCM.

bool cudaq::qec::pcm_is_sorted(const cudaqx::tensor<uint8_t> &pcm, std::uint32_t num_syndromes_per_round = 0)

Check if a PCM is sorted.

Parameters:
  • pcm – The PCM to check.

  • num_syndromes_per_round – The number of syndromes per round.

Returns:

True if the PCM is sorted, false otherwise.

cudaqx::tensor<uint8_t> cudaq::qec::reorder_pcm_columns(const cudaqx::tensor<uint8_t> &pcm, const std::vector<std::uint32_t> &column_order, uint32_t row_begin = 0, uint32_t row_end = std::numeric_limits<uint32_t>::max())

Reorder the columns of a PCM according to the given column order. Note: this may return a subset of the columns in the original PCM if the column_order does not contain all of the columns in the original PCM.

Parameters:
  • pcm – The PCM to reorder.

  • column_order – The column order to use for reordering.

  • row_begin – The first row to include in the reordering. Leave at the default value to include all rows.

  • row_end – The last row to include in the reordering. Leave at the default value to include all rows.

Returns:

A new PCM with the columns reordered according to the given column order.

cudaqx::tensor<uint8_t> cudaq::qec::shuffle_pcm_columns(const cudaqx::tensor<uint8_t> &pcm, std::mt19937_64 &&rng)

Randomly permute the columns of a PCM.

Parameters:
  • pcm – The PCM to permute.

  • rng – The random number generator to use (e.g. std::mt19937_64(your_seed))

Returns:

A new PCM with the columns permuted randomly.

std::pair<cudaqx::tensor<uint8_t>, std::vector<double>> cudaq::qec::simplify_pcm(const cudaqx::tensor<uint8_t> &pcm, const std::vector<double> &weights, std::uint32_t num_syndromes_per_round = 0)

Simplify a PCM by removing duplicate columns and 0-weight columns, and combine the probability weight vectors accordingly.

Parameters:
  • pcm – The PCM to simplify.

  • weights – The probability weight vectors to combine.

Returns:

A new PCM with the columns sorted in topological order, and the probability weight vectors combined accordingly.

cudaqx::tensor<uint8_t> cudaq::qec::sort_pcm_columns(const cudaqx::tensor<uint8_t> &pcm, std::uint32_t num_syndromes_per_round = 0)

Sort the columns of a PCM in topological order.

Parameters:

pcm – The PCM to sort.

Returns:

A new PCM with the columns sorted in topological order.

Common

using cudaq::qec::float_t = double
enum class cudaq::qec::operation

Enum describing all supported logical operations.

Values:

enumerator x

Logical X gate.

enumerator y

Logical Y gate.

enumerator z

Logical Z gate.

enumerator h

Logical Hadamard gate.

enumerator s

Logical S gate.

enumerator cx

Logical controlled-X gate.

enumerator cy

Logical controlled-Y gate.

enumerator cz

Logical controlled-Z gate.

enumerator stabilizer_round

Stabilizer measurement round.

enumerator prep0

Prepare logical |0⟩ state.

enumerator prep1

Prepare logical |1⟩ state.

enumerator prepp

Prepare logical |+⟩ state.

enumerator prepm

Prepare logical |-⟩ state.

std::tuple<cudaqx::tensor<uint8_t>, cudaqx::tensor<uint8_t>> cudaq::qec::sample_code_capacity(const cudaqx::tensor<uint8_t> &H, std::size_t numShots, double error_probability)

Sample syndrome measurements with code capacity noise.

Parameters:
  • H – Parity check matrix of a QEC code

  • numShots – Number of measurement shots

  • error_probability – Probability of bit flip on data

Returns:

Tuple containing syndrome measurements and data qubit measurements

std::tuple<cudaqx::tensor<uint8_t>, cudaqx::tensor<uint8_t>> cudaq::qec::sample_code_capacity(const cudaqx::tensor<uint8_t> &H, std::size_t numShots, double error_probability, unsigned seed)

Sample syndrome measurements with code capacity noise.

Parameters:
  • H – Parity check matrix of a QEC code

  • numShots – Number of measurement shots

  • error_probability – Probability of bit flip on data

  • seed – RNG seed for reproducible experiments

Returns:

Tuple containing syndrome measurements and data qubit measurements

std::tuple<cudaqx::tensor<uint8_t>, cudaqx::tensor<uint8_t>> cudaq::qec::sample_code_capacity(const code &code, std::size_t numShots, double error_probability)

Sample syndrome measurements with code capacity noise.

Parameters:
  • code – QEC Code to sample

  • numShots – Number of measurement shots

  • error_probability – Probability of bit flip on data

Returns:

Tuple containing syndrome measurements and data qubit measurements

std::tuple<cudaqx::tensor<uint8_t>, cudaqx::tensor<uint8_t>> cudaq::qec::sample_code_capacity(const code &code, std::size_t numShots, double error_probability, unsigned seed)

Sample syndrome measurements with code capacity noise.

Parameters:
  • code – QEC Code to sample

  • numShots – Number of measurement shots

  • error_probability – Probability of bit flip on data

  • seed – RNG seed for reproducible experiments

Returns:

Tuple containing syndrome measurements and data qubit measurements

std::tuple<cudaqx::tensor<uint8_t>, cudaqx::tensor<uint8_t>> cudaq::qec::sample_memory_circuit(const code &code, std::size_t numShots, std::size_t numRounds = 1)

Sample syndrome measurements starting from |0⟩ state.

Parameters:
  • numShots – Number of measurement shots

  • numRounds – Number of stabilizer measurement rounds

Returns:

Tuple containing syndrome measurements and data qubit measurements (mz for z basis state prep, mx for x basis)

std::tuple<cudaqx::tensor<uint8_t>, cudaqx::tensor<uint8_t>> cudaq::qec::sample_memory_circuit(const code &code, std::size_t numShots, std::size_t numRounds, cudaq::noise_model &noise)

Sample syndrome measurements from |0⟩ state with noise.

Parameters:
  • numShots – Number of measurement shots

  • numRounds – Number of stabilizer measurement rounds

  • noise – Noise model to apply

Returns:

Tuple containing syndrome measurements and data qubit measurements (mz for z basis state prep, mx for x basis)

std::tuple<cudaqx::tensor<uint8_t>, cudaqx::tensor<uint8_t>> cudaq::qec::sample_memory_circuit(const code &code, operation statePrep, std::size_t numShots, std::size_t numRounds = 1)

Sample syndrome measurements from the memory circuit.

Parameters:
  • statePrep – Initial state preparation operation

  • numShots – Number of measurement shots

  • numRounds – Number of stabilizer measurement rounds

Returns:

Tuple containing syndrome measurements and data qubit measurements (mz for z basis state prep, mx for x basis)

std::tuple<cudaqx::tensor<uint8_t>, cudaqx::tensor<uint8_t>> cudaq::qec::sample_memory_circuit(const code &code, operation statePrep, std::size_t numShots, std::size_t numRounds, cudaq::noise_model &noise)

Sample syndrome measurements with circuit-level noise.

Parameters:
  • statePrep – Initial state preparation operation

  • numShots – Number of measurement shots

  • numRounds – Number of stabilizer measurement rounds

  • noise – Noise model to apply

Returns:

Tuple containing syndrome measurements and data qubit measurements (mz for z basis state prep, mx for x basis)