CUDA Quantum C++ API

Operators

class spin_op

The spin_op represents a general sum of Pauli tensor products. It exposes the typical algebraic operations that allow programmers to define primitive Pauli operators and use them to compose larger, more complex Pauli tensor products and sums thereof.

Public Types

using spin_op_term = std::vector<bool>

We represent the spin_op terms in binary symplectic form, i.e. each term is a vector of 1s and 0s of size 2 * nQubits, where the first n elements represent X, the next n elements represent Z, and X=Z=1 -> Y on site i, X=1, Z=0 -> X on site i, and X=0, Z=1 -> Z on site i.

using csr_spmatrix = std::tuple<std::vector<std::complex<double>>, std::vector<std::size_t>, std::vector<std::size_t>>

Typedef for a vector of non-zero sparse matrix elements.

Public Functions

spin_op(std::pair<const spin_op_term, std::complex<double>> &termData)

The constructor, takes a single term / coefficient pair.

spin_op(const std::pair<const spin_op_term, std::complex<double>> &termData)

The constructor, takes a single term / coefficient constant pair.

spin_op(pauli, const std::size_t id, std::complex<double> coeff = 1.0)

Constructor, takes the Pauli type, the qubit site, and the term coefficient. Constructs a spin_op of one Pauli on one qubit.

spin_op(const spin_op_term &term, const std::complex<double> &coeff)

Constructor, takes the binary representation of a single term and its coefficient.

spin_op(const std::unordered_map<spin_op_term, std::complex<double>> &_terms)

Constructor, takes a full set of terms for the composite spin op as an unordered_map mapping individual terms to their coefficient.

spin_op(const std::vector<spin_op_term> &bsf, const std::vector<std::complex<double>> &coeffs)

Construct from a vector of term data.

spin_op()

Constructor, creates the identity term.

spin_op(std::size_t numQubits)

Construct the identity term on the given number of qubits.

spin_op(const spin_op &o)

Copy constructor.

spin_op(std::vector<double> &data_rep, std::size_t nQubits)

Construct this spin_op from a serialized representation. Specifically, this encoding is via a vector of doubles. The encoding is as follows: for each term, a list of doubles where element i is a 3.0 for a Y, a 1.0 for a X, and a 2.0 for a Z on qubit i, followed by the real and imaginary part of the coefficient. Each term is appended to the array forming one large 1d array of doubles. The array is ended with the total number of terms represented as a double.

~spin_op() = default

The destructor.

iterator<spin_op> begin()

Return iterator to start of spin_op terms.

iterator<spin_op> end()

Return iterator to end of spin_op terms.

iterator<const spin_op> begin() const

Return constant iterator to start of spin_op terms.

iterator<const spin_op> end() const

Return constant iterator to end of spin_op terms.

spin_op &operator=(const spin_op&)

Set the provided spin_op equal to this one and return *this.

spin_op &operator+=(const spin_op &v) noexcept

Add the given spin_op to this one and return *this.

spin_op &operator-=(const spin_op &v) noexcept

Subtract the given spin_op from this one and return *this.

spin_op &operator*=(const spin_op &v) noexcept

Multiply the given spin_op with this one and return *this.

bool operator==(const spin_op &v) const noexcept

Return true if this spin_op is equal to the given one. Equality here does not consider the coefficients.

spin_op &operator*=(const double v) noexcept

Multiply this spin_op by the given double.

spin_op &operator*=(const std::complex<double> v) noexcept

Multiply this spin_op by the given complex value.

std::size_t num_qubits() const

Return the number of qubits this spin_op is on.

std::size_t num_terms() const

Return the number of terms in this spin_op.

std::complex<double> get_coefficient() const

For a spin_op with 1 term, get that terms’ coefficient. Throws an exception for spin_ops with > 1 terms.

std::pair<std::vector<spin_op_term>, std::vector<std::complex<double>>> get_raw_data() const

Return the binary symplectic form data.

bool is_identity() const

Is this spin_op == to the identity.

void dump() const

Dump a string representation of this spin_op to standard out.

std::string to_string(bool printCoefficients = true) const

Return a string representation of this spin_op.

std::vector<double> getDataRepresentation()

Return the vector<double> serialized representation of this spin_op. (see the constructor for the encoding)

std::vector<spin_op> distribute_terms(std::size_t numChunks) const

Return a vector of spin_op representing a distribution of the terms in this spin_op into equally sized chunks.

void for_each_term(std::function<void(spin_op&)>&&) const

Apply the give functor on each term of this spin_op. This method can enable general reductions via lambda capture variables.

void for_each_pauli(std::function<void(pauli, std::size_t)>&&) const

Apply the functor on each Pauli in this 1-term spin_op. An exception is thrown if there are more than 1 terms. Users should pass a functor that takes the pauli type and the qubit index.

complex_matrix to_matrix() const

Return a dense matrix representation of this spin_op.

csr_spmatrix to_sparse_matrix() const

Return a sparse matrix representation of this spin_op. The return type encodes all non-zero (row, col, value) elements.

Public Static Functions

static spin_op random(std::size_t nQubits, std::size_t nTerms, unsigned int seed = std::random_device{}())

Return a random spin operator acting on the specified number of qubits and composed of the given number of terms. Override seed for repeatability.

static spin_op from_word(const std::string &pauliWord)

Return a spin_op representative of the input Pauli word, e.g. XYX for a spin_op on 3 qubits with a X support on the first and 3rd and Y support on the second.

template<typename QualifiedSpinOp>
struct iterator

Quantum

constexpr std::size_t cudaq::dyn = ~0
template<std::size_t Levels>
class qudit

The qudit models a general d-level quantum system. This type is templated on the number of levels d.

Public Functions

inline qudit()

Construct a qudit, will allocated a new unique index.

template<std::size_t N = dyn, std::size_t Levels = 2, typename = std::enable_if_t<(N > 0)>>
class qreg

A qreg is a container for qudits. This container can be dynamic or compile-time-size specified. By default, the qreg is constructed as a dynamic register (vector-like) of qubits (2-level). This can be changed via the qreg type template parameters.

Public Types

using value_type = qudit<Levels>

Useful typedef indicating the underlying qudit type.

Public Functions

inline auto begin()

