Namespace qc

namespace qc

Typedefs

using BVBitString = std::bitset<4096>
using GroverBitString = std::bitset<128>
using Qubit = std::uint32_t

Type alias for qubit indices.

This type (alias) is used to represent qubit indices in the library. It has been chosen to be an unsigned 32-bit integer to allow for up to 4,294,967,295 qubits, which should be enough for most use cases.

using Bit = std::uint64_t

Type alias for classical bit indices.

This type (alias) is used to represent classical bit indices in the library. The choice of 64-bits is arbitrary and can be changed if necessary.

using Targets = std::vector<Qubit>

A type alias for a vector of qubits which are supposed to act as targets.

using fp = double

Floating-point type used throughout the library.

using Controls = std::set<Control, CompareControl>

Type alias for a set of control qubits.

using Symbolic = sym::Expression<fp, fp>
using VariableAssignment = std::unordered_map<sym::Variable, fp>
using SymbolOrNumber = std::variant<Symbolic, fp>
typedef std::unordered_map<std::string, QuantumRegister> QuantumRegisterMap
using ClassicalRegisterMap = std::unordered_map<std::string, ClassicalRegister>
using QubitIndexToRegisterMap = std::unordered_map<Qubit, std::pair<const QuantumRegister&, std::string>>
using BitIndexToRegisterMap = std::unordered_map<Bit, std::pair<const ClassicalRegister&, std::string>>

Enums

enum class Format : uint8_t

Supported file formats.

Values:

enumerator OpenQASM2

OpenQASM 2.0 format.

enumerator OpenQASM3

OpenQASM 3 format.

enum ComparisonKind

Values:

enumerator Eq
enumerator Neq
enumerator Lt
enumerator Leq
enumerator Gt
enumerator Geq
enum OpTypeFlags

Values:

enumerator OpTypeNone
enumerator OpTypeInv
enumerator OpTypeDiag
enum OpType

Values:

Functions

auto createBernsteinVazirani(const BVBitString &hiddenString) -> QuantumComputation
auto createBernsteinVazirani(Qubit nq, std::size_t seed = 0) -> QuantumComputation
auto createBernsteinVazirani(const BVBitString &hiddenString, Qubit nq) -> QuantumComputation
auto createIterativeBernsteinVazirani(const BVBitString &hiddenString) -> QuantumComputation
auto createIterativeBernsteinVazirani(Qubit nq, std::size_t seed = 0) -> QuantumComputation
auto createIterativeBernsteinVazirani(const BVBitString &hiddenString, Qubit nq) -> QuantumComputation
auto createGHZState(Qubit nq) -> QuantumComputation
auto appendGroverInitialization(QuantumComputation &qc) -> void
auto appendGroverOracle(QuantumComputation &qc, const GroverBitString &targetValue) -> void
auto appendGroverDiffusion(QuantumComputation &qc) -> void
auto computeNumberOfIterations(Qubit nq) -> std::size_t
auto createGrover(Qubit nq, const GroverBitString &targetValue) -> QuantumComputation
auto createGrover(Qubit nq, std::size_t seed = 0) -> QuantumComputation
auto createQFT(Qubit nq, bool includeMeasurements = true) -> QuantumComputation
auto createIterativeQFT(Qubit nq) -> QuantumComputation
auto createQPE(Qubit nq, bool exact = true, std::size_t seed = 0) -> QuantumComputation
auto createQPE(fp lambda, Qubit precision) -> QuantumComputation
auto createIterativeQPE(Qubit nq, bool exact = true, std::size_t seed = 0) -> QuantumComputation
auto createIterativeQPE(fp lambda, Qubit precision) -> QuantumComputation
auto createRandomCliffordCircuit(Qubit nq, std::size_t depth = 1, std::size_t seed = 0) -> QuantumComputation
auto createStatePreparationCircuit(const std::vector<std::complex<double>> &amplitudes, double eps = 1e-10) -> QuantumComputation

