Namespace dd¶
-
namespace dd¶
Typedefs
-
template<typename T>
using isMatrixVariant = std::enable_if_t<std::is_same_v<T, mNode> || std::is_same_v<T, dNode>, bool>¶
-
using Qubit = std::uint16_t¶
Integer type used for indexing qubits.
std::uint16_tcan address up to 65536 qubits as [0, …, 65535].Note
If you need even more qubits, this can be increased to
std::uint32_t. Beware of the increased memory footprint of matrix nodes.
-
using fp = double¶
Floating point type to use for computations.
Note
Adjusting the precision might lead to unexpected results.
-
using SparseCMat = std::unordered_map<std::pair<std::size_t, std::size_t>, std::complex<fp>, PairHash>¶
-
using vCachedEdge = CachedEdge<vNode>¶
-
using mCachedEdge = CachedEdge<mNode>¶
-
using dCachedEdge = CachedEdge<dNode>¶
-
using ArrayOfEdges = std::array<dCachedEdge, NrEdges::value>¶
Enums
-
enum class BasisStates : std::uint8_t¶
Values:
-
enumerator zero¶
-
enumerator one¶
-
enumerator plus¶
-
enumerator minus¶
-
enumerator right¶
-
enumerator left¶
-
enumerator zero¶
Functions
-
ApproximationMetadata approximate(VectorDD &state, double fidelity, Package &dd)¶
Approximate the
statebased on fidelity. The fidelity of the approximated state will be at leastfidelity.Traverses the decision diagram layer by layer in a breadth-first manner (iterative deepening algorithm) and eliminates edges greedily until the budget (1 -
fidelity) is exhausted.- Parameters:
state – The DD to approximate.
fidelity – The desired minimum fidelity after approximation.
dd – The DD package to use for the approximation.
- Returns:
Metadata about the approximation.
-
template<class Node>
CachedEdge(Node*, const ComplexValue&) -> CachedEdge<Node>¶
-
template<class Node>
CachedEdge(Node*, const Complex&) -> CachedEdge<Node>¶
-
std::ostream &operator<<(std::ostream &os, const Complex &c)¶
Print a complex number to a stream.
- Parameters:
os – The output stream to write to.
c – The complex number to print.
- Returns:
The output stream.
-
ComplexValue operator*(const Complex &c1, const ComplexValue &c2)¶
-
ComplexValue operator*(const ComplexValue &c1, const Complex &c2)¶
-
ComplexValue operator*(const Complex &c1, const Complex &c2)¶
-
ComplexValue operator*(const Complex &c1, fp real)¶
-
ComplexValue operator*(fp real, const Complex &c1)¶
-
ComplexValue operator/(const Complex &c1, const ComplexValue &c2)¶
-
ComplexValue operator/(const ComplexValue &c1, const Complex &c2)¶
-
ComplexValue operator/(const Complex &c1, const Complex &c2)¶
-
ComplexValue operator/(const Complex &c1, fp real)¶
-
ComplexValue operator+(const ComplexValue &c1, const ComplexValue &c2)¶
-
ComplexValue operator*(const ComplexValue &c1, fp r)¶
-
ComplexValue operator*(fp r, const ComplexValue &c1)¶
-
ComplexValue operator*(const ComplexValue &c1, const ComplexValue &c2)¶
-
ComplexValue operator/(const ComplexValue &c1, fp r)¶
-
ComplexValue operator/(const ComplexValue &c1, const ComplexValue &c2)¶
-
std::ostream &operator<<(std::ostream &os, const ComplexValue &c)¶
Print a complex value to the given output stream.
- Parameters:
os – The output stream to write to.
c – The complex value to print.
- Returns:
The output stream.
-
static std::string intToBinaryString(const std::size_t value, const std::size_t nbits)¶
Converts a decimal number to a binary string (big endian)
- Parameters:
value – The decimal number to convert
nbits – The number of bits to use for the binary representation
- Returns:
The binary representation of the decimal number
-
constexpr std::size_t murmur64(std::size_t k) noexcept¶
64bit mixing hash (from MurmurHash3)
Hash function for 64bit integers adapted from MurmurHash3
- Parameters:
k – the number to hash
- Returns:
the hash value
-
template<class Node>
static std::ostream &header(const Edge<Node> &e, std::ostream &os, bool edgeLabels, bool formatAsPolar = true)¶
-
template<class Node>
static std::ostream &coloredHeader(const Edge<Node> &e, std::ostream &os, bool edgeLabels, bool formatAsPolar = true)¶
-
template<class Node>
static std::ostream &memoryHeader(const Edge<Node> &e, std::ostream &os, bool edgeLabels)¶
-
std::ostream &bwEdge(const mEdge &from, const mEdge &to, std::uint16_t idx, std::ostream &os, bool edgeLabels = false, bool classic = false, bool formatAsPolar = true)¶
-
std::ostream &bwEdge(const vEdge &from, const vEdge &to, std::uint16_t idx, std::ostream &os, bool edgeLabels = false, bool classic = false, bool formatAsPolar = true)¶
-
std::ostream &coloredEdge(const mEdge &from, const mEdge &to, std::uint16_t idx, std::ostream &os, bool edgeLabels = false, bool classic = false, bool formatAsPolar = true)¶
-
std::ostream &coloredEdge(const vEdge &from, const vEdge &to, std::uint16_t idx, std::ostream &os, bool edgeLabels = false, bool classic = false, bool formatAsPolar = true)¶
-
template<class Node>
static std::ostream &memoryEdge(const Edge<Node> &from, const Edge<Node> &to, std::uint16_t idx, std::ostream &os, bool edgeLabels = false)¶
-
template<class Node>
static void toDot(const Edge<Node> &e, std::ostream &os, bool colored = true, bool edgeLabels = false, bool classic = false, bool memory = false, bool formatAsPolar = true)¶
-
template<class Node>
static void export2Dot(Edge<Node> basic, const std::string &outputFilename, bool colored = true, bool edgeLabels = false, bool classic = false, bool memory = false, bool show = true, bool formatAsPolar = true)¶
-
void serialize(const vEdge &basic, std::ostream &os, bool writeBinary = false)¶
Serialization Note: do not rely on the binary format being portable across different architectures/platforms
-
void serializeMatrix(const mEdge &basic, std::int64_t &idx, std::unordered_map<mNode*, std::int64_t> &nodeIndex, std::unordered_set<mNode*> &visited, std::ostream &os, bool writeBinary = false)¶
-
template<class Node>
static void serialize(const Edge<Node> &basic, const std::string &outputFilename, bool writeBinary = false)¶
-
MatrixDD buildFunctionality(const qc::QuantumComputation &qc, Package &dd)¶
Sequentially build a decision diagram representation for the functionality of a purely-quantum qc::QuantumComputation.
For a circuit \(G\) with \(|G|\) gates \(g_0, g_1, \ldots, g_{|G|-1}\), the functionality of \(G\) is defined as the unitary matrix \(U\) such that
where \(U_i\) is the unitary matrix corresponding to gate \(g_i\). For an \(n\)-qubit quantum computation, \(U\) is a \(2^n \times 2^n\) matrix.\[ U = U_{|G|-1}) \cdot U_{|G|-2} \cdot \ldots \cdot U_1 \cdot U_0, \]By representing every single operation in the circuit as a decision diagram instead of a unitary matrix and performing the matrix multiplication directly using decision diagrams, a representation of the functionality of a quantum computation can oftentimes be computed more efficiently in terms of memory and runtime.
This function effectively computes
by sequentially applying the decision diagrams of the gates in the circuit to the current decision diagram representing the functionality of the quantum computation.\[ DD(U) = DD(g_{|G|-1}) \otimes DD(g_{|G|-2}) \otimes \ldots \otimes DD(g_0) \]- Parameters:
qc – The quantum computation to construct the functionality for
dd – The DD package to use for the construction
- Returns:
The matrix diagram representing the functionality of the quantum computation
-
MatrixDD buildFunctionalityRecursive(const qc::QuantumComputation &qc, Package &dd)¶
Recursively build a decision diagram representation for the functionality of a purely-quantum qc::QuantumComputation.
Instead of sequentially applying the decision diagrams of the gates in the circuit, this function builds a binary computation tree out of the decision diagrams of the gates in the circuit. This results in a recursive pairwise grouping that can be more memory and runtime efficient compared to the sequential approach.
See also
buildFunctionality
See also
- Parameters:
qc – The quantum computation to construct the functionality for
dd – The DD package to use for the construction
- Returns:
The matrix diagram representing the functionality of the quantum computation
-
GateMatrix opToSingleQubitGateMatrix(qc::OpType t, const std::vector<fp> ¶ms = {})¶
Converts a given quantum operation to a single-qubit gate matrix.
- Parameters:
t – The quantum operation to convert
params – The parameters of the quantum operation
- Returns:
The single-qubit gate matrix representation of the quantum operation
-
TwoQubitGateMatrix opToTwoQubitGateMatrix(qc::OpType t, const std::vector<fp> ¶ms = {})¶
Converts a given quantum operation to a two-qubit gate matrix.
- Parameters:
t – The quantum operation to convert
params – The parameters of the quantum operation
- Returns:
The two-qubit gate matrix representation of the quantum operation
-
void sanityCheckOfNoiseProbabilities(double noiseProbability, double amplitudeDampingProb, double multiQubitGateFactor)¶
-
MatrixDD getStandardOperationDD(Package &dd, qc::OpType type, const std::vector<fp> ¶ms, const qc::Controls &controls, const std::vector<qc::Qubit> &targets)¶
Get the decision diagram representation of an operation based on its constituent parts.
Note
This function is only intended for internal use and should not be called directly.
- Parameters:
dd – The DD package to use
type – The operation type
params – The operation parameters
controls – The operation controls
targets – The operation targets
- Returns:
The decision diagram representation of the operation
-
MatrixDD getStandardOperationDD(const qc::StandardOperation &op, Package &dd, const qc::Controls &controls, const std::vector<qc::Qubit> &targets, bool inverse)¶
Get the decision diagram representation of a qc::StandardOperation.
Note
This function is only intended for internal use and should not be called directly.
- Parameters:
op – The operation to get the DD for
dd – The DD package to use
controls – The operation controls
targets – The operation targets
inverse – Whether to get the inverse of the operation
- Returns:
The decision diagram representation of the operation
-
MatrixDD getDD(const qc::Operation &op, Package &dd, const qc::Permutation &permutation = {}, bool inverse = false)¶
Get the decision diagram representation of an operation.
- Parameters:
op – The operation to get the DD for
dd – The DD package to use
permutation – The permutation to apply to the operation’s qubits. An empty permutation marks the identity permutation.
inverse – Whether to get the inverse of the operation
- Returns:
The decision diagram representation of the operation
-
MatrixDD getInverseDD(const qc::Operation &op, Package &dd, const qc::Permutation &permutation = {})¶
Get the decision diagram representation of the inverse of an operation.
See also
getDD
- Parameters:
op – The operation to get the inverse DD for
dd – The DD package to use
permutation – The permutation to apply to the operation’s qubits. An empty permutation marks the identity permutation.
- Returns:
The decision diagram representation of the inverse of the operation
-
VectorDD applyUnitaryOperation(const qc::Operation &op, const VectorDD &in, Package &dd, const qc::Permutation &permutation = {})¶
Apply a unitary operation to a given vector DD.
This is a convenience function that realizes
optimesinand correctly accounts for the permutation of the operation’s qubits as well as automatically handles reference counting.- Parameters:
op – The operation to apply
in – The input DD
dd – The DD package to use
permutation – The permutation to apply to the operation’s qubits. An empty permutation marks the identity permutation.
- Returns:
The output DD
-
MatrixDD applyUnitaryOperation(const qc::Operation &op, const MatrixDD &in, Package &dd, const qc::Permutation &permutation = {}, bool applyFromLeft = true)¶
Apply a unitary operation to a given matrix DD.
This is a convenience function that realizes
optimesinand correctly accounts for the permutation of the operation’s qubits as well as automatically handles reference counting.- Parameters:
op – The operation to apply
in – The input DD
dd – The DD package to use
permutation – The permutation to apply to the operation’s qubits. An empty permutation marks the identity permutation.
applyFromLeft – Whether to apply the operation from the left (true) or from the right (false).
- Returns:
The output DD
-
VectorDD applyMeasurement(const qc::NonUnitaryOperation &op, VectorDD in, Package &dd, std::mt19937_64 &rng, std::vector<bool> &measurements, const qc::Permutation &permutation = {})¶
Apply a measurement operation to a given DD.
This is a convenience function that realizes the measurement
oponinand stores the measurement results inmeasurements. The result is determined based on the RNGrng. The function correctly accounts for the permutation of the operation’s qubits as well as automatically handles reference counting.- Parameters:
op – The measurement operation to apply
in – The input DD
dd – The DD package to use
rng – The random number generator to use
measurements – The vector to store the measurement results in
permutation – The permutation to apply to the operation’s qubits. An empty permutation marks the identity permutation.
- Returns:
The output DD
-
VectorDD applyReset(const qc::NonUnitaryOperation &op, VectorDD in, Package &dd, std::mt19937_64 &rng, const qc::Permutation &permutation = {})¶
Apply a reset operation to a given DD.
This is a convenience function that realizes the reset
oponin. To this end, it measures the qubit and applies an X operation if the measurement result is one. The result is determined based on the RNGrng. The function correctly accounts for the permutation of the operation’s qubits as well as automatically handles reference counting.- Parameters:
op – The reset operation to apply
in – The input DD
dd – The DD package to use
rng – The random number generator to use
permutation – The permutation to apply to the operation’s qubits. An empty permutation marks the identity permutation.
- Returns:
The output DD
-
VectorDD applyIfElseOperation(const qc::IfElseOperation &op, const VectorDD &in, Package &dd, const std::vector<bool> &measurements, const qc::Permutation &permutation = {})¶
Apply an if-else operation to a given DD.
This is a convenience function that realizes the if-else operation
oponin. It applies the underlying operation if the actual value stored in the measurement results matches the expected value according to the comparison kind. The function correctly accounts for the permutation of the operation’s qubits as well as automatically handles reference counting.- Parameters:
op – The if-else operation to apply
in – The input DD
dd – The DD package to use
measurements – The vector of measurement results
permutation – The permutation to apply to the operation’s qubits. An empty permutation marks the identity permutation.
- Returns:
The output DD
-
bool isExecutableVirtually(const qc::Operation &op) noexcept¶
Check whether
opis virtually executable.- Parameters:
op – The operation in question.
- Returns:
Whether
opis virtually executable.
-
void applyVirtualOperation(const qc::Operation &op, qc::Permutation &permutation) noexcept¶
Apply virtual operation
op.- Parameters:
op – The virtual operation to apply.
permutation – If suitable, the to be updated permutation.
-
VectorDD applyGlobalPhase(VectorDD &in, const fp &phase, Package &dd)¶
Apply global phase to a given DD.
- Parameters:
in – The input DD
phase – The phase to apply
dd – The DD package to use
- Returns:
The output DD
-
template<class DDType>
void changePermutation(DDType &on, qc::Permutation &from, const qc::Permutation &to, Package &dd, const bool regular = true)¶ Change the permutation of a given DD.
This function changes the permutation of the given DD
onfromfromtotoby applying SWAP gates. Thefrompermutation must be at least as large as thetopermutation.- Template Parameters:
DDType – The type of the DD
- Parameters:
on – The DD to change the permutation of
from – The current permutation
to – The target permutation
dd – The DD package to use
regular – Whether to apply the permutation from the left (true) or from the right (false)
-
VectorDD simulate(const qc::QuantumComputation &qc, const VectorDD &in, Package &dd)¶
Simulate a purely-quantum qc::QuantumComputation on a given input state using decision diagrams.
This method classically simulates the quantum computation
qcon the input stateinby sequentially applying the operations in the circuit to the initial state via decision diagram multiplication.This simple simulation method can only handle circuits that do not contain any classical control operations or measurements. Its main purpose is to construct a representation of the statevector after simulating the quantum computation for the given input state. For more elaborate simulation methods that can handle classical control and mid-circuit measurements, see sample(const QuantumComputation&,
std::size_t, std::size_t).
- Parameters:
qc – The quantum computation to simulate
in – The input state to simulate. Represented as a vector DD.
dd – The DD package to use for the simulation
- Returns:
A vector DD representing the output state of the simulation
-
std::map<std::string, std::size_t> sample(const qc::QuantumComputation &qc, std::size_t shots = 1024U, std::size_t seed = 0U)¶
Sample from the output distribution of a quantum computation.
This method classically simulates the quantum computation
qcstarting from the all-zero state and samplesshotstimes from the output distribution. The seed for the random number generator can be set usingseed.For a circuit without mid-circuit measurements, this function will construct a representation of the final statevector similar to simulate and then repeatedly sample from the resulting decision diagram, without actually collapsing the state. For a fixed number of qubits, each sample can be drawn in constant time, which is a significant of the decision diagram structure.
For a circuit with mid-circuit measurements, this function will separately execute the circuit for each sample, probabilistically collapsing the state after each measurement.
- Parameters:
qc – The quantum computation to simulate
shots – The number of shots to sample
seed – The seed for the random number generator
- Returns:
A histogram of the measurement results
-
std::map<std::string, std::size_t> sample(const qc::QuantumComputation &qc, const VectorDD &in, Package &dd, std::size_t shots, std::size_t seed = 0U)¶
Sample from the output distribution of a quantum computation.
This is a more general version of sample that allows for choosing the input state to simulate as well as the DD package to use for the simulation.
- Parameters:
qc – The quantum computation to simulate
in – The input state to simulate. Represented as a vector DD.
dd – The DD package to use for the simulation
shots – The number of shots to sample
seed – The seed for the random number generator
- Returns:
A histogram of the measurement results
-
VectorDD makeZeroState(std::size_t n, Package &dd, std::size_t start = 0)¶
Construct the all-zero state \(|0...0\rangle\).
- Parameters:
n – The number of qubits.
dd – The DD package to use for making the vector DD.
start – The starting qubit index. Default is 0.
- Throws:
`std::invalid_argument` –
dd.qubits() < n.- Returns:
A vector DD for the all-zero state.
-
VectorDD makeBasisState(std::size_t n, const std::vector<bool> &state, Package &dd, std::size_t start = 0)¶
Construct a computational basis state \(|b_{n-1}...b_0\rangle\).
- Parameters:
n – The number of qubits.
state – The state to construct.
dd – The DD package to use for making the vector DD.
start – The starting qubit index. Default is 0.
- Throws:
`std::invalid_argument` –
dd.qubits() < norsize(state) < n.- Returns:
A vector DD for the computational basis state.
-
VectorDD makeBasisState(std::size_t n, const std::vector<BasisStates> &state, Package &dd, std::size_t start = 0)¶
Construct a product state out of \(\{0, 1, +, -, R, L\}^{\otimes n}\).
- Parameters:
n – The number of qubits
state – The state to construct.
dd – The DD package to use for making the vector DD.
start – The starting qubit index. Default is 0.
- Throws:
`std::invalid_argument` –
dd.qubits() < norsize(state) < n.- Returns:
A vector DD for the product state.
-
VectorDD makeGHZState(std::size_t n, Package &dd)¶
Construct a GHZ state \(|0...0\rangle + |1...1\rangle\).
- Parameters:
n – The number of qubits.
dd – The DD package to use for making the vector DD.
- Throws:
`std::invalid_argument` –
dd.qubits() < n.- Returns:
A vector DD for the GHZ state.
-
VectorDD makeWState(std::size_t n, Package &dd)¶
Construct a W state.
The W state is defined as
\[ |0...01\rangle + |0...10\rangle + |10...0\rangle \]- Parameters:
n – The number of qubits.
dd – The DD package to use for making the vector DD.
- Throws:
`std::invalid_argument` –
dd.qubits() < nor the number of qubits and currently set tolerance would lead to an underflow.- Returns:
A vector DD for the W state.
-
VectorDD makeStateFromVector(const CVec &vec, Package &dd)¶
Construct a decision diagram from an arbitrary state vector.
- Parameters:
vec – The state vector to convert to a DD.
dd – The DD package to use for making the vector DD.
- Throws:
`std::invalid_argument` –
vec.size()is not a power of two ordd.qubits() < log2(vec.size()) - 1.- Returns:
A vector DD representing the state.
-
VectorDD generateExponentialState(std::size_t levels, Package &dd)¶
Generate exponentially large vector DD.
- Parameters:
levels – The number of levels in the vector DD.
dd – The DD package to use for generating the vector DD.
- Throws:
`std::invalid_argument` –
dd.qubits() < levels.- Returns:
The exponentially large vector DD.
-
VectorDD generateExponentialState(std::size_t levels, Package &dd, std::size_t seed)¶
Generate exponentially large vector DD. Use
seedfor randomization.- Parameters:
levels – The number of levels in the vector DD.
dd – The DD package to use for generating the vector DD.
seed – The seed used for randomization.
- Throws:
`std::invalid_argument` –
dd.qubits() < levels.- Returns:
The exponentially large vector DD.
-
VectorDD generateRandomState(std::size_t levels, const std::vector<std::size_t> &nodesPerLevel, GenerationWireStrategy strategy, Package &dd)¶
Generate random vector DD.
- Parameters:
levels – The number of levels in the vector DD.
nodesPerLevel – The number of nodes per level.
strategy – The strategy to wire two layers.
dd – The DD package to use for generating the vector DD.
- Throws:
`std::invalid_argument` –
dd.qubits() < levels.- Returns:
The random vector DD.
-
VectorDD generateRandomState(std::size_t levels, const std::vector<std::size_t> &nodesPerLevel, GenerationWireStrategy strategy, Package &dd, std::size_t seed)¶
Generate random vector DD. Use
seedfor randomization.- Parameters:
levels – The number of levels in the vector DD.
nodesPerLevel – The number of nodes per level.
strategy – The strategy to wire two layers.
dd – The DD package to use for generating the vector DD.
seed – The seed used for randomization.
- Throws:
`std::invalid_argument` –
dd.qubits() < levels,levels <= 0, ornodesPerLevel.size() != levels.- Returns:
The random vector DD.
-
double computeActiveMemoryMiB(Package &package)¶
Computes an estimate for the memory usage of active DDs.
The estimate is based on the number of active entries which are computed by temporarily marking all nodes reachable from the current root set and subsequently counting them in the unique tables. It accounts for the memory used by DD nodes, DD edges, and real numbers.
- Parameters:
package – The package instance
- Returns:
The estimated memory usage in MiB
-
double computePeakMemoryMiB(const Package &package)¶
Computes an estimate for the peak memory usage of DDs.
The estimate is based on the peak number of used entries in the respective memory managers. It accounts for the memory used by DD nodes, DD edges, and real numbers.
- Parameters:
package – The package instance
- Returns:
The estimated memory usage in MiB
-
nlohmann::json getDataStructureStatistics()¶
Get some key statistics about data structures used by the DD package.
- Returns:
A JSON representation of the statistics
Variables
-
static constexpr std::uint8_t RADIX = 2¶
-
static constexpr auto SQRT2_2 = static_cast<fp>(0.707106781186547524400844362104849039284835937688474036588L)¶
-
static constexpr std::uint64_t SERIALIZATION_VERSION = 1¶
-
constexpr auto STOCHASTIC_NOISE_SIMULATOR_DD_PACKAGE_CONFIG =
[]() { DDPackageConfigconfig{};config.stochasticCacheOps = qc::OpType::OpTypeEnd;config.ctVecAddMagNumBucket = 1U;config.ctMatAddMagNumBucket = 1U;config.ctVecConjNumBucket = 1U;return config;}()¶
-
constexpr auto DENSITY_MATRIX_SIMULATOR_DD_PACKAGE_CONFIG =
[]() { DDPackageConfigconfig{};config.utDmNumBucket = 65536U;config.utDmInitialAllocationSize = 4096U;config.ctDmDmMultNumBucket = 16384U;config.ctDmAddNumBucket = 16384U;config.ctDmNoiseNumBucket = 4096U;config.utMatNumBucket = 16384U;config.ctMatAddNumBucket = 4096U;config.ctVecAddNumBucket = 4096U;config.ctMatConjTransNumBucket = 4096U;config.ctMatMatMultNumBucket = 1U;config.ctMatVecMultNumBucket = 1U;config.utVecNumBucket = 1U;config.utVecInitialAllocationSize = 1U;config.utMatInitialAllocationSize = 1U;config.ctVecKronNumBucket = 1U;config.ctMatKronNumBucket = 1U;config.ctDmTraceNumBucket = 4096U;config.ctMatTraceNumBucket = 1U;config.ctVecInnerProdNumBucket = 1U;config.stochasticCacheOps = 1U;config.ctVecAddMagNumBucket = 1U;config.ctMatAddMagNumBucket = 1U;config.ctVecConjNumBucket = 1U;return config;}()¶
-
constexpr auto UNITARY_SIMULATOR_DD_PACKAGE_CONFIG =
[]() { DDPackageConfigconfig{};config.utMatNumBucket = 65'536U;config.ctMatAddNumBucket = 65'536U;config.ctMatMatMultNumBucket = 65'536U;config.utVecNumBucket = 1U;config.utVecInitialAllocationSize = 1U;config.ctVecAddNumBucket = 1U;config.ctVecAddMagNumBucket = 1U;config.ctMatAddMagNumBucket = 1U;config.ctVecConjNumBucket = 1U;config.ctMatConjTransNumBucket = 1U;config.ctMatVecMultNumBucket = 1U;config.ctVecKronNumBucket = 1U;config.ctMatKronNumBucket = 1U;config.ctMatTraceNumBucket = 1U;config.ctVecInnerProdNumBucket = 1U;return config;}()¶
-
constexpr GateMatrix MEAS_ZERO_MAT = {1, 0, 0, 0}¶
Single-qubit gate matrix for collapsing a qubit to the |0> state.
-
constexpr GateMatrix MEAS_ONE_MAT = {0, 0, 0, 1}¶
Single-qubit gate matrix for collapsing a qubit to the |1> state.
-
struct ApproximationMetadata¶
- #include <Approximation.hpp>
Useful metadata of an approximation run.
-
template<typename Node>
struct CachedEdge¶ - #include <CachedEdge.hpp>
A DD node with a cached edge weight.
Some DD operations create intermediate results that are not part of the final result. To avoid storing these intermediate results in the unique table, they are represented via cached numbers.
- Template Parameters:
Node – Type of the DD node
Public Functions
-
inline bool operator==(const CachedEdge &other) const¶
Comparing two DD edges with another involves comparing the respective pointers and checking whether the corresponding weights are “close enough” according to a given tolerance this notion of equivalence is chosen to counter floating point inaccuracies
-
inline constexpr bool isTerminal() const¶
Check whether this is a terminal.
- Returns:
whether this is a terminal
-
template<typename T = Node, isMatrixVariant<T> = true>
inline bool isIdentity(const bool upToGlobalPhase = true) const¶ Check whether the matrix represented by the DD is the identity.
- Template Parameters:
T – template parameter to enable this function only for matrix nodes
- Returns:
whether the matrix is the identity
Public Static Functions
-
static inline constexpr CachedEdge terminal(const ComplexValue &w)¶
Create a terminal edge with the given weight.
- Parameters:
w – The weight of the terminal edge.
- Returns:
A terminal edge with the given weight.
-
static inline constexpr CachedEdge terminal(const std::complex<fp> &w)¶
Create a terminal edge with the given weight.
- Parameters:
w – The weight of the terminal edge.
- Returns:
A terminal edge with the given weight.
-
static inline constexpr CachedEdge terminal(const Complex &w)¶
Create a terminal edge with the given weight.
- Parameters:
w – The weight of the terminal edge.
- Returns:
A terminal edge with the given weight.
-
static inline constexpr CachedEdge zero()¶
Create a zero terminal edge.
- Returns:
A zero terminal edge.
-
static inline constexpr CachedEdge one()¶
Create a one terminal edge.
- Returns:
A one terminal edge.
-
template<typename T = Node, isVector<T> = true>
static auto normalize(Node *p, const std::array<CachedEdge, RADIX> &e, MemoryManager &mm, ComplexNumbers &cn) -> CachedEdge¶ Get a normalized vector DD from a fresh node and a list of edges.
- Template Parameters:
T – template parameter to enable this method only for vNode
- Parameters:
p – the fresh node
e – the list of edges that form the successor nodes
mm – a reference to the memory manager (for returning unused nodes)
cn – a reference to the complex number manager (for adding new complex numbers)
- Returns:
the normalized vector DD
-
template<typename T = Node, isMatrixVariant<T> = true>
static auto normalize(Node *p, const std::array<CachedEdge, NEDGE> &e, MemoryManager &mm, ComplexNumbers &cn) -> CachedEdge¶ Get a normalized (density) matrix) DD from a fresh node and a list of edges.
- Template Parameters:
T – template parameter to enable this method only for matrix nodes
- Parameters:
p – the fresh node
e – the list of edges that form the successor nodes
mm – a reference to the memory manager (for returning unused nodes)
cn – a reference to the complex number manager (for adding new complex numbers)
- Returns:
the normalized (density) matrix DD
-
struct Complex¶
- #include <Complex.hpp>
A complex number represented by two pointers to compute table entries.
Public Functions
-
inline constexpr bool exactlyZero() const noexcept¶
Check whether the complex number is exactly equal to zero.
See also
- Returns:
True if the complex number is exactly equal to zero, false otherwise.
-
inline constexpr bool exactlyOne() const noexcept¶
Check whether the complex number is exactly equal to one.
See also
See also
- Returns:
True if the complex number is exactly equal to one, false otherwise.
-
bool approximatelyEquals(const Complex &c) const noexcept¶
Check whether the complex number is approximately equal to the given complex number.
See also
- Parameters:
c – The complex number to compare to.
- Returns:
True if the complex number is approximately equal to the given complex number, false otherwise.
-
bool approximatelyZero() const noexcept¶
Check whether the complex number is approximately equal to zero.
See also
- Returns:
True if the complex number is approximately equal to zero, false otherwise.
-
void mark() const noexcept¶
Mark the complex number as used.
-
void unmark() const noexcept¶
Unmark the complex number.
-
std::string toString(bool formatted = true, int precision = -1) const¶
Convert the complex number to a string.
See also
- Parameters:
formatted – Whether to apply special formatting to the numbers.
precision – The precision to use for the numbers.
- Returns:
The string representation of the complex number.
-
void writeBinary(std::ostream &os) const¶
Write the complex number to a binary stream.
See also
- Parameters:
os – The output stream to write to.
-
explicit operator ComplexValue() const noexcept¶
Convert the Complex number to a ComplexValue.
- Returns:
The ComplexValue representation of the Complex number.
Public Members
-
RealNumber *r¶
Compute table entry for the real part.
-
RealNumber *i¶
Compute table entry for the imaginary part.
-
inline constexpr bool exactlyZero() const noexcept¶
-
class ComplexNumbers¶
- #include <ComplexNumbers.hpp>
A class for managing complex numbers in the DD package.
Public Functions
-
inline explicit ComplexNumbers(RealNumberUniqueTable &table)¶
Default constructor.
-
~ComplexNumbers() = default¶
Default destructor.
-
Complex lookup(const Complex &c)¶
Lookup a complex value in the complex table; if not found add it.
- Parameters:
c – The complex number.
- Returns:
The found or added complex number.
-
Complex lookup(const ComplexValue &c)¶
See also
-
Complex lookup(fp r)¶
Lookup a real value in the complex table; if not found add it.
- Parameters:
r – The real number.
- Returns:
The found or added complex number with real part r and imaginary part zero.
-
Complex lookup(fp r, fp i)¶
Lookup a complex value in the complex table; if not found add it.
See also
ComplexTable::lookup
- Parameters:
r – The real part.
i – The imaginary part.
- Returns:
The found or added complex number.
-
template<class Node>
inline Edge<Node> lookup(const CachedEdge<Node> &ce)¶ Turn CachedEdge into Edge via lookup.
- Template Parameters:
Node – The type of the node.
- Parameters:
ce – The cached edge.
- Returns:
The edge with looked-up weight. The zero terminal if the new weight is exactly zero.
-
std::size_t realCount() const noexcept¶
Get the number of stored real numbers.
- Returns:
The number of stored real numbers.
Public Static Functions
-
static void setTolerance(fp tol) noexcept¶
Set the numerical tolerance for comparisons of floats.
- Parameters:
tol – The new tolerance.
-
static fp mag2(const Complex &a) noexcept¶
Compute the squared magnitude of a complex number.
- Parameters:
a – The complex number.
- Returns:
The squared magnitude.
-
static fp mag(const Complex &a) noexcept¶
Compute the magnitude of a complex number.
- Parameters:
a – The complex number.
- Returns:
The magnitude.
-
static fp arg(const Complex &a) noexcept¶
Compute the argument of a complex number.
- Parameters:
a – The complex number.
- Returns:
The argument.
-
static Complex conj(const Complex &a) noexcept¶
Compute the complex conjugate of a complex number.
Note
Conjugation is efficiently handled by just flipping the sign of the imaginary pointer.
- Parameters:
a – The complex number.
- Returns:
The complex conjugate.
-
inline explicit ComplexNumbers(RealNumberUniqueTable &table)¶
-
struct ComplexValue¶
- #include <ComplexValue.hpp>
A complex number represented by two floating point values.
Public Functions
-
bool operator==(const ComplexValue &other) const noexcept¶
Check for exact equality.
- Parameters:
other – The other complex number to compare to.
- Returns:
True if the complex numbers are exactly equal, false otherwise.
-
bool operator!=(const ComplexValue &other) const noexcept¶
See also
operator==
-
inline bool exactlyZero() const noexcept¶
Check whether the complex number is exactly equal to zero.
- Returns:
True if the complex number is exactly equal to zero, false otherwise.
-
inline bool exactlyOne() const noexcept¶
Check whether the complex number is exactly equal to one.
- Returns:
True if the complex number is exactly equal to one, false otherwise.
-
bool approximatelyEquals(const ComplexValue &c) const noexcept¶
Check whether the complex number is approximately equal to the given complex number.
See also
- Parameters:
c – The complex number to compare to.
- Returns:
True if the complex number is approximately equal to the given complex number, false otherwise.
-
bool approximatelyZero() const noexcept¶
Check whether the complex number is approximately equal to zero.
See also
- Returns:
True if the complex number is approximately equal to zero, false otherwise.
-
void writeBinary(std::ostream &os) const¶
Write a binary representation of the complex number to the given output stream.
- Parameters:
os – The output stream to write to.
-
void readBinary(std::istream &is)¶
Read a binary representation of the complex number from the given input stream.
- Parameters:
is – The input stream to read from.
-
void fromString(const std::string &realStr, std::string imagStr)¶
Construct a complex number from a string.
- Parameters:
realStr – The string representation of the real part.
imagStr – The string representation of the imaginary part.
-
inline explicit operator auto() const noexcept¶
Automatically convert to std::complex<fp>
-
inline fp mag2() const noexcept¶
Compute the squared magnitude of the complex number.
- Returns:
The squared magnitude of the complex number.
-
inline fp mag() const noexcept¶
Compute the magnitude of the complex number.
- Returns:
The magnitude of the complex number.
-
ComplexValue &operator+=(const ComplexValue &rhs) noexcept¶
In-place addition of two complex numbers.
Public Static Functions
-
static std::pair<std::uint64_t, std::uint64_t> getLowestFraction(fp x, std::uint64_t maxDenominator = 1U << 10)¶
Get the closest fraction to the given number.
- Parameters:
x – The number to approximate.
maxDenominator – The maximum denominator to use.
- Returns:
The closest fraction to the given number as a pair of numerator and denominator.
-
static void printFormatted(std::ostream &os, fp num, bool imaginary = false)¶
Pretty print the given real number to the given output stream.
- Parameters:
os – The output stream to write to.
num – The number to print.
imaginary – Whether the number is imaginary.
-
static std::string toString(const fp &real, const fp &imag, bool formatted = true, int precision = -1)¶
Print the given complex number to the given output stream.
- Parameters:
real – The real part of the complex number.
imag – The imaginary part of the complex number.
formatted – Whether to pretty print the number.
precision – The precision to use for printing numbers..
- Returns:
The string representation of the complex number.
-
bool operator==(const ComplexValue &other) const noexcept¶
-
template<class LeftOperandType, class RightOperandType, class ResultType>
class ComputeTable¶ - #include <ComputeTable.hpp>
Data structure for caching computed results of binary operations.
- Template Parameters:
LeftOperandType – type of the operation’s left operand
RightOperandType – type of the operation’s right operand
ResultType – type of the operation’s result
Public Functions
-
inline explicit ComputeTable(const size_t numBuckets = DEFAULT_NUM_BUCKETS)¶
Default constructor
- Parameters:
numBuckets – Number of hash table buckets. Must be a power of two.
-
inline std::size_t hash(const LeftOperandType &leftOperand, const RightOperandType &rightOperand) const¶
Compute the hash value for a given pair of operands.
- Parameters:
leftOperand – The left operand
rightOperand – The right operand
- Returns:
The hash value
-
inline const auto &getTable() const¶
Get a reference to the underlying table.
-
inline const auto &getStats() const noexcept¶
Get a reference to the statistics.
-
inline void insert(const LeftOperandType &leftOperand, const RightOperandType &rightOperand, const ResultType &result)¶
Insert a new entry into the compute table.
Any existing entry for the resulting hash value will be replaced.
- Parameters:
leftOperand – The left operand
rightOperand – The right operand
result – The result of the operation
-
inline ResultType *lookup(const LeftOperandType &leftOperand, const RightOperandType &rightOperand, const bool useDensityMatrix = false)¶
Look up a result in the compute table.
- Parameters:
leftOperand – The left operand
rightOperand – The right operand
useDensityMatrix – Whether a density matrix is expected
- Returns:
A pointer to the result if it is found, otherwise nullptr.
-
inline void clear()¶
Clear the compute table.
Sets all entries to invalid.
-
inline std::ostream &printStatistics(std::ostream &os = std::cout) const¶
Print the statistics of the compute table.
- Parameters:
os – The output stream to print to
- Returns:
The output stream
Public Static Attributes
-
static constexpr std::size_t DEFAULT_NUM_BUCKETS = 16384U¶
Default number of buckets for the compute table.
-
struct Entry¶
- #include <ComputeTable.hpp>
An entry in the compute table.
A triple consisting of the left operand, the right operand, and the result of a binary operation.
-
struct DDPackageConfig¶
-
template<class OperandType, class ResultType>
class DensityNoiseTable¶ - #include <DensityNoiseTable.hpp>
Data structure for caching computed results of noise operations.
- Template Parameters:
OperandType – type of the operation’s operand
ResultType – type of the operation’s result
Public Functions
-
inline explicit DensityNoiseTable(const size_t numBuckets = 32768U)¶
Default constructor
- Parameters:
numBuckets – Number of hash table buckets. Must be a power of two.
-
inline const auto &getTable() const¶
Get a reference to the table.
-
inline const auto &getStats() const noexcept¶
Get a reference to the statistics.
-
struct Entry¶
-
class DeterministicNoiseFunctionality¶
-
struct dNode : public dd::NodeBase¶
- #include <Node.hpp>
A density matrix DD node.
Data Layout (8)|(2|2|4)|(24|24|24|24) = 112B
-
template<class Node>
struct Edge¶ - #include <Edge.hpp>
A weighted edge pointing to a DD node.
This struct is used to represent the core data structure of the DD package. It is a wrapper around a pointer to a DD node and a complex edge weight.
- Template Parameters:
Node – Type of the DD node
Public Functions
-
inline constexpr bool operator==(const Edge &other) const¶
Comparing two DD edges with another involves comparing the respective pointers and checking whether the corresponding weights are “close enough” according to a given tolerance this notion of equivalence is chosen to counter floating point inaccuracies
-
inline constexpr bool isTerminal() const¶
Check whether this is a terminal.
- Returns:
whether this is a terminal
-
inline constexpr bool isZeroTerminal() const¶
Check whether this is a zero terminal.
- Returns:
whether this is a zero terminal
-
inline constexpr bool isOneTerminal() const¶
Check whether this is a one terminal.
- Returns:
whether this is a one terminal
-
std::complex<fp> getValueByPath(std::size_t numQubits, const std::string &decisions) const¶
Get a single element of the vector or matrix represented by the DD.
- Parameters:
numQubits – number of qubits in the considered DD
decisions – string {0, 1, 2, 3}^n describing which outgoing edge should be followed (for vectors entries are limited to 0 and 1) If string is longer than required, the additional characters are ignored.
- Returns:
the complex amplitude of the specified element
-
std::size_t size() const¶
Get the size of the DD.
The size of a DD is defined as the number of nodes (including the terminal node) in the DD.
- Returns:
the size of the DD
-
void mark() const noexcept¶
Mark the edge as used.
-
void unmark() const noexcept¶
Unmark the edge.
-
template<typename T = Node, isVector<T> = true>
std::complex<fp> getValueByIndex(std::size_t i) const¶ Get a single element of the vector represented by the DD.
- Template Parameters:
T – template parameter to enable this function only for vNode
- Parameters:
i – index of the element
- Returns:
the complex value of the amplitude
-
template<typename T = Node, isVector<T> = true>
CVec getVector(fp threshold = 0.) const¶ Get the vector represented by the DD.
- Template Parameters:
T – template parameter to enable this function only for vNode
- Parameters:
threshold – amplitudes with a magnitude below this threshold will be ignored
- Returns:
the vector
-
template<typename T = Node, isVector<T> = true>
SparseCVec getSparseVector(fp threshold = 0.) const¶ Get the sparse vector represented by the DD.
- Template Parameters:
T – template parameter to enable this function only for vNode
- Parameters:
threshold – amplitudes with a magnitude below this threshold will be ignored
- Returns:
the sparse vector
-
template<typename T = Node, isVector<T> = true>
void printVector() const¶ Print the vector represented by the DD.
Note
This function scales exponentially with the number of qubits.
- Template Parameters:
T – template parameter to enable this function only for vNode
-
template<typename T = Node, isVector<T> = true>
void addToVector(CVec &litudes) const¶ Add the amplitudes of a vector DD to a vector.
- Template Parameters:
T – template parameter to enable this function only for vNode
- Parameters:
amplitudes – the vector to add to
-
template<typename T = Node, isMatrixVariant<T> = true>
inline bool isIdentity(const bool upToGlobalPhase = true) const¶ Check whether the matrix represented by the DD is the identity.
- Template Parameters:
T – template parameter to enable this function only for matrix nodes
- Returns:
whether the matrix is the identity
-
template<typename T = Node, isMatrixVariant<T> = true>
std::complex<fp> getValueByIndex(std::size_t numQubits, std::size_t i, std::size_t j) const¶ Get a single element of the matrix represented by the DD.
- Template Parameters:
T – template parameter to enable this function only for matrix nodes
- Parameters:
numQubits – number of qubits in the considered DD
i – row index of the element
j – column index of the element
- Returns:
the complex value of the entry
-
template<typename T = Node, isMatrixVariant<T> = true>
CMat getMatrix(std::size_t numQubits, fp threshold = 0.) const¶ Get the matrix represented by the DD.
- Template Parameters:
T – template parameter to enable this function only for matrix nodes
- Parameters:
numQubits – number of qubits in the considered DD
threshold – entries with a magnitude below this threshold will be ignored
- Returns:
the matrix
-
template<typename T = Node, isMatrixVariant<T> = true>
SparseCMat getSparseMatrix(std::size_t numQubits, fp threshold = 0.) const¶ Get the sparse matrix represented by the DD.
- Template Parameters:
T – template parameter to enable this function only for matrix nodes
- Parameters:
numQubits – number of qubits in the considered DD
threshold – entries with a magnitude below this threshold will be ignored
- Returns:
the sparse matrix
-
template<typename T = Node, isMatrixVariant<T> = true>
void printMatrix(std::size_t numQubits) const¶ Print the matrix represented by the DD.
Note
This function scales exponentially with the number of qubits.
- Template Parameters:
T – template parameter to enable this function only for matrix nodes
- Parameters:
numQubits – number of qubits in the considered DD
-
template<typename T = Node, isMatrixVariant<T> = true>
void traverseMatrix(const std::complex<fp> &, std::size_t i, std::size_t j, MatrixEntryFunc f, std::size_t level, fp threshold = 0.) const¶ Recursively traverse the DD and call a function for each non-zero matrix entry.
- Template Parameters:
T – template parameter to enable this function only for matrix nodes
- Parameters:
amp – the accumulated amplitude from previous traversals
i – the current row index in the matrix
j – the current column index in the matrix
f – This function is called for each non-zero matrix entry with the row index, the column index and the amplitude as arguments.
level – the current level in the DD (ranges from 1 to n for regular nodes and is 0 for the terminal node)
threshold – entries with a magnitude below this threshold will be ignored
-
template<typename T = Node, isDensityMatrix<T> = true>
SparsePVec getSparseProbabilityVector(std::size_t numQubits, fp threshold = 0.) const¶ Get the sparse probability vector for the underlying density matrix.
- Template Parameters:
T – template parameter to enable this function only for dNode
- Parameters:
numQubits – number of qubits in the considered DD
threshold – probabilities below this threshold will be ignored
- Returns:
the sparse probability vector
-
template<typename T = Node, isDensityMatrix<T> = true>
SparsePVecStrKeys getSparseProbabilityVectorStrKeys(std::size_t numQubits, fp threshold = 0.) const¶ Get the sparse probability vector for the underlying density matrix.
- Template Parameters:
T – template parameter to enable this function only for dNode
- Parameters:
numQubits – number of qubits in the considered DD
threshold – probabilities below this threshold will be ignored
- Returns:
the sparse probability vector (using strings as keys)
Public Static Functions
-
static inline constexpr Edge terminal(const Complex &w)¶
Get a terminal DD with a given edge weight.
- Parameters:
w – the edge weight
- Returns:
the terminal DD representing (w)
-
static inline constexpr bool trackingRequired(const Edge &e)¶
Check whether an edge requires tracking.
- Parameters:
e – The edge to check.
- Returns:
Whether the edge requires tracking.
-
template<typename T = Node, isVector<T> = true>
static auto normalize(Node *p, const std::array<Edge, RADIX> &e, MemoryManager &mm, ComplexNumbers &cn) -> Edge¶ Get a normalized vector DD from a fresh node and a list of edges.
- Template Parameters:
T – template parameter to enable this function only for vNode
- Parameters:
p – the fresh node
e – the list of edges that form the successor nodes
mm – a reference to the memory manager (for returning unused nodes)
cn – a reference to the complex number manager (for adding new complex numbers)
- Returns:
the normalized vector DD
-
template<typename T = Node, isMatrixVariant<T> = true>
static auto normalize(Node *p, const std::array<Edge, NEDGE> &e, MemoryManager &mm, ComplexNumbers &cn) -> Edge¶ Get a normalized (density) matrix DD from a fresh node and a list of edges.
- Template Parameters:
T – template parameter to enable this function only for matrix nodes
- Parameters:
p – the fresh node
e – the list of edges that form the successor nodes
mm – a reference to the memory manager (for returning unused nodes)
cn – a reference to the complex number manager (for adding new complex numbers)
- Returns:
the normalized (density) matrix DD
-
struct LLBase¶
- #include <LinkedListBase.hpp>
A class to provide a base for linked list objects.
Subclassed by dd::NodeBase, dd::RealNumber
Public Functions
Public Members
-
class MemoryManager¶
- #include <MemoryManager.hpp>
A memory manager for objects of the same type that inherit from
LLBase.The class manages a collection of objects. The objects are stored in contiguous chunks of memory. The manager supports reclaiming objects that are no longer in use. This is done by maintaining a linked list of available objects. When an object is no longer in use, it is added to the list. When a new object is requested, the first object from the list is returned. If the list is empty, an object from the current chunk is returned. If the current chunk is full, a new chunk is allocated. The size of chunks grows exponentially according to a growth factor.
Note
The main purpose of this class is to reduce the number of memory allocations and deallocations. This is achieved by allocating a large number of objects at once and reusing them. This is especially useful for objects that are frequently created and destroyed, such as decision diagram nodes, edge weights, etc.
Public Functions
-
~MemoryManager() = default¶
default destructor
-
template<class T>
inline T *get()¶ Get an entry from the manager.
If an entry is available for reuse, it is returned. Otherwise, an entry from the pre-allocated chunks is returned. If no entry is available, a new chunk is allocated.
- Template Parameters:
T – The type of the entry.
- Returns:
A pointer to an entry.
-
void returnEntry(LLBase &entry) noexcept¶
Return an entry to the manager.
The entry is added to the list of available entries. The entry must not be used after it has been returned to the manager.
- Parameters:
entry – A reference to an entry that is no longer in use.
-
void reset(bool resizeToTotal = false) noexcept¶
Reset the manager.
Drops all but the first chunk. If
resizeToTotalis set to true, the first chunk is resized to the total number of entries. This increases memory locality and reduces the number of allocations when the manager is used again. However, it might also require a huge contiguous block of memory to be allocated.- Parameters:
resizeToTotal – If set to true, the first chunk is resized to the total number of entries.
-
inline const auto &getStats() const noexcept¶
Get a reference to the statistics.
Public Static Functions
-
template<class T>
static inline MemoryManager create(const std::size_t initialAllocationSize = INITIAL_ALLOCATION_SIZE)¶ Construct a new MemoryManager object for objects of type T.
- Parameters:
initialAllocationSize – The initial number of entries to allocate
- Template Parameters:
T – The type of the entries
Public Static Attributes
-
static constexpr std::size_t INITIAL_ALLOCATION_SIZE = 2048U¶
The number of initially allocated entries.
The number of initially allocated entries is the number of entries that are allocated as a chunk when the manager is created. Increasing this number reduces the number of allocations, but increases the memory usage.
-
static constexpr double GROWTH_FACTOR = 2U¶
The growth factor for table entry allocation.
The growth factor is used to determine the number of entries that are allocated when the manager runs out of entries. Per default, the number of entries is doubled. Increasing this number reduces the number of memory allocations, but increases the memory usage.
-
~MemoryManager() = default¶
-
struct MemoryManagerStatistics : public dd::Statistics¶
- #include <MemoryManagerStatistics.hpp>
A utility class for storing statistics of a memory manager.
Public Functions
-
inline explicit MemoryManagerStatistics(const std::size_t entrySize)¶
Construct a new Memory Manager Statistics object.
- Parameters:
entrySize – The size of a single entry
-
std::size_t getNumAvailableFromChunks() const noexcept¶
Get the number of available entries from memory chunks.
-
std::size_t getTotalNumAvailable() const noexcept¶
Get the total number of available entries.
-
double getUsageRatio() const noexcept¶
Get an estimate for ratio of used memory.
-
double getAllocatedMemoryMiB() const noexcept¶
Get an estimate of the total allocated memory in MiB.
-
double getUsedMemoryMiB() const noexcept¶
Get an estimate of the total used memory in MiB.
-
double getPeakUsedMemoryMiB() const noexcept¶
Get an estimate for the peak used memory in MiB.
-
void trackUsedEntries(std::size_t numEntries = 1U) noexcept¶
Track newly used entries (from chunks)
-
void trackReusedEntries(std::size_t numEntries = 1U) noexcept¶
Track reused entries (from available list)
-
void trackReturnedEntry() noexcept¶
Track a new available entry for reuse.
-
virtual void reset() noexcept override¶
Reset all statistics (except for the peak values)
-
virtual nlohmann::json json() const override¶
Get a JSON representation of the statistics.
Public Members
-
std::size_t entrySize_¶
The size of a single entry.
-
std::size_t numAllocations = 0U¶
The number of allocations performed.
-
std::size_t numAllocated = 0U¶
The number of allocated entries.
-
std::size_t numUsed = 0U¶
The number of entries currently in use.
-
std::size_t numAvailableForReuse = 0U¶
The number of entries currently available for reuse.
-
std::size_t peakNumUsed = 0U¶
The peak number of entries in use.
-
std::size_t peakNumAvailableForReuse = 0U¶
The peak number of entries available for reuse.
-
inline explicit MemoryManagerStatistics(const std::size_t entrySize)¶
-
struct mNode : public dd::NodeBase¶
- #include <Node.hpp>
A matrix DD node.
Data Layout (8)|(2|2|4)|(24|24|24|24) = 112B
-
struct NodeBase : public dd::LLBase¶
- #include <Node.hpp>
Base class for all DD nodes.
This class is used to store common information for all DD nodes. The
flagsmakes the implicit padding explicit and can be used for storing node properties. Data Layout (8)|(2|2|4) = 16B.Subclassed by dd::dNode, dd::mNode, dd::vNode
Public Functions
-
inline bool isMarked() const noexcept¶
Whether a node is marked as used.
-
inline void mark() noexcept¶
Mark the node as used.
-
inline void unmark() noexcept¶
Unmark the node.
Public Members
-
std::uint16_t flags = 0¶
Flags for node properties.
Not required for all node types, but padding is required either way.
0b10000 = mark flag used for mark-and-sweep garbage collection, 0b1000 = marks a reduced dm node, 0b100 = marks a dm (tmp flag), 0b10 = mark first path edge (tmp flag), 0b1 = mark path is conjugated (tmp flag)
Public Static Functions
-
static inline bool isTerminal(const NodeBase *p) noexcept¶
Check if a node is terminal.
Generally, a node is terminal if it is nullptr. Some nodes (dNode) encode additional information in the least significant bits of the pointer. These bits are masked out before checking for terminal nodes.
- Parameters:
p – The node to check
- Returns:
true if the node is terminal, false otherwise.
Public Static Attributes
-
static constexpr std::uint16_t MARK_FLAG = 0b10000U¶
Mark flag used for mark-and-sweep garbage collection.
-
inline bool isMarked() const noexcept¶
-
class Package¶
- #include <Package.hpp>
The DD package class.
This is the main class of the decision diagram module in MQT Core. It contains the core functionality for working with quantum decision diagrams. Specifically, it provides the means to
represent quantum states as decision diagrams,
represent quantum operations as decision diagrams,
multiply decision diagrams (MxV, MxM, etc.),
perform collapsing measurements on decision diagrams,
sample from decision diagrams.
To this end, it maintains several internal data structures, such as unique tables, compute tables, and memory managers, which are used to manage the nodes of the decision diagrams.
Public Functions
-
explicit Package(std::size_t nq = DEFAULT_QUBITS, const DDPackageConfig &config = DDPackageConfig{})¶
Construct a new DD Package instance.
- Parameters:
nq – The maximum number of qubits to allocate memory for. This can always be extended later using resize.
config – The configuration of the package
-
void resize(std::size_t nq)¶
Resize the package to a new number of qubits.
This method will resize all the unique tables appropriately so that they can handle the new number of qubits.
- Parameters:
nq – The new number of qubits
-
void reset()¶
Reset package state.
-
inline auto qubits() const¶
Get the number of qubits.
-
template<class T>
inline auto &getMemoryManager()¶ Get the memory manager for a given type.
- Template Parameters:
T – The type to get the manager for
- Returns:
A reference to the manager
-
void resetMemoryManagers(bool resizeToTotal = false)¶
Reset all memory managers.
resizeToTotal If set to true, each manager allocates one chunk of memory as large as all chunks combined before the reset.
See also
-
template<class T>
inline auto &getUniqueTable()¶ Get the unique table for a given type.
- Template Parameters:
T – The type to get the unique table for
- Returns:
A reference to the unique table
-
void clearUniqueTables()¶
Clear all unique tables.
See also
UniqueTable::clear
See also
-
template<class Node>
inline void incRef(const Edge<Node> &e) noexcept¶ Add the DD to a tracking hashset and update its reference count.
- Template Parameters:
Node – The node type of the edge.
- Parameters:
e – The edge to increase the reference count of.
-
template<class Node>
inline void decRef(const Edge<Node> &e)¶ Decrease the DD’s reference count and remove it from the tracking hashset if the count hits zero.
- Template Parameters:
Node – The node type of the edge.
- Parameters:
e – The edge to decrease the reference count of.
- Throws:
std::invalid_argument – If the edge is not part of the tracking hashset.
-
bool garbageCollect(bool force = false)¶
Trigger garbage collection on all unique tables.
Mark-and-sweep algorithm: First, mark all nodes and complex numbers tracked in
roots. Second, remove any unmarked nodes and numbers from the respective unique tables. Lastly, unmark all nodes and complex numbers again.Note
By default, garbage collection is only triggered if the unique tables report that a collection might be necessary.
- Parameters:
force – Force garbage collect, regardless of whether any table reports that it may need collecting.
- Returns:
Whether at least one vector, matrix, density-matrix node, or any complex number was reclaimed.
-
ActiveCounts computeActiveCounts()¶
Compute the active number of nodes and numbers.
Note
This traverses every currently tracked DD twice.
-
dEdge makeZeroDensityOperator(std::size_t n)¶
Construct the all-zero density operator \(|0...0\rangle\langle0...0|\).
Vector nodes, edges and quantum states
- Parameters:
n – The number of qubits
- Returns:
A decision diagram for the all-zero density operator
-
mEdge makeGateDD(const GateMatrix &mat, qc::Qubit target)¶
Construct the DD for a single-qubit gate.
Matrix nodes, edges and quantum gates
- Parameters:
mat – The matrix representation of the gate
target – The target qubit
- Returns:
A decision diagram for the gate
-
mEdge makeGateDD(const GateMatrix &mat, const qc::Control &control, qc::Qubit target)¶
Construct the DD for a single-qubit controlled gate.
- Parameters:
mat – The matrix representation of the gate
control – The control qubit
target – The target qubit
- Returns:
A decision diagram for the gate
-
mEdge makeGateDD(const GateMatrix &mat, const qc::Controls &controls, qc::Qubit target)¶
Construct the DD for a multi-controlled single-qubit gate.
- Parameters:
mat – The matrix representation of the gate
controls – The control qubits
target – The target qubit
- Returns:
A decision diagram for the gate
-
mEdge makeTwoQubitGateDD(const TwoQubitGateMatrix &mat, qc::Qubit target0, qc::Qubit target1)¶
Creates the DD for a two-qubit gate.
- Parameters:
mat – Matrix representation of the gate
target0 – First target qubit
target1 – Second target qubit
- Throws:
std::runtime_error – if the number of qubits is larger than the package configuration
- Returns:
DD representing the gate
-
mEdge makeTwoQubitGateDD(const TwoQubitGateMatrix &mat, const qc::Control &control, qc::Qubit target0, qc::Qubit target1)¶
Creates the DD for a two-qubit gate.
- Parameters:
mat – Matrix representation of the gate
control – Control qubit of the two-qubit gate
target0 – First target qubit
target1 – Second target qubit
- Throws:
std::runtime_error – if the number of qubits is larger than the package configuration
- Returns:
DD representing the gate
-
mEdge makeTwoQubitGateDD(const TwoQubitGateMatrix &mat, const qc::Controls &controls, qc::Qubit target0, qc::Qubit target1)¶
Creates the DD for a two-qubit gate.
- Parameters:
mat – Matrix representation of the gate
controls – Control qubits of the two-qubit gate
target0 – First target qubit
target1 – Second target qubit
- Throws:
std::runtime_error – if the number of qubits is larger than the package configuration
- Returns:
DD representing the gate
-
mEdge makeDDFromMatrix(const CMat &matrix)¶
Converts a given matrix to a decision diagram.
- Parameters:
matrix – A complex matrix to convert to a DD.
- Throws:
std::invalid_argument – If the given matrix is not square or its length is not a power of two.
- Returns:
A decision diagram representing the matrix.
-
template<class Node, template<class> class EdgeType>
inline EdgeType<Node> makeDDNode(const Qubit var, const std::array<EdgeType<Node>, std::tuple_size_v<decltype(Node::e)>> &edges, const bool generateDensityMatrix = false)¶ Create a normalized DD node and return an edge pointing to it.
The node is not recreated if it already exists. This function retrieves a node from the memory manager, sets its variable, and normalizes the edges. If the node resembles the identity, it is skipped. The function then looks up the node in the unique table and returns an edge pointing to it.
- Template Parameters:
Node – The type of the node.
EdgeType – The type of the edge.
- Parameters:
var – The variable associated with the node.
edges – The edges of the node.
generateDensityMatrix – Flag to indicate if a density matrix node should be generated.
- Returns:
An edge pointing to the normalized DD node.
-
template<class Node>
inline Edge<Node> deleteEdge(const Edge<Node> &e, const Qubit v, const std::size_t edgeIdx)¶ Delete an edge from the decision diagram.
- Template Parameters:
Node – The type of the node.
- Parameters:
e – The edge to delete.
v – The variable associated with the edge.
edgeIdx – The index of the edge to delete.
- Returns:
The modified edge after deletion.
-
template<class Node>
inline Edge<Node> deleteEdge(const Edge<Node> &e, const Qubit v, const std::size_t edgeIdx, std::unordered_map<Node*, Edge<Node>> &nodes)¶ Helper function to delete an edge from the decision diagram.
- Template Parameters:
Node – The type of the node.
- Parameters:
e – The edge to delete.
v – The variable associated with the edge.
edgeIdx – The index of the edge to delete.
nodes – A map to keep track of processed nodes.
- Returns:
The modified edge after deletion.
-
void clearComputeTables()¶
Clear all compute tables.
Compute table definitions
This method clears all entries in the compute tables used for various operations. It resets the state of the compute tables, making them ready for new computations.
-
std::string measureAll(vEdge &rootEdge, bool collapse, std::mt19937_64 &mt, fp epsilon = 0.001)¶
Measure all qubits in the given decision diagram.
Measurements from state decision diagrams
This function measures all qubits in the decision diagram represented by
rootEdge. It checks for numerical instabilities and collapses the state if requested.- Parameters:
rootEdge – The decision diagram to measure.
collapse – If true, the state is collapsed after measurement.
mt – A random number generator.
epsilon – The tolerance for numerical instabilities.
- Throws:
std::runtime_error – If numerical instabilities are detected or if probabilities do not sum to 1.
- Returns:
A string representing the measurement result.
-
char measureOneCollapsing(vEdge &rootEdge, Qubit index, std::mt19937_64 &mt, fp epsilon = 0.001)¶
Measures the qubit with the given index in the given state vector decision diagram. Collapses the state according to the measurement result.
- Parameters:
rootEdge – the root edge of the state vector decision diagram
index – the index of the qubit to be measured
mt – the random number generator
epsilon – the numerical precision used for checking the normalization of the state vector decision diagram
- Throws:
std::runtime_error – if a numerical instability is detected during the measurement.
- Returns:
the measurement result (‘0’ or ‘1’)
-
void performCollapsingMeasurement(vEdge &rootEdge, Qubit index, fp probability, bool measureZero)¶
Performs a specific measurement on the given state vector decision diagram. Collapses the state according to the measurement result.
- Parameters:
rootEdge – the root edge of the state vector decision diagram
index – the index of the qubit to be measured
probability – the probability of the measurement result (required for normalization)
measureZero – whether or not to measure ‘0’ (otherwise ‘1’ is measured)
-
template<class Node>
inline auto &getAddComputeTable()¶ Get the compute table for addition operations.
- Template Parameters:
Node – The type of the node.
- Returns:
A reference to the appropriate compute table for the given node type.
-
template<class Node>
inline auto &getAddMagnitudesComputeTable()¶ Get the compute table for addition operations with magnitudes.
- Template Parameters:
Node – The type of the node.
- Returns:
A reference to the appropriate compute table for the given node type.
-
template<class Node>
inline Edge<Node> add(const Edge<Node> &x, const Edge<Node> &y)¶ Add two decision diagrams.
This function performs the addition of two decision diagrams (DDs). It uses a compute table to cache intermediate results and avoid redundant computations. The addition is conducted recursively, where the function traverses the nodes of the DDs, adds corresponding edges, and normalizes the resulting edges. If the nodes are terminal, their weights are directly added. The function ensures that the resulting DD is properly normalized and stored in the unique table to maintain the canonical form.
- Template Parameters:
Node – The type of the node.
- Parameters:
x – The first DD.
y – The second DD.
- Returns:
The resulting DD after addition.
-
template<class Node>
inline CachedEdge<Node> add2(const CachedEdge<Node> &x, const CachedEdge<Node> &y, const Qubit var)¶ Internal function to add two decision diagrams.
This function is used internally to add two decision diagrams (DDs) of type Node. It is not intended to be called directly.
- Template Parameters:
Node – The type of the node.
- Parameters:
x – The first DD.
y – The second DD.
var – The variable associated with the current level of recursion.
- Returns:
The resulting DD after addition.
-
template<class Node>
inline CachedEdge<Node> addMagnitudes(const CachedEdge<Node> &x, const CachedEdge<Node> &y, const Qubit var)¶ Compute the element-wise magnitude sum of two vectors or matrices.
For two vectors (or matrices)
xandy, this function returns a resultrsuch that for each indexi:\( r[i] = \sqrt{|x[i]|^2 + |y[i]|^2} \)- Parameters:
x – DD representation of the first operand.
y – DD representation of the second operand.
var – Number of qubits in the DD.
- Returns:
DD representing the result.
-
vEdge conjugate(const vEdge &a)¶
Conjugates a given decision diagram edge.
- Parameters:
a – The decision diagram edge to conjugate.
- Returns:
The conjugated decision diagram edge.
-
vCachedEdge conjugateRec(const vEdge &a)¶
Recursively conjugates a given decision diagram edge.
- Parameters:
a – The decision diagram edge to conjugate.
- Returns:
The conjugated decision diagram edge.
-
mEdge conjugateTranspose(const mEdge &a)¶
Computes the conjugate transpose of a given matrix edge.
- Parameters:
a – The matrix edge to conjugate transpose.
- Returns:
The conjugated transposed matrix edge.
-
mCachedEdge conjugateTransposeRec(const mEdge &a)¶
Recursively computes the conjugate transpose of a given matrix edge.
- Parameters:
a – The matrix edge to conjugate transpose.
- Returns:
The conjugated transposed matrix edge.
-
template<class RightOperandNode>
inline auto &getMultiplicationComputeTable()¶ Get the compute table for multiplication operations.
- Template Parameters:
RightOperandNode – The type of the right operand node.
- Returns:
A reference to the appropriate compute table for the given node type.
-
VectorDD applyOperation(const MatrixDD &operation, const VectorDD &e)¶
Applies a matrix operation to a vector.
The reference count of the input vector is decreased, while the reference count of the result is increased. After the operation, garbage collection is triggered.
- Parameters:
operation – Matrix operation to apply
e – Vector to apply the operation to
- Returns:
The appropriately reference-counted result.
-
MatrixDD applyOperation(const MatrixDD &operation, const MatrixDD &e, bool applyFromLeft = true)¶
Applies a matrix operation to a matrix.
The reference count of the input matrix is decreased, while the reference count of the result is increased. After the operation, garbage collection is triggered.
- Parameters:
operation – Matrix operation to apply
e – Matrix to apply the operation to
applyFromLeft – Flag to indicate if the operation should be applied from the left (default) or right.
- Returns:
The appropriately reference-counted result.
-
template<class LeftOperandNode, class RightOperandNode>
inline Edge<RightOperandNode> multiply(const Edge<LeftOperandNode> &x, const Edge<RightOperandNode> &y, const bool generateDensityMatrix = false)¶ Multiplies two decision diagrams.
This function performs the multiplication of two decision diagrams (DDs). It uses a compute table to cache intermediate results and avoid redundant computations. The multiplication is conducted recursively, where the function traverses the nodes of the DDs, multiplies corresponding edges, and normalizes the resulting edges. If the nodes are terminal, their weights are directly multiplied. The function ensures that the resulting DD is properly normalized and stored in the unique table to maintain the canonical form.
- Template Parameters:
LeftOperandNode – The type of the left operand node.
RightOperandNode – The type of the right operand node.
- Parameters:
x – The left operand decision diagram.
y – The right operand decision diagram.
generateDensityMatrix – Flag to indicate if a density matrix node should be generated.
- Returns:
The resulting decision diagram after multiplication.
-
ComplexValue innerProduct(const vEdge &x, const vEdge &y)¶
Calculates the inner product of two vector decision diagrams.
- Parameters:
x – A vector DD representing a quantum state.
y – A vector DD representing a quantum state.
- Returns:
A complex number representing the scalar product of the DDs.
-
fp fidelity(const vEdge &x, const vEdge &y)¶
Calculates the fidelity between two vector decision diagrams.
- Parameters:
x – A vector DD representing a quantum state.
y – A vector DD representing a quantum state.
- Returns:
The fidelity between the two quantum states.
-
fp expectationValue(const mEdge &x, const vEdge &y)¶
Calculates the expectation value of an operator with respect to a quantum state.
This function calls the multiply() function to apply the operator to the quantum state, then calls innerProduct() to calculate the overlap between the original state and the applied state (i.e., <Psi| Psi’> = <Psi| (Op|Psi>)). It also calls the garbageCollect() function to free up any unused memory.
- Parameters:
x – A matrix decision diagram (DD) representing the operator.
y – A vector decision diagram (DD) representing the quantum state.
- Throws:
std::runtime_error – if the edges are not on the same level or if the expectation value is non-real.
- Returns:
A floating-point value representing the expectation value of the operator with respect to the quantum state.
-
template<class Node>
inline auto &getKroneckerComputeTable()¶ Get the compute table for Kronecker product operations.
- Template Parameters:
Node – The type of the node.
- Returns:
A reference to the appropriate compute table for the given node type.
-
template<class Node>
inline Edge<Node> kronecker(const Edge<Node> &x, const Edge<Node> &y, const std::size_t yNumQubits, const bool incIdx = true)¶ Computes the Kronecker product of two decision diagrams.
- Template Parameters:
Node – The type of the node.
- Parameters:
x – The first decision diagram.
y – The second decision diagram.
yNumQubits – The number of qubits in the second decision diagram.
incIdx – Whether to increment the index of the nodes in the second decision diagram.
- Throws:
std::invalid_argument – if the node type is
dNode(density matrices).- Returns:
The resulting decision diagram after computing the Kronecker product.
-
template<class Node>
inline auto &getTraceComputeTable()¶ Get the compute table for trace operations.
- Template Parameters:
Node – The type of the node.
- Returns:
A reference to the appropriate compute table for the given node type.
-
mEdge partialTrace(const mEdge &a, const std::vector<bool> &eliminate)¶
Computes the partial trace of a matrix decision diagram.
- Parameters:
a – The matrix decision diagram.
eliminate – A vector of booleans indicating which qubits to trace out.
- Returns:
The resulting matrix decision diagram after the partial trace.
-
template<class Node>
inline ComplexValue trace(const Edge<Node> &a, const std::size_t numQubits)¶ Computes the trace of a decision diagram.
- Template Parameters:
Node – The type of the node.
- Parameters:
a – The decision diagram.
numQubits – The number of qubits in the decision diagram.
- Returns:
The trace of the decision diagram as a complex value.
-
bool isCloseToIdentity(const mEdge &m, fp tol = 1e-10, const std::vector<bool> &garbage = {}, bool checkCloseToOne = true) const¶
Checks if a given matrix is close to the identity matrix.
This function checks if a given matrix is close to the identity matrix, while ignoring any potential garbage qubits and ignoring the diagonal weights if
checkCloseToOneis set to false.- Parameters:
m – An mEdge that represents the DD of the matrix.
tol – The accepted tolerance for the edge weights of the DD.
garbage – A vector of boolean values that defines which qubits are considered garbage qubits. If it’s empty, then no qubit is considered to be a garbage qubit.
checkCloseToOne – If false, the function only checks if the matrix is close to a diagonal matrix.
-
mEdge reduceAncillae(mEdge e, const std::vector<bool> &ancillary, bool regular = true)¶
Reduces the decision diagram by handling ancillary qubits.
Ancillary and garbage reduction
This function modifies the decision diagram to account for ancillary qubits by:
Early returning if there are no ancillary qubits or if the edge is zero
Special handling for identity matrices by creating appropriate zero nodes
Finding the lowest ancillary qubit as a starting point
Recursively reducing nodes starting from the lowest ancillary qubit
Adding zero nodes for any remaining higher ancillary qubits
The function maintains proper reference counting by incrementing the reference count of the result and decrementing the reference count of the input edge.
- Parameters:
e – The matrix decision diagram edge to be reduced.
ancillary – A boolean vector indicating which qubits are ancillary (true) or not (false).
regular – Flag indicating whether to perform regular (true) or inverse (false) reduction.
- Returns:
The reduced matrix decision diagram edge.
-
vEdge reduceGarbage(vEdge &e, const std::vector<bool> &garbage, bool normalizeWeights = false)¶
Reduces the given decision diagram by summing entries for garbage qubits.
For each garbage qubit q, this function sums all the entries for q = 0 and q = 1, setting the entry for q = 0 to the sum and the entry for q = 1 to zero. To ensure that the probabilities of the resulting state are the sum of the probabilities of the initial state, the function computes
sqrt(|a|^2 + |b|^2)for two entriesaandb.- Parameters:
e – DD representation of the matrix/vector.
garbage – Vector that describes which qubits are garbage and which ones are not. If garbage[i] = true, then qubit q_i is considered garbage.
normalizeWeights – By default set to
false. If set totrue, the function changes all weights in the DD to their magnitude, also for non-garbage qubits. This is used for checking partial equivalence of circuits. For partial equivalence, only the measurement probabilities are considered, so we need to consider only the magnitudes of each entry.
- Returns:
DD representing the reduced matrix/vector.
-
mEdge reduceGarbage(const mEdge &e, const std::vector<bool> &garbage, bool regular = true, bool normalizeWeights = false)¶
Reduces garbage qubits in a matrix decision diagram.
For each garbage qubit q, this function sums all the entries for q=0 and q=1, setting the entry for q=0 to the sum and the entry for q=1 to zero. To maintain proper probabilities, the function computes sqrt(|a|^2 + |b|^2) for two entries a and b. The function handles special cases like zero terminals and identity matrices separately and maintains proper reference counting throughout the reduction process.
- Parameters:
e – The matrix decision diagram edge to be reduced.
garbage – A boolean vector indicating which qubits are garbage (true) or not (false).
regular – Flag indicating whether to apply regular (true) or inverse (false) reduction. In regular mode, garbage entries are summed in the first two components, in inverse mode, they are summed in the first and third components.
normalizeWeights – Flag indicating whether to normalize weights to their magnitudes. When true, all weights in the DD are changed to their magnitude, also for non-garbage qubits. This is used for checking partial equivalence where only measurement probabilities matter.
- Returns:
The reduced matrix decision diagram edge.
Public Members
-
MemoryManager vMemoryManager = {MemoryManager::create<vNode>(config_.utVecInitialAllocationSize)}¶
The memory manager for vector nodes.
-
MemoryManager mMemoryManager = {MemoryManager::create<mNode>(config_.utMatInitialAllocationSize)}¶
The memory manager for matrix nodes.
-
MemoryManager dMemoryManager = {MemoryManager::create<dNode>(config_.utDmInitialAllocationSize)}¶
The memory manager for density matrix nodes.
-
MemoryManager cMemoryManager = {MemoryManager::create<RealNumber>()}¶
The memory manager for complex numbers.
Note
The real and imaginary part of complex numbers are treated separately. Hence, it suffices for the manager to only manage real numbers.
-
UniqueTable vUniqueTable = {vMemoryManager, {0U, config_.utVecNumBucket}}¶
The unique table used for vector nodes.
-
UniqueTable mUniqueTable = {mMemoryManager, {0U, config_.utMatNumBucket}}¶
The unique table used for matrix nodes.
-
UniqueTable dUniqueTable = {dMemoryManager, {0U, config_.utDmNumBucket}}¶
The unique table used for density matrix nodes.
-
RealNumberUniqueTable cUniqueTable = {cMemoryManager}¶
The unique table used for complex numbers.
See also
Note
The table actually only stores real numbers in the interval [0, 1], but is used to manages all complex numbers throughout the package.
-
ComputeTable<vCachedEdge, vCachedEdge, vCachedEdge> vectorAdd{config_.ctVecAddNumBucket}¶
Addition
-
UnaryComputeTable<vNode*, vCachedEdge> conjugateVector{config_.ctVecConjNumBucket}¶
Vector conjugation
-
UnaryComputeTable<mNode*, mCachedEdge> conjugateMatrixTranspose{config_.ctMatConjTransNumBucket}¶
Matrix (conjugate) transpose
-
ComputeTable<mNode*, vNode*, vCachedEdge> matrixVectorMultiplication{config_.ctMatVecMultNumBucket}¶
Multiplication
-
ComputeTable<vNode*, vNode*, vCachedEdge> vectorInnerProduct{config_.ctVecInnerProdNumBucket}¶
Inner product, fidelity, expectation value
-
ComputeTable<vNode*, vNode*, vCachedEdge> vectorKronecker{config_.ctVecKronNumBucket}¶
Kronecker/tensor product
-
UnaryComputeTable<dNode*, dCachedEdge> densityTrace{config_.ctDmTraceNumBucket}¶
(Partial) trace
-
StochasticNoiseOperationTable<mEdge> stochasticNoiseOperationCache{nqubits, config_.stochasticCacheOps}¶
Noise Operations
Public Static Functions
-
static std::pair<fp, fp> determineMeasurementProbabilities(const vEdge &rootEdge, Qubit index)¶
Determine the measurement probabilities for a given qubit index.
This function calculates the probabilities of measuring 0 and 1 for a given qubit index in the decision diagram. It uses a breadth-first search to traverse the decision diagram and accumulate the measurement probabilities. The function maintains a map of measurement probabilities for each node and a set of visited nodes to avoid redundant calculations. It also uses a queue to process nodes level by level.
- Parameters:
rootEdge – The root edge of the decision diagram.
index – The qubit index to determine the measurement probabilities for.
- Returns:
A pair of floating-point values representing the probabilities of measuring 0 and 1, respectively.
-
static fp fidelityOfMeasurementOutcomes(const vEdge &e, const SparsePVec &probs, const qc::Permutation &permutation = {})¶
Calculates the fidelity between a vector decision diagram and a sparse probability vector.
This function computes the fidelity between a quantum state represented by a vector decision diagram and a sparse probability vector. The optional permutation of qubits can be provided to match the qubit ordering.
- Parameters:
e – The root edge of the decision diagram.
probs – A map of probabilities for each measurement outcome.
permutation – An optional permutation of qubits.
- Returns:
The fidelity of the measurement outcomes.
Public Static Attributes
-
struct ActiveCounts¶
-
struct PairHash¶
-
struct RealNumber : public dd::LLBase¶
- #include <RealNumber.hpp>
A struct for representing real numbers as part of the DD package.
Consists of a floating point number (the value) and a next pointer (used for chaining entries). Numbers are marked for garbage collection via the second least significant bit of pointers referencing them.
Note
Due to the way the sign of the value is encoded, special care has to be taken when accessing the value. The static functions in this struct provide safe access to the value of a RealNumber* pointer.
Public Functions
-
RealNumber *next() const noexcept¶
Getter for the next object.
Public Members
-
fp value = {}¶
The value of the number.
The value of the number is a floating point number. The sign of the value is encoded in the least significant bit of the memory address of the number. As a consequence, values stored here are always non-negative. The sign of the value as well as the value itself can be accessed using the static functions of this struct.
Public Static Functions
-
static constexpr bool exactlyZero(const RealNumber *e) noexcept¶
Check whether the number points to the zero number.
- Parameters:
e – The number to check.
- Returns:
Whether the number points to zero.
-
static constexpr bool exactlyOne(const RealNumber *e) noexcept¶
Check whether the number points to the one number.
- Parameters:
e – The number to check.
- Returns:
Whether the number points to one.
-
static constexpr bool exactlySqrt2over2(const RealNumber *e) noexcept¶
Check whether the number points to the sqrt(2)/2 = 1/sqrt(2) number.
- Parameters:
e – The number to check.
- Returns:
Whether the number points to negative one.
-
static fp val(const RealNumber *e) noexcept¶
Get the value of the number.
Note
This function accounts for the sign of the number embedded in the memory address of the number.
- Parameters:
e – The number to get the value for.
- Returns:
The value of the number.
-
static bool approximatelyEquals(fp left, fp right) noexcept¶
Check whether two floating point numbers are approximately equal.
This function checks whether two floating point numbers are approximately equal. The two numbers are considered approximately equal if the absolute difference between them is smaller than a small value (TOLERANCE). This function is used to compare floating point numbers stored in the table.
- Parameters:
left – The first floating point number.
right – The second floating point number.
- Returns:
Whether the two floating point numbers are approximately equal.
-
static bool approximatelyEquals(const RealNumber *left, const RealNumber *right) noexcept¶
Check whether two numbers are approximately equal.
This function checks whether two numbers are approximately equal. Two numbers are considered approximately equal if they point to the same number or if the values of the numbers are approximately equal.
See also
- Parameters:
left – The first number.
right – The second number.
- Returns:
Whether the two numbers are approximately equal.
-
static bool approximatelyZero(fp e) noexcept¶
Check whether a floating point number is approximately zero.
- Parameters:
e – The floating point number to check.
- Returns:
Whether the floating point number is approximately zero.
-
static bool approximatelyZero(const RealNumber *e) noexcept¶
Check whether a number is approximately zero.
See also
- Parameters:
e – The number to check.
- Returns:
Whether the number is approximately zero.
-
static void writeBinary(const RealNumber *e, std::ostream &os)¶
Write a binary representation of the number to a stream.
- Parameters:
e – The number to write.
os – The stream to write to.
-
static void writeBinary(fp num, std::ostream &os)¶
Write a binary representation of a floating point number to a.
- Parameters:
num – The number to write.
os – The stream to write to.
-
static void readBinary(fp &num, std::istream &is)¶
Read a binary representation of a number from a stream.
- Parameters:
num – The number to read into.
is – The stream to read from.
-
static RealNumber *getAlignedPointer(const RealNumber *e) noexcept¶
Get an aligned pointer to the number.
Since the least significant bit of the memory address of the number is used to encode the sign of the value, the pointer to the number might not be aligned. This function returns an aligned pointer to the number.
- Parameters:
e – The number to get the aligned pointer for.
- Returns:
An aligned pointer to the number.
-
static RealNumber *getNegativePointer(const RealNumber *e) noexcept¶
Get a pointer to the number with a negative sign.
Since the least significant bit of the memory address of the number is used to encode the sign of the value, this function just sets the least significant bit of the memory address of the number to 1.
- Parameters:
e – The number to get the negative pointer for.
- Returns:
A negative pointer to the number.
-
static RealNumber *flipPointerSign(const RealNumber *e) noexcept¶
Flip the sign of the number pointer.
Note
This function does not change the sign of the value of the number. It rather changes the sign of the pointer to the number.
Note
We do not consider negative zero here, since it is not used in the DD package. There only exists one zero number, which is positive.
- Parameters:
e – The number to flip the sign of.
- Returns:
The number with the sign flipped.
-
static void mark(RealNumber *e) noexcept¶
Mark
efor garbage collection.Sets the 2nd least significant bit of the next_ pointer.
- Parameters:
e – The number to mark.
-
static void unmark(RealNumber *e) noexcept¶
Unmark
eafter garbage collection.Unsets the 2nd least significant bit of the next_ pointer.
- Parameters:
e – The number to unmark.
-
static void immortalize(RealNumber *e) noexcept¶
Immortalize
e.Sets the 3rd least significant bit of the next_ pointer.
- Parameters:
e – The number to immortalize.
-
static bool isNegativePointer(const RealNumber *e) noexcept¶
Check whether the number is flagged as negative.
- Parameters:
e – The number to check.
- Returns:
Whether the number is negative.
-
static bool isMarked(const RealNumber *e) noexcept¶
Check whether the number is flagged as marked.
- Parameters:
e – The number to check.
- Returns:
Whether the number is marked.
-
static bool isImmortal(const RealNumber *e) noexcept¶
Check whether the number is flagged as immortal.
- Parameters:
e – The number to check.
- Returns:
Whether the number is immortal.
-
RealNumber *next() const noexcept¶
-
class RealNumberUniqueTable¶
- #include <RealNumberUniqueTable.hpp>
A unique table for real numbers.
A hash table that stores real numbers. The hash table is implemented as an array of buckets, each of which is a linked list of entries. The hash table has a fixed number of buckets.
Note
: The implementation assumes that all values are non-negative and in the range [0, 1]. While numbers outside of this range can be stored, they will always be placed in the same bucket and will therefore cause collisions.
Public Functions
-
explicit RealNumberUniqueTable(MemoryManager &manager, std::size_t initialGCLim = INITIAL_GC_LIMIT)¶
The default constructor.
- Parameters:
manager – The memory manager to use for allocating new numbers.
initialGCLim – The initial garbage collection limit.
-
inline const auto &getTable() const noexcept¶
Get a reference to the table.
-
inline const auto &getStats() const noexcept¶
Get a reference to the statistics.
-
RealNumber *lookup(fp val)¶
Lookup a number in the table.
This function is used to lookup and insert them into the table if they are not yet present. Since the table only ever stores non-negative numbers, the lookup is a three-step process. First the sign is stripped off the number and stored, then the non-negative value is looked up in the table and an aligned pointer to the respective entry is returned. Finally, If the sign of the original number was negative, the pointer is adjusted.
- Parameters:
val – The floating point number to look up.
- Returns:
A pointer to an entry corresponding to that number.
-
bool possiblyNeedsCollection() const noexcept¶
Check whether the table possibly needs garbage collection.
- Returns:
Whether the number of entries in the table has reached the garbage collection limit.
-
std::size_t garbageCollect(bool force = false) noexcept¶
Perform garbage collection.
This function performs garbage collection. It first checks whether garbage collection is necessary. If not, it does nothing. Otherwise, it iterates over all entries in the table and removes all numbers whose pointers are unmarked. If the force flag is set, garbage collection is performed even if it is not strictly necessary. Based on how many entries are returned to the available list, the garbage collection limit is dynamically adjusted.
- Parameters:
force – Whether to force garbage collection.
- Returns:
The number of entries returned to the available list.
-
void clear() noexcept¶
Clear the table.
This function clears the table. It iterates over all entries in the table and sets them to nullptr. It also discards the available list and all but the first chunk of the allocated chunks. Also resets all counters.
-
void print() const¶
Print the table.
-
std::ostream &printBucketDistribution(std::ostream &os = std::cout)¶
Print the bucket distribution of the table.
- Parameters:
os – The output stream to print to.
- Returns:
The output stream.
-
std::size_t countMarkedEntries() const noexcept¶
Count the marked entries in the table.
Public Static Functions
-
static std::int64_t hash(fp val) noexcept¶
The hash function for the hash table.
The hash function for the table is a simple linear (clipped) hash function. The hash function is used to map floating point numbers to the buckets of the table.
Note
Typically, you would expect the hash to be an unsigned integer. Here, we use a signed integer because it turns out to result in fewer assembly instructions. See https://godbolt.org/z/9v4TEMfdz for a comparison.
- Parameters:
val – The floating point number to hash. Must be non-negative.
- Returns:
The hash value of the floating point number.
-
explicit RealNumberUniqueTable(MemoryManager &manager, std::size_t initialGCLim = INITIAL_GC_LIMIT)¶
-
struct Statistics¶
Subclassed by dd::MemoryManagerStatistics, dd::TableStatistics
Public Functions
-
inline virtual void reset() noexcept¶
Reset all statistics (except for peak values)
-
virtual nlohmann::json json() const¶
Get a JSON representation of the statistics.
-
virtual std::string toString() const¶
Get a pretty-printed string representation of the statistics.
Friends
-
inline friend std::ostream &operator<<(std::ostream &os, const Statistics &stats)¶
Write a string representation to an output stream.
- Parameters:
os – The output stream
stats – The statistics
- Returns:
The output stream
-
inline virtual void reset() noexcept¶
-
class StochasticNoiseFunctionality¶
-
template<class Edge>
class StochasticNoiseOperationTable¶
-
struct TableStatistics : public dd::Statistics¶
- #include <TableStatistics.hpp>
A utility class for storing statistics of a table.
Subclassed by dd::UniqueTableStatistics
Public Functions
-
void trackInsert() noexcept¶
Track a new insert.
-
virtual void reset() noexcept override¶
Reset all statistics (except for peak values)
-
double hitRatio() const noexcept¶
Get the hit ratio of the table.
The hit ratio is the ratio of lookups that were successful.
- Returns:
The hit ratio of the table.
-
double colRatio() const noexcept¶
Get the collision ratio of the table.
A collision occurs when the hash function maps two different entries to the same bucket. The collision ratio is the ratio of lookups that resulted in a collision.
- Returns:
The collision ratio of the table.
-
double loadFactor() const noexcept¶
Get the load factor of the table.
The load factor is the ratio of entries to buckets.
- Returns:
The load factor of the table.
-
double getEntrySizeMiB() const noexcept¶
Convert the entry size to MiB.
-
double getMemoryMiB() const noexcept¶
Get the amount of memory required for the table in MiB.
-
virtual nlohmann::json json() const override¶
Get a JSON representation of the statistics.
Public Members
-
std::size_t entrySize = 0U¶
The size of a single entry.
-
std::size_t numBuckets = 0U¶
The number of buckets in the table.
-
std::size_t numEntries = 0U¶
The number of entries in the table.
-
std::size_t peakNumEntries = 0U¶
The peak number of entries in the table.
-
std::size_t collisions = 0U¶
The number of collisions.
-
std::size_t hits = 0U¶
The number of successful lookups.
-
std::size_t lookups = 0U¶
The number of lookups.
-
std::size_t inserts = 0U¶
The number of inserts.
-
void trackInsert() noexcept¶
-
template<class OperandType, class ResultType>
class UnaryComputeTable¶ - #include <UnaryComputeTable.hpp>
Data structure for caching computed results of unary operations.
- Template Parameters:
OperandType – type of the operation’s operand
ResultType – type of the operation’s result
Public Functions
-
inline explicit UnaryComputeTable(const size_t numBuckets = DEFAULT_NUM_BUCKETS)¶
Default constructor.
-
inline const auto &getTable() const¶
Get a reference to the underlying table.
-
inline const auto &getStats() const noexcept¶
Get a reference to the statistics.
-
inline std::size_t hash(const OperandType &a) const¶
Compute the hash value for a given operand.
-
inline void insert(const OperandType &operand, const ResultType &result)¶
Insert a new entry into the compute table.
Any existing entry for the resulting hash value will be replaced.
- Parameters:
operand – The operand
result – The result of the operation
-
inline ResultType *lookup(const OperandType &operand)¶
Look up a result in the compute table.
- Parameters:
operand – The operand
- Returns:
A pointer to the result if it is found, otherwise nullptr.
-
inline void clear()¶
Clear the compute table.
Sets all entries to invalid.
Public Static Attributes
-
static constexpr std::size_t DEFAULT_NUM_BUCKETS = 32768U¶
Default number of buckets for the compute table.
-
struct Entry¶
- #include <UnaryComputeTable.hpp>
An entry in the compute table.
-
class UniqueTable¶
- #include <UniqueTable.hpp>
Data structure for uniquely storing DD nodes.
Public Functions
-
UniqueTable(MemoryManager &manager, const UniqueTableConfig &config)¶
The default constructor.
The MemoryManager shall be constructed from the same type that the unique table is then used for in the lookup method.
- Parameters:
manager – The memory manager to use
config – The configuration for the unique table
-
template<class Node>
inline std::size_t hash(const Node &p) const¶ The hash function for the hash table.
The hash function just combines the hashes of the edges of the node. The hash value is masked to ensure that it is in the range [0, nBuckets - 1].
- Parameters:
p – The node to hash.
- Returns:
The hash value of the node.
-
inline const auto &getTables() const¶
Get a reference to the table.
-
inline const auto &getStats() const noexcept¶
Get a reference to the statistics.
-
const UniqueTableStatistics &getStats(std::size_t idx) const noexcept¶
Get a reference to individual statistics.
-
nlohmann::basic_json getStatsJson(bool includeIndividualTables = false) const¶
Get a JSON object with the statistics.
-
std::size_t getNumEntries() const noexcept¶
Get the total number of entries.
-
std::size_t countMarkedEntries() const noexcept¶
Count the number of marked entries.
-
bool possiblyNeedsCollection() const¶
Determine whether the table possibly requires garbage collection.
Public Static Attributes
-
static constexpr std::size_t INITIAL_GC_LIMIT = 131072U¶
The initial garbage collection limit.
The initial garbage collection limit is the number of entries that must be present in the table before garbage collection is triggered. Increasing this number reduces the number of garbage collections, but increases the memory usage.
-
struct UniqueTableConfig¶
Public Members
-
std::size_t nVars = 0U¶
The number of variables.
-
std::size_t nBuckets = 32768¶
The number of hash buckets to use (has to be a power of two)
-
std::size_t initialGCLimit = INITIAL_GC_LIMIT¶
The initial garbage collection limit.
-
std::size_t nVars = 0U¶
-
UniqueTable(MemoryManager &manager, const UniqueTableConfig &config)¶
-
struct UniqueTableStatistics : public dd::TableStatistics¶
- #include <UniqueTableStatistics.hpp>
A class for storing statistics of a unique table.
Public Functions
-
virtual void reset() noexcept override¶
Reset all statistics (except for the peak values)
-
virtual nlohmann::json json() const override¶
Get a JSON representation of the statistics.
Public Members
-
std::size_t gcRuns = 0U¶
The number of garbage collection runs.
-
virtual void reset() noexcept override¶
-
struct vNode : public dd::NodeBase¶
- #include <Node.hpp>
A vector DD node.
Data Layout (8)|(2|2|4)|(24|24) = 64B
-
namespace constants¶
Functions
-
constexpr bool isStaticNumber(const RealNumber *e) noexcept¶
Check whether a number is one of the static numbers.
- Parameters:
e – The number to check.
- Returns:
Whether the number is one of the static numbers.
Variables
- MQT_CORE_DD_EXPORT RealNumber zero
The constant zero.
- MQT_CORE_DD_EXPORT RealNumber one
The constant one.
- MQT_CORE_DD_EXPORT RealNumber sqrt2over2
The constant sqrt(2)/2 = 1/sqrt(2).
-
constexpr bool isStaticNumber(const RealNumber *e) noexcept¶
-
namespace immortals¶
Immortal numbers that will never be garbage collected.
-
template<typename T>