Iterator interface, begin.

inline value_type &operator[](const std::size_t idx)

Returns the qudit at idx.

inline qspan<dyn, Levels> front(std::size_t count)

Returns the [0, count) qudits.

inline value_type &front()

Returns the first qudit.

inline qspan<dyn, Levels> back(std::size_t count)

Returns the [count, size()) qudits.

inline value_type &back()

Returns the last qudit.

inline qspan<dyn, Levels> slice(std::size_t start, std::size_t size)

Returns the [start, start+size) qudits.

inline std::size_t size() const

Returns the number of contained qudits.

inline void clear()

Destroys all contained qudits. Postcondition: size() == 0.

template<std::size_t Levels = 2>
class qvector

A qvector is an owning, dynamically sized container for qudits. The semantics of the qvector follows that of a std::vector for qudits. It is templated on the number of levels for the held qudits.

Public Types

using value_type = qudit<Levels>

Useful typedef indicating the underlying qudit type.

Public Functions

inline qvector(std::size_t size)

Construct a qvector with size qudits in the |0> state.

qvector(qvector const&) = delete

qvectors cannot be copied

qvector(qvector&&) = delete

qvectors cannot be moved

qvector &operator=(const qvector&) = delete

qvectors cannot be copy assigned.

inline auto begin()

Iterator interface, begin.

inline auto end()

Iterator interface, end.

inline value_type &operator[](const std::size_t idx)

Returns the qudit at idx.

inline qview<Levels> front(std::size_t count)

Returns the [0, count) qudits as a non-owning qview.

inline value_type &front()

Returns the first qudit.

inline qview<Levels> back(std::size_t count)

Returns the [count, size()) qudits as a non-owning qview

inline value_type &back()

Returns the last qudit.

inline qview<Levels> slice(std::size_t start, std::size_t size)

Returns the [start, start+size) qudits as a non-owning qview

inline std::size_t size() const

Returns the number of contained qudits.

inline void clear()

Destroys all contained qudits. Postcondition: size() == 0.

template<std::size_t N = dyn, std::size_t Levels = 2>
class qspan
template<std::size_t Levels = 2>
class qview

The qview represents a non-owning container of qudits.

Public Types

using value_type = qudit<Levels>

Useful typedef exposing the underlying qudit type that this qview contains.

using cudaq::qubit = qudit<2>

Common

class observe_result

The observe_result encapsulates all data generated from a cudaq”::”observe call. This includes all measurement counts from the execution of each ansatz + measure circuit, and the global expected value of the spin_op passed to observe.

Public Functions

inline observe_result(double e, const spin_op &H)

Constructor, takes the precomputed expectation value for <psi(x) | H | psi(x)> for the given spin_op.

inline observe_result(double e, const spin_op &H, sample_result counts)

Constructor, takes the precomputed expectation value for <psi(x) | H | psi(x)> for the given spin_op. If this execution was shots based, also provide the sample_result data containing counts for each term in H.

inline sample_result raw_data()

Return the raw counts data for all terms.

Returns:

inline operator double()

Conversion operator for this observe_result to double. Simply returns the precomputed expectation value for the given spin_op. This enables one to ignore the fine-grain sample_result data, and explicitly request the expected value: double exp = cudaq”::”observe(…); as opposed to cudaq”::”observe_data data = cudaq::observe(…); auto exp = data.expectation();.

inline double expectation()

Return the expected value for the provided spin_op.

Returns:

template<typename SpinOpType>
inline double expectation(SpinOpType term)

Return the expectation value for a sub-term in the provided spin_op.

template<typename SpinOpType>
inline sample_result counts(SpinOpType term)

Return the counts data for the given spin_op.

Parameters:

term

Returns:

inline double id_coefficient()

Return the coefficient of the identity term.

Returns:

inline void dump()

Dump the counts data to standard out.

class ExecutionContext

The ExecutionContext is an abstraction to indicate how a CUDA Quantum kernel should be executed.

Public Functions

inline ExecutionContext(const std::string n)

The Constructor, takes the name of the context.

Parameters:

n – The name of the context

inline ExecutionContext(const std::string n, std::size_t shots_)

The constructor, takes the name and the number of shots.

Parameters:
  • n – The name of the context

  • shots_ – The number of shots

Public Members

const std::string name

The name of the context ({basic, sampling, observe})

std::size_t shots = 0

The number of execution shots.

std::optional<cudaq::spin_op*> spin

An optional spin operator.

sample_result result

Measurement counts for a CUDA Quantum kernel invocation.

std::optional<double> expectationValue = std::nullopt

A computed expectation value.

bool hasConditionalsOnMeasureResults = false

The kernel being executed in this context has conditional statements on measure results.

const noise_model *noiseModel = nullptr

Noise model to apply to the current execution.

bool canHandleObserve = false

Flag to indicate if backend can handle spin_op observe task under this ExecutionContext.

bool asyncExec = false

Flag indicating that the current execution should occur asynchronously.

details::future futureResult

When execution asynchronously, store the expected results as a cudaq::future here.

State simulationData

simulationData provides a mechanism for simulation clients to extract the underlying simulation data.

Trace kernelTrace

When run under the tracer context, persist the traced quantum resources here.

std::string kernelName = ""

The name of the kernel being executed.

std::size_t batchIteration = 0

The current iteration for a batch execution, used by observe_n and sample_n.

std::size_t totalIterations = 0

For batch execution, the total number of batch iterations.

std::vector<std::string> registerNames

For mid-circuit measurements in library mode keep track of the register names.

std::vector<std::size_t> reorderIdx

A vector containing information about how to reorder the global register after execution. Empty means no reordering.

class future

The future type models the expected result of a CUDA Quantum kernel execution under a specific execution context. This type is returned from asynchronous execution calls. It encapsulates the job-specific circuit execution identifiers, the name of the QPU the job executed on, and any extra configuration information needed to retrieve the results later from the server. This type can be persisted to file and read in later to retrieve execution results. It also optionally wraps a std::future<T> type, and in this case, persistence to file is not allowed, .get() must be invoked at some later point within the same runtime context.

Public Functions

future() = default

The constructor.

future(future&&) = default

move constructor

inline future(std::vector<Job> &_jobs, std::string &qpuNameIn, std::map<std::string, std::string> &config)