Prepares a generic quantum state from a list of normalized complex amplitudes.

Adapted implementation of IBM Qiskit’s State Preparation: https://github.com/Qiskit/qiskit/blob/e9ccd3f374fd5424214361d47febacfa5919e1e3/qiskit/circuit/library/data_preparation/state_preparation.py based on the following paper:

 V. V. Shende, S. S. Bullock and I. L. Markov,
 "Synthesis of quantum-logic circuits", in IEEE Transactions on
 Computer-Aided Design of Integrated Circuits and Systems,
 vol. 25, no. 6, pp. 1000-1010, June 2006,
 doi: 10.1109/TCAD.2005.855930.

Parameters:
  • amplitudes – State (vector) to prepare. Must be normalized and have a size that is a power of two.

  • eps – Precision wanted for computations, default 1e-10

Throws:

invalid_argument – If amplitudes is not normalized or its length is not a power of two.

Returns:

Quantum computation that prepares the state

auto createWState(Qubit nq) -> QuantumComputation
constexpr std::size_t combineHash(const std::size_t lhs, const std::size_t rhs) noexcept

Combine two 64bit hashes into one 64bit hash.

Combines two 64bit hashes into one 64bit hash based on boost::hash_combine (https://www.boost.org/LICENSE_1_0.txt)

Parameters:
  • lhs – The first hash

  • rhs – The second hash

Returns:

The combined hash

constexpr void hashCombine(std::size_t &hash, const std::size_t with) noexcept

Extend a 64bit hash with a 64bit integer.

Parameters:
  • hash – The hash to extend

  • with – The integer to extend the hash with

Returns:

The combined hash

inline void unreachable()

Function used to mark unreachable code.

Uses compiler specific extensions if possible. Even if no extension is used, undefined behavior is still raised by an empty function body and the noreturn attribute.

inline bool operator<(const Control &lhs, const Control &rhs)

Defines the order of controls based on their qubit index and type.

inline bool operator==(const Control &lhs, const Control &rhs)

operator== overload for Control

inline bool operator!=(const Control &lhs, const Control &rhs)

operator!= overload for Control

inline Control operator""_pc(const unsigned long long int q)

User-defined literal for positive control qubits.

This literal allows to create a positive control qubit from an unsigned integer, for example as 0_pc.

Parameters:

q – Index of the qubit that acts as a control.

Returns:

A positive control qubit.

inline Control operator""_nc(const unsigned long long int q)

User-defined literal for negative control qubits.

This literal allows to create a negative control qubit from an unsigned integer, for example as 0_nc.

Parameters:

q – Index of the qubit that acts as a control.

Returns:

A negative control qubit.

ComparisonKind getInvertedComparisonKind(ComparisonKind kind)
std::string toString(const ComparisonKind &kind)
std::ostream &operator<<(std::ostream &os, const ComparisonKind &kind)
std::string toString(OpType opType)
std::string shortName(OpType opType)

Gives a short name for the given OpType (at most 3 characters)

Parameters:

opType – OpType to get the short name for

Returns:

Short name for the given OpType

constexpr bool isTwoQubitGate(const OpType opType)
constexpr bool isSingleQubitGate(const OpType type)

Checks if given OpType is a single qubit gate.

inline std::ostream &operator<<(std::ostream &out, const OpType opType)
OpType opTypeFromString(const std::string &opType)
inline std::istream &operator>>(std::istream &in, OpType &opType)

Variables

static constexpr auto PI = static_cast<fp>(3.141592653589793238462643383279502884197169399375105820974L)

A constant for the value of \(\pi\).

static constexpr auto PI_2 = static_cast<fp>(1.570796326794896619231321691639751442098584699687552910487L)

A constant for the value of \(\frac{\pi}{2}\).

static constexpr auto PI_4 = static_cast<fp>(0.785398163397448309615660845819875721049292349843776455243L)

A constant for the value of \(\frac{\pi}{4}\).

static constexpr auto TAU = static_cast<fp>(6.283185307179586476925286766559005768394338798750211641950L)

A constant for the value of \(\tau\).

static constexpr auto E = static_cast<fp>(2.718281828459045235360287471352662497757247093699959574967L)

A constant for the value of \(e\).

static constexpr unsigned NUM_OP_TYPE_FLAG_BITS = 2
class CircuitOptimizer

Public Static Functions

static void replaceMCXWithMCZ(QuantumComputation &qc)

Replaces all MCX gates with MCZ gates (and H gates surrounding the target qubit) in the given circuit.

Parameters:

qc – the quantum circuit

static void backpropagateOutputPermutation(QuantumComputation &qc)

Backpropagates the output permutation through the circuit.

Starts at the end of the circuit with a potentially incomplete output permutation and backpropagates it through the circuit until the beginning of the circuit is reached. The tracked permutation is updated with every SWAP gate and, eventually, the initial layout of the circuit is set to the tracked permutation. Any unassigned qubit in the initial layout is assigned to the first available position (favoring an identity mapping).

Parameters:

qc – the quantum circuit

static void collectBlocks(QuantumComputation &qc, std::size_t maxBlockSize)

Collects all operations in the circuit into blocks of a maximum size.

The circuit is traversed and operations are collected into blocks of a maximum size. The blocks are then appended to the circuit in the order they were collected. Each block is realized as a compound operation. Light optimizations are applied to the blocks, such as removing identity gates and fusing single-qubit gates.

Parameters:
  • qc – the quantum circuit

  • maxBlockSize – the maximum size of a block

static void collectCliffordBlocks(QuantumComputation &qc, std::size_t maxBlockSize)

Collects all Clifford blocks in the circuit.

The circuit is traversed and all operations that are part of a Clifford block are collected into a compound operation with a certain maximum block size. All non-Clifford operations remain untouched. Light optimizations are applied to the blocks, such as removing identity gates.

Parameters:
  • qc – the quantum circuit

  • maxBlockSize – the maximum size of a block

static void elidePermutations(QuantumComputation &qc)

Elide permutations by propagating them through the circuit.

The circuit is traversed and any SWAP gate is eliminated by propagating the permutation through the circuit. The final layout of the circuit is updated accordingly. This pass works well together with the swapReconstruction pass.

Parameters:

qc – the quantum circuit

class ClassicalRegister : public qc::Register<Bit>
struct CompareControl
#include <Control.hpp>

Allows a set of Control to be indexed by a Qubit

class CompoundOperation : public qc::Operation

Public Functions

virtual bool isGlobal(size_t nQubits) const noexcept override

Checks whether a gate is global.

A StandardOperation is global if it acts on all qubits. A CompoundOperation is global if all its sub-operations are StandardOperations of the same type with the same parameters acting on all qubits. The latter is what a QASM line like ry(π) q; is translated to in MQT Core. All other operations are not global.

Returns:

True if the operation is global, false otherwise.

virtual auto commutesAtQubit(const Operation &other, const Qubit &qubit) const -> bool override

Checks whether operation commutes with other operation on a given qubit.

virtual auto isInverseOf(const Operation &other) const -> bool override

This refines the inherited method because the inherited method leads to false negatives

void merge(CompoundOperation &op)

Merge another compound operation into this one.

This transfers ownership of the operations from the other compound operation to this one. The other compound operation will be empty after this operation.

Parameters:

op – the compound operation to merge into this one

bool isConvertibleToSingleOperation() const

Check whether this operation can be collapsed into a single operation.

Returns:

true if this operation can be collapsed into a single operation, false otherwise

std::unique_ptr<Operation> collapseToSingleOperation()

Collapse this operation into a single operation.

This operation must be convertible to a single operation.

Returns:

the collapsed operation

inline auto begin() noexcept

Pass-Through

struct Control
#include <Control.hpp>

Represents a control qubit as a qubit index and a control type.

Public Types

enum class Type : bool

The polarity of the control.

Values:

enumerator Pos

Positive controls trigger on \(\ket{1}\).

enumerator Neg

Negative controls trigger on \(\ket{0}\).

Public Functions

inline std::string toString() const

Get a string representation of the control.

inline Control(const Qubit q = {}, const Type t = Type::Pos)

Construct a control qubit.

Note

This constructor is not explicit to allow implicit conversion from Qubit to Control.

Parameters:
  • q – The qubit that acts as a control.

  • t – The type of the control. Defaults to Type::Pos.

Public Members

Qubit qubit = {}

The qubit that acts as a control.

Type type = Type::Pos

The type of the control.

template<class V>
class DirectedAcyclicGraph : public qc::DirectedGraph<V>

Public Functions

inline auto orderTopologically() const -> std::vector<V>

Perform a depth-first search on the graph and return the nodes in a topological order

template<class V>
class DirectedGraph
#include <DirectedGraph.hpp>

Class representing generic directed graphs.

Template Parameters:

V – the type of the vertices in the graph. Must implement operator<<.

Subclassed by qc::DirectedAcyclicGraph< V >

Public Functions

inline auto toString() const -> std::string

Outputs a string representation of the graph in the DOT format.

template<class T>
struct DisjointSet
class IfElseOperation : public qc::Operation
class Layer
#include <Layer.hpp>

Class to manage the creation of layers when traversing a quantum circuit.

The class uses the DAG of the circuit to create layers of gates that can be executed at the same time. It can be used to create the front or look ahead layer.

Public Functions

inline explicit Layer(const QuantumComputation &qc, bool commutable = true)

Constructs a new layer from the given quantum circuit.

The layer contains all gates that are currently executable in a set of executable gates. When a gate is executed, this can enable other gates that are added to the set of executable sets then, or disable gates that are removed from the set of executable gates. The commutable flag can be used to specify whether commutation rules should be considered.

Parameters:
  • qc – quantum circuit

  • commutable – true if commutation rules should be considered, false otherwise (default: true)

class DAGVertex : public std::enable_shared_from_this<DAGVertex>
class NonUnitaryOperation : public qc::Operation
class Operation

Subclassed by na::AodOperation, qc::CompoundOperation, qc::IfElseOperation, qc::NonUnitaryOperation, qc::StandardOperation

Public Functions

inline virtual bool isGlobal(size_t) const

Checks whether a gate is global.

A StandardOperation is global if it acts on all qubits. A CompoundOperation is global if all its sub-operations are StandardOperations of the same type with the same parameters acting on all qubits. The latter is what a QASM line like ry(π) q; is translated to in MQT Core. All other operations are not global.

Returns:

True if the operation is global, false otherwise.

inline virtual auto commutesAtQubit(const Operation&, const Qubit&) const -> bool

Checks whether operation commutes with other operation on a given qubit.

template<class T, class U>
struct PairHash
#include <UndirectedGraph.hpp>

Pairs do not provide a hash function by default, this is the replacement.

class Permutation

Public Functions

Permutation() = default

Constructors.

inline auto begin () noexcept -> decltype(permutation)::iterator

Returns an iterator to the beginning.

inline auto end () noexcept -> decltype(permutation)::iterator

Returns an iterator to the end.

inline auto rbegin () noexcept -> decltype(permutation)::reverse_iterator

Returns a reverse iterator to the beginning.

inline auto rend () noexcept -> decltype(permutation)::reverse_iterator

Returns a reverse iterator to the end.

inline auto empty() const -> bool

Checks whether the permutation is empty.

inline auto size() const -> std::size_t

Returns the number of elements.

inline void clear()

Clears the permutation.

inline auto find(const Qubit qubit) -> decltype(permutation.find(qubit))

Finds element with specific key.

inline auto count(const Qubit qubit) const -> std::size_t

Returns the number of elements with specific key.

inline auto at(const Qubit qubit) const -> Qubit

Access specified element with bounds checking.

inline auto at(const Qubit qubit) -> Qubit&

Access specified element with bounds checking.

inline auto operator[](const Qubit qubit) -> Qubit&

Access or insert specified element.

inline auto insert(const std::pair<const Qubit, Qubit> &value) -> auto

Inserts elements or nodes.

template<class ...Args>
inline auto emplace(Args&&... args) -> auto

Constructs element in-place.

template<class ...Args>
inline auto try_emplace(const Qubit key, Args&&... args) -> auto

Inserts in-place if the key does not exist, does nothing otherwise.

inline auto insert_or_assign(const Qubit key, const Qubit value) -> auto

Inserts an element or assigns to the current element if the key already exists

inline auto erase(const Qubit qubit) -> std::size_t

Erases elements.

inline void swap(Permutation &other) noexcept

Swaps the contents.

inline auto operator<(const Permutation &other) const -> bool

Lexicographically compares the values in the map.

class QuantumComputation

Public Functions

Qubit getHighestLogicalQubitIndex() const

Returns the highest qubit index used as a value in the initial layout.

Qubit getHighestPhysicalQubitIndex() const

Returns the highest qubit index used as a key in the initial layout.

Qubit getPhysicalQubitIndex(Qubit logicalQubitIndex) const

Returns the physical qubit index of the given logical qubit index.

Iterates over the initial layout dictionary and returns the key corresponding to the given value.

Parameters:

logicalQubitIndex – The logical qubit index to look for

Returns:

The physical qubit index of the given logical qubit index

void setLogicalQubitAncillary(Qubit logicalQubitIndex)

Sets the given logical qubit to be ancillary.

Removes the qubit from the qubit register and adds it to the ancillary register, if such a register exists. Otherwise a new ancillary register is created.

Parameters:

logicalQubitIndex

void setLogicalQubitsAncillary(Qubit minLogicalQubitIndex, Qubit maxLogicalQubitIndex)

Sets all logical qubits in the range [minLogicalQubitIndex, maxLogicalQubitIndex] to be ancillary.

Removes the qubits from the qubit register and adds it to the ancillary register, if such a register exists. Otherwise a new ancillary register is created.

Parameters:
  • minLogicalQubitIndex – first qubit that is set to be ancillary

  • maxLogicalQubitIndex – last qubit that is set to be ancillary

void setLogicalQubitsGarbage(Qubit minLogicalQubitIndex, Qubit maxLogicalQubitIndex)

Sets all logical qubits in the range [minLogicalQubitIndex, maxLogicalQubitIndex] to be garbage.

Parameters:
  • minLogicalQubitIndex – first qubit that is set to be garbage

  • maxLogicalQubitIndex – last qubit that is set to be garbage

std::pair<bool, std::optional<Qubit>> containsLogicalQubit(Qubit logicalQubitIndex) const

checks whether the given logical qubit exists in the initial layout.

Parameters:

logicalQubitIndex – the logical qubit index to check

Returns:

whether the given logical qubit exists in the initial layout and to which physical qubit it is mapped

void gphase(fp angle)

Adds a global phase to the quantum circuit.

Parameters:

angle – the angle to add

void measureAll(bool addBits = true)

Add measurements to all qubits.

This function adds measurements to all qubits in the circuit and appends a new classical register (named “meas”) to the circuit if addBits is true. Otherwise, qubit q is measured into classical bit q.

Parameters:

addBits – Whether to add new classical bits to the circuit

void stripIdleQubits(bool force = false)

strip away qubits with no operations applied to them and which do not pop up in the output permutation

Parameters:

force – if true, also strip away idle qubits occurring in the output permutation

std::pair<Qubit, std::optional<Qubit>> removeQubit(Qubit logicalQubitIndex)

Removes a logical qubit.

Parameters:

logicalQubitIndex – The qubit to remove

Returns:

The physical qubit index that the logical qubit was mapped to in the initial layout and the output qubit index that the logical qubit was mapped to in the output permutation.

void invert()

Invert the circuit.

Inverts the circuit by inverting all operations and reversing the order of the operations. Additionally, the initial layout and output permutation are swapped. If the circuit has different initial layout and output permutation sizes, the initial layout and output permutation will not be swapped.

std::ostream &print(std::ostream &os) const

printing

void dumpOpenQASM(std::ostream &of, bool openQasm3 = true) const

Dumps the circuit in OpenQASM format to the given output stream.

Parameters:
  • of – The output stream to write the OpenQASM representation to

  • openQasm3 – Whether to use OpenQASM 3.0 or 2.0

std::string toQASM(bool qasm3 = true) const

Returns the OpenQASM representation of the circuit.

Parameters:

qasm3 – Whether to use OpenQASM 3.0 or 2.0

Returns:

The OpenQASM representation of the circuit

void reorderOperations()

Reorders the operations in the quantum computation to establish a canonical order.

Uses iterative breadth-first search starting from the topmost qubit.

bool isDynamic() const

Check whether the quantum computation contains dynamic circuit primitives.

Dynamic circuit primitives are mid-circuit measurements, resets, or classical control flow operations. This method traverses the whole circuit once until it finds a dynamic operation.

Returns:

Whether the quantum computation contains dynamic circuit primitives

inline auto begin() noexcept

Pass-Through

Public Static Functions

static QuantumComputation fromCompoundOperation(const CompoundOperation &op)

Construct a QuantumComputation from CompoundOperation object.

The function creates a copy of each operation in the compound operation. It uses the largest qubit index in the CompoundOperation for determining the number of qubits. It adds a single quantum register with all qubits from 0 to the largest qubit index and a corresponding classical register with the same size. The initial layout as well as the output permutation are set to the identity permutation.

Parameters:

op – The CompoundOperation to convert to a quantum circuit

Returns:

The constructed QuantumComputation

class QuantumRegister : public qc::Register<Qubit>
template<typename BitType>
class Register
class StandardOperation : public qc::Operation

Subclassed by qc::SymbolicOperation

Public Functions

virtual bool isGlobal(size_t nQubits) const override

Checks whether a gate is global.

A StandardOperation is global if it acts on all qubits. A CompoundOperation is global if all its sub-operations are StandardOperations of the same type with the same parameters acting on all qubits. The latter is what a QASM line like ry(π) q; is translated to in MQT Core. All other operations are not global.

Returns:

True if the operation is global, false otherwise.

virtual auto commutesAtQubit(const Operation &other, const Qubit &qubit) const -> bool override

Checks whether operation commutes with other operation on a given qubit.

class SymbolicOperation : public qc::StandardOperation
template<typename T>
class SymmetricMatrix
#include <SymmetricMatrix.hpp>

Symmetric matrix class with same number of rows and columns that allows access by row and column but uses less memory than a full matrix.

template<class V, class E>
class UndirectedGraph
#include <UndirectedGraph.hpp>

Class representing generic undirected directed graphs.

Template Parameters:

V – the type of the vertices in the graph. Must implement operator<<.

Public Functions

inline auto toString() const -> std::string

Outputs a string representation of the graph in the DOT format.

namespace literals

Inline namespace for control literals.

Use using namespace qc::literals to enable the literals.

Functions

inline Control operator""_pc(const unsigned long long int q)

User-defined literal for positive control qubits.

This literal allows to create a positive control qubit from an unsigned integer, for example as 0_pc.

Parameters:

q – Index of the qubit that acts as a control.

Returns:

A positive control qubit.

inline Control operator""_nc(const unsigned long long int q)

User-defined literal for negative control qubits.

This literal allows to create a negative control qubit from an unsigned integer, for example as 0_nc.

Parameters:

q – Index of the qubit that acts as a control.

Returns:

A negative control qubit.