The constructor, takes all info required to be able to retrieve results at a later date, even after file persistence.

template<typename T>
class async_result

the async_result type is a user facing, future-like type that is returned from CUDA Quantum public asynchronous API functions. It wraps a details::future type, which can itself be constructed from a std::future or a collection of data pertinent to remote QPU REST invocation.

Public Functions

inline T get()

Return the asynchronously computed data, will wait until the data is ready.

struct ExecutionResult

The ExecutionResult models the result of a typical quantum state sampling task. It will contain the observed measurement bit strings and corresponding number of times observed, as well as an expected value with respect to the Z…Z operator.

Public Functions

std::vector<std::size_t> serialize() const

Serialize this sample result to a vector of integers. Encoding: 1st element is size of the register name N, then next N represent register name, next is the number of bitstrings M, then for each bit string a triple {string mapped to long, bit string length, count}.

Returns:

void deserialize(std::vector<std::size_t> &data)

Deserialize a vector of integers to a ExecutionResult

Parameters:

data – The data with encoding discussed in the brief for serialize.

ExecutionResult() = default

Constructor.

ExecutionResult(CountsDictionary c)

Construct from a CountsDictionary, assumes registerName == global

Parameters:

c – the counts

ExecutionResult(std::string name)

Construct from a register name.

ExecutionResult(double expVal)

Construct from a precomputed expectation value.

ExecutionResult(CountsDictionary c, std::string name)

Construct from a CountsDictionary, specify the register name.

Parameters:
  • c – the counts

  • name – the register name

ExecutionResult(CountsDictionary c, double e)

Construct from a CountsDictionary and expected value.

Parameters:
  • c – The counts

  • e – The precomputed expected value

ExecutionResult(const ExecutionResult &other)

Copy constructor.

Parameters:

other

ExecutionResult &operator=(const ExecutionResult &other)

Set this ExecutionResult equal to the provided one.

Parameters:

other

Returns:

bool operator==(const ExecutionResult &result) const

Return true if the given ExecutionResult is the same as this one.

Parameters:

result

Returns:

void appendResult(std::string bitString, std::size_t count)

Append the bitstring and count to this ExecutionResult

Parameters:
  • bitString

  • count

Public Members

std::string registerName = GlobalRegisterName

Register name for the classical bits.

std::vector<std::string> sequentialData

Sequential bit strings observed (not collated into a map)

class sample_result

The sample_result abstraction wraps a set of ExecutionResults for a single quantum kernel execution under the sampling or observation ExecutionContext. Each ExecutionResult is mapped to a register name, with a default ExecutionResult with name global representing the observed measurement results holistically for the quantum kernel.

Public Functions

sample_result() = default

Nullary constructor.

sample_result(ExecutionResult &&result)

The constructor, sets the global sample result.

sample_result(ExecutionResult &result)

The constructor, sets the global sample result.

Parameters:

result

sample_result(std::vector<ExecutionResult> &results)

The constructor, appends all provided ExecutionResults.

sample_result(double preComputedExp, std::vector<ExecutionResult> &results)

The constructor, takes a precomputed expectation value and stores it with the __global__ ExecutionResult.

sample_result(const sample_result&)

Copy Constructor.

~sample_result() = default

The destructor.

bool has_expectation(const std::string_view registerName = GlobalRegisterName) const

Return true if the ExecutionResult with the specified register name has a precomputed expectation value.

void append(ExecutionResult &result)

Add another ExecutionResult to this sample_result.

Parameters:

result

std::vector<std::string> register_names() const

Return all register names. Can be used in tandem with sample_result::to_map(regName : string) to retrieve the counts for each register.

Returns:

sample_result &operator=(sample_result &counts)

Set this sample_result equal to the provided one.

Parameters:

counts

Returns:

sample_result &operator+=(const sample_result &other)

Append all the data from other to this sample_result. Merge when necessary.

Parameters:

other

Returns:

std::vector<std::size_t> serialize() const

Serialize this sample_result. See ExecutionResult::serialize() documentation for information.

Returns:

void deserialize(std::vector<std::size_t> &data)

Create this sample_result from the serialized data.

Parameters:

data

bool operator==(const sample_result &counts) const

Return true if this sample_result is the same as the given one.

Parameters:

counts

Returns:

double expectation(const std::string_view registerName = GlobalRegisterName) const

Return the expected value <Z…Z>

Returns:

double exp_val_z(const std::string_view registerName = GlobalRegisterName)

Deprecated: Return the expected value <Z…Z>

double probability(std::string_view bitString, const std::string_view registerName = GlobalRegisterName) const

Return the probability of observing the given bit string.

Parameters:

bitString

Returns:

std::string most_probable(const std::string_view registerName = GlobalRegisterName)

Return the most probable bit string.

Parameters:

registerName

Returns:

std::size_t count(std::string_view bitString, const std::string_view registerName = GlobalRegisterName)

Return the number of times the given bitstring was observed.

Parameters:

bitString

Returns:

std::size_t size(const std::string_view registerName = GlobalRegisterName) noexcept

Return the number of observed bit strings.

Returns:

void dump()

Dump this sample_result to standard out.

void dump(std::ostream &os)

Dump this sample_result to the given output stream.

void clear()

Clear this sample_result.

CountsDictionary to_map(const std::string_view registerName = GlobalRegisterName) const

Extract the ExecutionResults as a std::unordered<string, size_t> map.

Parameters:

registerName

Returns:

inline sample_result get_marginal(const std::vector<std::size_t> &&marginalIndices, const std::string_view registerName = GlobalRegisterName)

Extract marginal counts, that is those counts for a subset of measured qubits.

Parameters:
  • marginalIndices – The qubit indices as an rvalue

  • registerName

Returns:

sample_result get_marginal(const std::vector<std::size_t> &marginalIndices, const std::string_view registerName = GlobalRegisterName)

Extract marginal counts, that is those counts for a subset of measured qubits.

Parameters:
  • marginalIndices – The qubit indices as an reference

  • registerName

Returns:

void reorder(const std::vector<std::size_t> &index, const std::string_view registerName = GlobalRegisterName)

Reorder the bits in an ExecutionResult.

Parameters:
  • index – Vector of indices such that newBitStr(:)=oldBitStr(index(:))

  • registerName – register name to process (defaults to global)

CountsDictionary::iterator begin()

Range-based iterator begin function.

Returns:

CountsDictionary::iterator end()

Range-based iterator end function.

Returns:

CountsDictionary::const_iterator cbegin() const

Range-based constant iterator begin function.

Returns:

CountsDictionary::const_iterator cend() const

Range-based constant iterator end function.

Returns:

inline CountsDictionary::const_iterator begin() const

Range-based constant iterator begin function.

Returns:

inline CountsDictionary::const_iterator end() const

Range-based constant iterator end function.

Returns:

Public Static Functions

static bool has_even_parity(std::string_view bitString)

Return true if the bit string has even parity.

Parameters:

bitString

Returns:

using cudaq::State = std::tuple<std::vector<std::size_t>, std::vector<std::complex<double>>>
template<typename T>
class RegisteredType

RegisteredType allows interface types to declare themselves as plugin interfaces. Used as follows class MyInterface : public RegisteredType<MyInterface> {…};.

class complex_matrix

The complex_matrix provides an abstraction for describing a matrix with N rows and M columns containing complex elements.

Public Functions

complex_matrix(const std::size_t rows, const std::size_t cols)

Create a matrix of the given sizes, all elements initialized to 0.0. The complex_matrix owns the matrix data and will delete it upon destruction.

complex_matrix(value_type *rawData, const std::size_t rows, const std::size_t cols)

Create a matrix from an existing data pointer. The complex_matrix does not own this memory and will not delete it upon destruction.

value_type *data() const

Return the internal data representation.

inline std::size_t rows() const

Return the number of rows.

inline std::size_t cols() const

Return the number of columns.

complex_matrix operator*(complex_matrix &other) const

Multiply this matrix with the provided other matrix. This does not modify this matrix but instead returns a new matrix value.

complex_matrix operator*(std::vector<value_type> &other) const

Multiply this matrix by a vector (A*x) such that x is provided as a std vector of the correct size.

value_type &operator()(std::size_t i, std::size_t j) const

Return the element at the row i and column j.

value_type minimal_eigenvalue() const

Return the minimal eigenvalue for this matrix.

std::vector<value_type> eigenvalues() const

Return this matrix’s eigenvalues.

complex_matrix eigenvectors() const

Return the eigenvectors of this matrix. They are returned as the columns of a new matrix.

void set_zero()

Set all elements in this matrix to 0.0.

void dump(std::ostream &os)

Print this matrix to the given output stream.

void dump()

Print this matrix to standard out.

class Trace

A trace is a circuit representation of the executed computation, as seen by the execution manager. (Here, a circuit is represented as a list of instructions on qudits). Since the execution manager cannot “see” control flow, the trace of a kernel with control flow represents a single execution path, and thus two calls to the same kernel might produce traces.

template<typename QuantumKernel, typename ...Args>
std::string cudaq::draw(QuantumKernel &&kernel, Args&&... args)

Returns a drawing of the execution path, i.e., the trace, of the kernel. The drawing is a UTF-8 encoded string.

Usage:

#include <cudaq.h>
#include <cudaq/algorithms/draw.h>
#include <iostream>

auto bell_pair = []() __qpu__ {
    cudaq::qvector q(2);
    h(q[0]);
    x<cudaq::ctrl>(q[0], q[1]);
    mz(q);
};
...
std::cout << cudaq::draw(bell_pair);
/* Output:
     ╭───╮     
q0 : ┤ h ├──●──
     ╰───╯╭─┴─╮
q1 : ─────┤ x ├
          ╰───╯
*/

auto kernel = [](float angle) __qpu__ {
  cudaq::qvector q(1);
  h(q[0]);
  ry(angle, q[0]);
};
...
std::cout << cudaq::draw(kernel, 0.59);
/* Output:
     ╭───╮╭──────────╮
q0 : ┤ h ├┤ ry(0.59) ├
     ╰───╯╰──────────╯
*/      

Parameters:
  • kernel – The quantum callable with non-trivial function signature.

  • args – The arguments required for evaluation of the quantum kernel.

Returns:

The UTF-8 encoded string of the circuit, without measurement operations.

class Resources

The Resources type encodes information regarding the currently executing kernel’s resource usage. This includes number and type of quantum operation, circuit depth, etc.

using cudaq::complex_matrix::value_type = std::complex<double>

Noise Modeling

using cudaq::complex = std::complex<double>
struct kraus_op

A kraus_op represents a single Kraus operation, described as a complex matrix of specific size. The matrix is represented here as a 1d array (specifically a std::vector).

Public Functions

kraus_op(const kraus_op&) = default

Copy constructor.

inline kraus_op(std::vector<complex> d)

Constructor, initialize from vector data.

template<typename T>
inline kraus_op(std::initializer_list<T> &&initList)

Constructor, initialize from initializer_list.

kraus_op &operator=(const kraus_op &other)

Set this kraus_op equal to the other.

kraus_op adjoint()

Return the adjoint of this kraus_op.

Public Members

std::vector<std::complex<double>> data

Matrix data, represented as a 1d flattened.

std::size_t nRows = 0

The number of rows in the matrix.

std::size_t nCols = 0

The number of columns in the matrix NOTE we currently assume nRows == nCols.

class kraus_channel

A kraus_channel represents a quantum noise channel on specific qubits. The action of the noise channel is described by a vector of Kraus operations - matrices with size equal to 2**nQubits x 2**nQubits, where the number of qubits is the number of provided qubit indices at construction.

Subclassed by cudaq::amplitude_damping_channel, cudaq::bit_flip_channel, cudaq::depolarization_channel, cudaq::phase_flip_channel

Public Functions

kraus_channel() = default

The nullary constructor.

kraus_channel(const kraus_channel &other)

The copy constructor.

Parameters:

other

template<typename ...T>
inline kraus_channel(std::initializer_list<T>&&... inputLists)

The constructor, initializes kraus_ops internally from the provided initializer_lists.

kraus_channel(std::vector<kraus_op> &ops)

The constructor, take qubits and channel kraus_ops as lvalue reference.

inline kraus_channel(std::vector<kraus_op> &&ops)

The constructor, take qubits and channel kraus_ops as rvalue reference.

std::size_t size() const

Return the number of kraus_ops that make up this channel.

bool empty() const

Return true if there are no ops in this channel.

kraus_op &operator[](const std::size_t idx)

Return the kraus_op at the given index.

kraus_channel &operator=(const kraus_channel &other)

Set this kraus_channel equal to the given one.

std::vector<kraus_op> get_ops()

Return all kraus_ops in this channel.

void push_back(kraus_op op)

Add a kraus_op to this channel.

class amplitude_damping_channel : public cudaq::kraus_channel

amplitude_damping_channel is a kraus_channel that automates the creation of the kraus_ops that make up a single-qubit amplitude damping error channel.

class bit_flip_channel : public cudaq::kraus_channel

bit_flip_channel is a kraus_channel that automates the creation of the kraus_ops that make up a single-qubit bit flipping error channel.

class phase_flip_channel : public cudaq::kraus_channel

phase_flip_channel is a kraus_channel that automates the creation of the kraus_ops that make up a single-qubit phase flip error channel.

class depolarization_channel : public cudaq::kraus_channel

depolarization_channel is a kraus_channel that automates the creation of the kraus_ops that make up a single-qubit depolarization error channel.

class noise_model

The noise_model type keeps track of a set of kraus_channels to be applied after the execution of quantum operations. Each quantum operation maps to a Kraus channel containing a number of kraus_ops to be applied to the density matrix representation of the state.

Public Functions

noise_model() = default

default constructor

inline bool empty() const

Return true if there are no kraus_channels in this noise model.

Returns:

void add_channel(const std::string &quantumOp, const std::vector<std::size_t> &qubits, const kraus_channel &channel)

Add the Kraus channel to the specified one-qubit quantum operation. It applies to the quantumOp operation for the specified qubits in the kraus_channel.

template<typename ...QuantumOp>
inline void add_channel(const std::vector<std::size_t> &qubits, const kraus_channel &channel)

Add the provided kraus_channel to all specified quantum operations.

std::vector<kraus_channel> get_channels(const std::string &quantumOp, const std::vector<std::size_t> &qubits) const

Return relevant kraus_channels on the specified qubits for.

template<typename QuantumOp>
inline std::vector<kraus_channel> get_channels(const std::vector<std::size_t> &qubits) const

Get all kraus_channels on the given qubits.

Kernel Builder

template<typename ...Args>
class kernel_builder : public cudaq::details::kernel_builder_base

Public Functions

inline kernel_builder(std::vector<details::KernelBuilderType> &types)

The constructor, takes the input KernelBuilderTypes which is used to create the MLIR function type.

inline auto &getArguments()

Return the QuakeValue arguments.

inline bool isArgStdVec(std::size_t idx)

Return true if the argument to the kernel is a std::vector, false otherwise.

inline std::string name()

Return the name of this kernel.

inline std::size_t getNumParams()

Return the number of function arguments.

Returns:

inline QuakeValue qalloc()

Return a QuakeValue representing the allocated qubit.

inline QuakeValue qalloc(const std::size_t nQubits)

Return a QuakeValue representing the allocated QVec.

inline QuakeValue qalloc(QuakeValue size)

Return a QuakeValue representing the allocated Veq, size is from a pre-allocated size QuakeValue or BlockArgument.

inline QuakeValue constantVal(double val)

Return a QuakeValue representing the constant floating-point value.

inline void swap(const QuakeValue &first, const QuakeValue &second)

SWAP operation for swapping the quantum states of two qubits.

template<typename mod, typename = typename std::enable_if_t<std::is_same_v<mod, cudaq::ctrl>>>
inline void swap(const QuakeValue &control, const QuakeValue &first, const QuakeValue &second)

SWAP operation for performing a Fredkin gate between two qubits, based on the state of input control qubit/s.

template<typename mod, typename = typename std::enable_if_t<std::is_same_v<mod, cudaq::ctrl>>>
inline void swap(const std::vector<QuakeValue> &controls, const QuakeValue &first, const QuakeValue &second)

SWAP operation for performing a Fredkin gate between two qubits, based on the state of an input vector of controls.

class QuakeValue

A QuakeValue is meant to provide a thin wrapper around an mlir::Value instance. These QuakeValues represent handles to function arguments and return values from MLIR Operations, specifically Quake Dialect operations. The QuakeValue also exposes and algebraic API enabling one to negate, add, subtract, and multiply QuakeValues with each other as well as with primitive arithmetic types, e.g. double.

Public Functions

mlir::Value getValue() const

Return the actual MLIR Value.

QuakeValue(mlir::ImplicitLocOpBuilder &builder, mlir::Value v)

The constructor, takes the builder and the value to wrap.

QuakeValue(mlir::ImplicitLocOpBuilder &builder, double v)

The constructor, takes the builder and a constant double value, which will map to an arith::ConstantFloatOp Value.

void dump()

Dump the QuakeValue to standard out.

void dump(std::ostream&)

Dump the QuakeValue to the given output stream.

inline bool canValidateNumElements()

Return true if this QuakeValue of StdVecType can validate its number of unique elements. We cannot do this in the case of QuakeValue extractions within for loops where we do not know the bounds of the loop.

QuakeValue slice(const std::size_t startIdx, const std::size_t count)

For a subscriptable QuakeValue, extract a sub set of the elements starting at the given startIdx and including the following count elements.

QuakeValue size()

For a QuakeValue with type StdVec or Veq, return the size QuakeValue.

std::optional<std::size_t> constantSize()

Return the constant size of this QuakeValue if it is of Veq type.

bool isStdVec()

Return true if this QuakeValue is of type StdVec.

Returns:

std::size_t getRequiredElements()

For a QuakeValue of type StdVec, return the number of required elements, i.e. the number of unique extractions observed.

QuakeValue operator[](const std::size_t idx)

Return a new QuakeValue when the current value is indexed, specifically for QuakeValues of type StdVecType and VeqType.

QuakeValue operator[](const QuakeValue &idx)

Return a new QuakeValue when the current value is indexed, specifically for QuakeValues of type StdVecType and VeqType.

QuakeValue operator-() const

Return the negation of this QuakeValue.

QuakeValue operator*(const double)

Multiply this QuakeValue by the given double.

QuakeValue operator*(QuakeValue other)

Multiply this QuakeValue by the given QuakeValue.

QuakeValue operator/(const double)

Divide this QuakeValue by the given double.

QuakeValue operator/(QuakeValue other)

Divide this QuakeValue by the given QuakeValue.

QuakeValue operator+(const double)

Add this QuakeValue with the given double.

QuakeValue operator+(const int)

Add this QuakeValue with the given int.

QuakeValue operator+(QuakeValue other)

Add this QuakeValue with the given QuakeValue.

QuakeValue operator-(const double)

Subtract the given double from this QuakeValue.

QuakeValue operator-(const int)

Subtract the given int from this QuakeValue.

QuakeValue operator-(QuakeValue other)

Subtract the given QuakeValue from this QuakeValue.

QuakeValue inverse() const

Return the inverse (1/x) of this QuakeValue.

class kernel_builder_base

The kernel_builder_base provides a base type for the templated kernel builder so that we can get a single handle on an instance within the runtime.

Subclassed by cudaq::kernel_builder< Args >

Friends

inline friend std::ostream &operator<<(std::ostream &stream, const kernel_builder_base &builder)

Write the kernel_builder to the given output stream. This outputs the Quake representation.

class KernelBuilderType

The kernel_builder::Type allows us to track input C++ types representing the quake function argument types in a way that does not expose MLIR Type to the CUDA Quantum code. This type keeps track of a functor that generates the MLIR Type in implementation code when create() is invoked.

Public Functions

KernelBuilderType(std::function<mlir::Type(mlir::MLIRContext *ctx)> &&f)

The constructor, take the Type generation functor.

mlir::Type create(mlir::MLIRContext *ctx)

Create the MLIR Type.

Algorithms

class optimizer

The cudaq::optimizer provides a high-level interface for general optimization of user-specified objective functions. This is meant to serve an interface for clients working with concrete subtypes providing specific optimization algorithms possibly delegating to third party libraries. This interface provides an optimize(…) method that takes the number of objective function input parameters (the dimension), and a user-specified objective function that takes the function input parameters as a immutable (const) vector<double> reference and a mutable vector<double> reference modeling the current iteration gradient vector (dF / dx_i, for all i parameters). This function must return a scalar double, the value of this function at the current input parameters. The optimizer also exposes a method for querying whether the current optimization strategy requires gradients or not. Parameterizing optimization strategies is left as a task for sub-types (things like initial parameters, max function evaluations, etc.).

cudaq::optimizers::cobyla opt;
assert(!opt.requiresGradients() && "Cobyla algo does not use gradients.");
auto [opt_val, opt_params] = opt.optimize(2,
              [&](const std::vector<double>& x, std::vector<double>& dx) {
                  ... use x, modify dx, return scalar double ...
              }
            );

Public Functions

virtual bool requiresGradients() = 0

Returns true if this optimization strategy requires gradients to achieve its optimization goals.

virtual optimization_result optimize(const int dim, optimizable_function &&opt_function) = 0

Run the optimization strategy defined by concrete sub-type implementations. Takes the number of variational parameters, and a custom objective function that takes the function input parameters as a immutable (const) vector<double> reference and a mutable vector<double> reference modeling the current iteration gradient vector (dF / dx_i, for all i parameters). This function must return a scalar double, the value of this function at the current input parameters.

class optimizable_function

An optimizable_function wraps a user-provided objective function to be optimized.

using cudaq::optimization_result = std::tuple<double, std::vector<double>>

Typedef modeling the result of an optimization strategy, a double representing the optimal value and the corresponding optimal parameters.

class state

The cudaq::state encapsulate backend simulation state vector or density matrix data.

Public Functions

inline state(State d)

The constructor, takes the simulation data.

inline state()

Default constructor (empty state)

std::complex<double> operator[](std::size_t idx)

Return the data element at the given indices.

void dump()

Dump the state to standard out.

std::vector<std::size_t> get_shape()

Return the dimensions of the state vector or density matrix.

std::complex<double> *get_data()

Return the raw quantum state data.

double overlap(state &other)

Compute the overlap of this state with the other one.

class gradient

The cudaq::gradient represents a base type for all gradient strategies leveraged by variational algorithms.

The cudaq::gradient tracks a std::function with signature void(std::vector<double>) representing the parameterized kernel ansatz. For ansatzes that do not follow this signature, a separate Argument Mapper must be provided which takes std::vector<double> to a tuple of custom function arguments. All gradient subtypes should inherit the base class constructors (using gradient::gradient), but provide a concrete implementation of gradient::compute(). The compute method takes as input the current iteration parameters, a reference to the gradient vector which compute() must update, the cudaq::spin_op for this variational algorithm, and the expected value of the spin_op at the current iteration’s parameters. Subtypes can leverage the protected gradient::getExpectedValue() method to compute <psi(x) | H | psi(x)> at the provided set of variational parameters.

Subclassed by cudaq::gradients::central_difference, cudaq::gradients::forward_difference, cudaq::gradients::parameter_shift

Public Functions

inline gradient(std::function<void(std::vector<double>)> &&kernel)

Constructor, takes the quantum kernel with prescribed signature.

gradient() = default

Empty constructor.

template<typename KernelT, typename ArgsMapper>
inline gradient(KernelT &kernel, ArgsMapper &&argsMapper)

Constructor, takes a callable with non-standard signature the Argument Mapper function object that maps the parameters to concrete arguments for the quantum kernel.

template<typename KernelT>
inline gradient(KernelT &kernel)

Constructor, takes a callable that must have the prescribed call signature (void(std::vector<double>))

template<typename QuantumKernel, typename ArgsMapper>
inline gradient(QuantumKernel &&kernel, ArgsMapper &&argsMapper)

Constructor, takes the quantum kernel with non-standard signature the Argument Mapper function object that maps the parameters to concrete arguments for the quantum kernel.

virtual void compute(const std::vector<double> &x, std::vector<double> &dx, const spin_op &h, double funcAtX) = 0

Compute the current iterations gradient vector and update the provided vector<double reference (dx).

virtual std::vector<double> compute(const std::vector<double> &x, const std::function<double(std::vector<double>)> &func, double funcAtX) = 0

Compute the gradient vector for the provided objective function, func, at the given set of parameters, x.

class central_difference : public cudaq::gradient

Public Functions

inline virtual void compute(const std::vector<double> &x, std::vector<double> &dx, const spin_op &h, double exp_h) override

Compute the current iterations gradient vector and update the provided vector<double reference (dx).

inline virtual std::vector<double> compute(const std::vector<double> &x, const std::function<double(std::vector<double>)> &func, double funcAtX) override

Compute the central_difference gradient for the arbitrary function, func, passed in by the user.

inline gradient(std::function<void(std::vector<double>)> &&kernel)

Constructor, takes the quantum kernel with prescribed signature.

gradient() = default

Empty constructor.

template<typename KernelT, typename ArgsMapper>
inline gradient(KernelT &kernel, ArgsMapper &&argsMapper)

Constructor, takes a callable with non-standard signature the Argument Mapper function object that maps the parameters to concrete arguments for the quantum kernel.

template<typename KernelT>
inline gradient(KernelT &kernel)

Constructor, takes a callable that must have the prescribed call signature (void(std::vector<double>))

template<typename QuantumKernel, typename ArgsMapper>
inline gradient(QuantumKernel &&kernel, ArgsMapper &&argsMapper)

Constructor, takes the quantum kernel with non-standard signature the Argument Mapper function object that maps the parameters to concrete arguments for the quantum kernel.

class parameter_shift : public cudaq::gradient

Public Functions

inline virtual void compute(const std::vector<double> &x, std::vector<double> &dx, const spin_op &h, double exp_h) override

Compute the current iterations gradient vector and update the provided vector<double reference (dx).

inline virtual std::vector<double> compute(const std::vector<double> &x, const std::function<double(std::vector<double>)> &func, double funcAtX) override

Compute the parameter_shift gradient for the arbitrary function, func, passed in by the user.

inline gradient(std::function<void(std::vector<double>)> &&kernel)

Constructor, takes the quantum kernel with prescribed signature.

gradient() = default

Empty constructor.

template<typename KernelT, typename ArgsMapper>
inline gradient(KernelT &kernel, ArgsMapper &&argsMapper)

Constructor, takes a callable with non-standard signature the Argument Mapper function object that maps the parameters to concrete arguments for the quantum kernel.

template<typename KernelT>
inline gradient(KernelT &kernel)

Constructor, takes a callable that must have the prescribed call signature (void(std::vector<double>))

template<typename QuantumKernel, typename ArgsMapper>
inline gradient(QuantumKernel &&kernel, ArgsMapper &&argsMapper)

Constructor, takes the quantum kernel with non-standard signature the Argument Mapper function object that maps the parameters to concrete arguments for the quantum kernel.

class forward_difference : public cudaq::gradient

Compute the first order forward difference approximation for the gradient.

Public Functions

inline virtual void compute(const std::vector<double> &x, std::vector<double> &dx, const spin_op &h, double funcAtX) override

Compute the forward_difference gradient.

inline virtual std::vector<double> compute(const std::vector<double> &x, const std::function<double(std::vector<double>)> &func, double funcAtX) override

Compute the forward_difference gradient for the arbitrary function, func, passed in by the user.

inline gradient(std::function<void(std::vector<double>)> &&kernel)

Constructor, takes the quantum kernel with prescribed signature.

gradient() = default

Empty constructor.

template<typename KernelT, typename ArgsMapper>
inline gradient(KernelT &kernel, ArgsMapper &&argsMapper)

Constructor, takes a callable with non-standard signature the Argument Mapper function object that maps the parameters to concrete arguments for the quantum kernel.

template<typename KernelT>
inline gradient(KernelT &kernel)

Constructor, takes a callable that must have the prescribed call signature (void(std::vector<double>))

template<typename QuantumKernel, typename ArgsMapper>
inline gradient(QuantumKernel &&kernel, ArgsMapper &&argsMapper)

Constructor, takes the quantum kernel with non-standard signature the Argument Mapper function object that maps the parameters to concrete arguments for the quantum kernel.

Platform

class QPU : public cudaq::registry::RegisteredType<QPU>

A CUDA Quantum QPU is an abstraction on the quantum processing unit which executes quantum kernel expressions. The QPU exposes certain information about the QPU being targeting, such as the number of available qubits, the logical ID for this QPU in a set of available QPUs, and its qubit connectivity. The QPU keeps track of an execution queue for enqueuing asynchronous tasks that execute quantum kernel expressions. The QPU also tracks the client-provided execution context to enable quantum kernel related tasks such as sampling and observation.

This type is meant to be subtyped by concrete quantum_platform subtypes.

Subclassed by cudaq::BaseRemoteRESTQPU, cudaq::BaseRemoteSimulatorQPU

Public Functions

inline QPU()

The constructor, initializes the execution queue.

inline QPU(std::size_t _qpuId)

The constructor, sets the current QPU Id and initializes the execution queue

QPU(QPU&&) = default

Move constructor.

virtual ~QPU() = default

The destructor.

inline void setId(std::size_t _qpuId)

Set the current QPU Id.

inline std::thread::id getExecutionThreadId() const

Get id of the thread this QPU’s queue executes on.

inline std::size_t getNumQubits()

Return the number of qubits.

inline auto getConnectivity()

Return the qubit connectivity.

inline virtual bool isSimulator()

Is this QPU a simulator ?

inline virtual bool supportsConditionalFeedback()

Return whether this QPU has conditional feedback support.

inline virtual void setShots(int _nShots)

Base class handling of shots is do-nothing, subclasses can handle as they wish

inline virtual bool isEmulated()

Is this a local emulator of a remote QPU?

virtual void enqueue(QuantumTask &task) = 0

Enqueue a quantum task on the asynchronous execution queue.

virtual void setExecutionContext(ExecutionContext *context) = 0

Set the execution context, meant for subtype specification.

virtual void resetExecutionContext() = 0

Reset the execution context, meant for subtype specification.

virtual void launchKernel(const std::string &name, void (*kernelFunc)(void*), void *args, std::uint64_t, std::uint64_t) = 0

Launch the kernel with given name (to extract its Quake representation). The raw function pointer is also provided, as are the runtime arguments, as a struct-packed void pointer and its corresponding size.

inline virtual void onRandomSeedSet(std::size_t seed)

Notify the QPU that a new random seed value is set. By default do nothing, let subclasses override.

class BaseRemoteRESTQPU : public cudaq::QPU
class BaseRemoteSimulatorQPU : public cudaq::QPU

Subclassed by cudaq::BaseNvcfSimulatorQPU

class BaseNvcfSimulatorQPU : public cudaq::BaseRemoteSimulatorQPU

Implementation of base QPU subtype that submits simulation request to NVCF.

class quantum_platform

The quantum_platform corresponds to a specific quantum architecture. The quantum_platform exposes a public API for programmers to query specific information about the targeted QPU(s) (e.g. number of qubits, qubit connectivity, etc.). This type is meant to be subclassed for concrete realizations of quantum platforms, which are intended to populate this platformQPUs member of this base class.

Public Functions

std::optional<QubitConnectivity> connectivity()

Fetch the connectivity info.

std::size_t get_num_qubits()

Get the number of qubits for the current QPU.

inline virtual bool supports_task_distribution() const

Return true if this platform exposes multiple QPUs and supports parallel distribution of quantum tasks.

std::size_t get_num_qubits(std::size_t qpu_id)

Get the number of qubits for the QPU with ID qpu_id.

inline std::optional<int> get_shots()

Getter for the shots. This will be deprecated once set_shots and clear_shots are removed.

inline virtual void set_shots(int numShots)

Setter for the shots.

inline virtual void clear_shots()

Reset shots.

void set_exec_ctx(cudaq::ExecutionContext *ctx, std::size_t qpu_id = 0)

Specify the execution context for this platform.

inline ExecutionContext *get_exec_ctx() const

Return the current execution context.

void reset_exec_ctx(std::size_t qpu_id = 0)

Reset the execution context for this platform.

inline std::size_t num_qpus() const

Get the number of QPUs available with this platform.

bool is_simulator(const std::size_t qpu_id = 0) const

Return whether this platform is simulating the architecture.

bool supports_conditional_feedback(const std::size_t qpu_id = 0) const

Return whether the QPU has conditional feedback support.

inline std::string name() const

The name of the platform, which also corresponds to the name of the platform file.

std::size_t get_current_qpu()

Get the ID of the current QPU.

void set_current_qpu(const std::size_t device_id)

Set the current QPU via its device ID.

bool is_remote(const std::size_t qpuId = 0)

Return true if the QPU is remote.

bool is_emulated(const std::size_t qpuId = 0) const

Return true if QPU is locally emulating a remote QPU.

void set_noise(const noise_model *model)

Set the noise model for future invocations of quantum kernels.

void reset_noise()

Turn off any noise models.

std::future<sample_result> enqueueAsyncTask(const std::size_t qpu_id, KernelExecutionTask &t)

Enqueue an asynchronous sampling task.

void enqueueAsyncTask(const std::size_t qpu_id, std::function<void()> &f)

Enqueue a general task that runs on the specified QPU.

inline virtual void setTargetBackend(const std::string &name)

Set the target backend, by default do nothing, let subclasses override.

Parameters:

name

virtual void onRandomSeedSet(std::size_t seed)

Called by the runtime to notify that a new random seed value is set.

Public Static Functions

static std::vector<std::string> list_platforms()

List all available platforms.

using cudaq::QuantumTask = std::function<void()>

The QuantumTask is ultimately what gets added to the execution queue. It is meant to wrap any Sampling or Observe task with an appropriate std::promise instance being provided and set.

using cudaq::QubitConnectivity = std::vector<QubitEdge>
using cudaq::QubitEdge = std::pair<std::size_t, std::size_t>

Typedefs for defining the connectivity structure of a QPU.

using cudaq::KernelExecutionTask = std::function<sample_result()>

A sampling tasks takes no input arguments and returns a sample_result instance.

Utilities

inline std::vector<std::size_t> cudaq::range(std::size_t N)

Return a vector of unsigned integers. The first element is zero, and the remaining elements are all values incremented by 1 to the total size value provided (exclusive).

Namespaces

namespace cudaq
int cudaq::num_available_gpus()

The number of available GPUs.

void cudaq::set_random_seed(std::size_t seed)

Set a seed for any random number generators used in backend simulations.

void cudaq::set_noise(const cudaq::noise_model &model)

Set a custom noise model for simulation. The caller must also call cudaq::unset_noise before model gets deallocated or goes out of scope.

void cudaq::unset_noise()

Remove an existing noise model from simulation.

namespace details
namespace registry
namespace mpi
void cudaq::mpi::initialize()

Initialize MPI if available. This function is a no-op if there CUDA Quantum has not been built against MPI.

void cudaq::mpi::initialize(int argc, char **argv)

Initialize MPI if available. This function is a no-op if there CUDA Quantum has not been built against MPI. Takes program arguments as input.

bool cudaq::mpi::is_initialized()

Return true if MPI is already initialized, false otherwise.

void cudaq::mpi::finalize()

Finalize MPI. This function is a no-op if there CUDA Quantum has not been built against MPI.

int cudaq::mpi::rank()

Return the rank of the calling process.

int cudaq::mpi::num_ranks()

Return the number of MPI ranks.

void cudaq::mpi::all_gather(std::vector<double> &global, const std::vector<double> &local)

Gather all vector data (floating point numbers) locally into the provided global vector.

Global vector must be sized to fit all vector elements coming from individual ranks.

void cudaq::mpi::all_gather(std::vector<int> &global, const std::vector<int> &local)

Gather all vector data (integers) locally into the provided global vector.

Global vector must be sized to fit all vector elements coming from individual ranks.

template<typename T, typename Func>
T cudaq::mpi::all_reduce(const T&, const Func&)
template<typename T, typename BinaryFunction>
T cudaq::mpi::all_reduce(const T &localValue, const BinaryFunction &function)

Reduce all values across ranks with the specified binary function.

void cudaq::mpi::broadcast(std::vector<double> &data, int rootRank)

Broadcast a vector from a process (rootRank) to all other processes.

void cudaq::mpi::broadcast(std::string &data, int rootRank)

Broadcast a string from a process (rootRank) to all other processes.