mqt.core.dd

MQT Core decision diagram module.

Module Contents

class Control(qubit: int, type_: Control = ...)

Control a raw matrix DD operation with one qubit.

Parameters:
  • qubit – Control qubit index.

  • type – Control polarity.

class Type

Bases: enum.Enum

Control polarity.

Pos = 1
Neg = 0
property qubit: int

Control qubit index.

property type_: Control

Control polarity.

__eq__(arg: object, /) → bool
__ne__(arg: object, /) → bool
__hash__() → int
class VectorDD

A class representing a vector decision diagram (DD).

is_terminal() → bool

Check if the DD is a terminal node.

is_zero_terminal() → bool

Check if the DD is a zero terminal node.

size() → int

Get the size of the DD by traversing it once.

__getitem__(key: int) → complex

Get the amplitude of a basis state by index.

get_amplitude(num_qubits: int, decisions: str) → complex

Get the amplitude of a basis state by decisions.

Parameters:
  • num_qubits – The number of qubits.

  • decisions – The decisions as a string of bits (0 or 1), where decisions[i] corresponds to the successor to follow at level i of the DD. Must be at least num_qubits long.

Returns:

The amplitude of the basis state.

get_vector(threshold: float = 0.0) → Annotated[numpy.typing.NDArray[numpy.complex128], {'shape': (None, )}]

Get the state vector represented by the DD.

Parameters:

threshold – The threshold for not including amplitudes in the state vector. Defaults to 0.0.

Returns:

The state vector.

Raises:

MemoryError – If the memory allocation fails.

to_bytes(binary: bool = True) → bytes

Serialize the DD to bytes.

Parameters:

binary – Whether to use the binary serialization format. Defaults to True. If False, the textual serialization format is used.

Returns:

The serialized DD.

Notes

The binary format is not portable across different architectures or platforms.

static from_bytes(dd_package: DDPackage, data: bytes, binary: bool = True) → VectorDD

Deserialize a DD from bytes.

Parameters:
  • dd_package – The DD package that owns the deserialized DD.

  • data – The serialized DD.

  • binary – Whether the data uses the binary serialization format. Defaults to True. If False, the textual serialization format is expected.

Returns:

The deserialized DD.

Notes

The binary format is not portable across different architectures or platforms.

to_dot(colored: bool = True, edge_labels: bool = False, classic: bool = False, memory: bool = False, format_as_polar: bool = True) → str

Convert the DD to a DOT graph that can be plotted via Graphviz.

Parameters:
  • colored – Whether to use colored edge weights

  • edge_labels – Whether to include edge weights as labels.

  • classic – Whether to use the classic DD visualization style.

  • memory – Whether to include memory information. For debugging purposes only.

  • format_as_polar – Whether to format the edge weights in polar coordinates.

Returns:

The DOT graph.

to_svg(filename: str, colored: bool = True, edge_labels: bool = False, classic: bool = False, memory: bool = False, format_as_polar: bool = True) → None

Convert the DD to an SVG file that can be viewed in a browser.

Uses PyGraphviz 2 or later when installed. Otherwise, requires the dot command from Graphviz to be available in the PATH.

Parameters:
  • filename – The filename of the SVG file. Any file extension will be replaced by .dot and then .svg.

  • colored – Whether to use colored edge weights.

  • edge_labels – Whether to include edge weights as labels.

  • classic – Whether to use the classic DD visualization style.

  • memory – Whether to include memory information. For debugging purposes only.

  • format_as_polar – Whether to format the edge weights in polar coordinates.

class MatrixDD

A class representing a matrix decision diagram (DD).

is_terminal() → bool

Check if the DD is a terminal node.

is_zero_terminal() → bool

Check if the DD is a zero terminal node.

is_identity(up_to_global_phase: bool = True) → bool

Check if the DD represents the identity matrix.

Parameters:

up_to_global_phase – Whether to ignore global phase.

Returns:

Whether the DD represents the identity matrix.

size() → int

Get the size of the DD by traversing it once.

get_entry(num_qubits: int, row: int, col: int) → complex

Get the entry of the matrix by row and column index.

get_entry_by_path(num_qubits: int, decisions: str) → complex

Get the entry of the matrix by decisions.

Parameters:
  • num_qubits – The number of qubits.

  • decisions – The decisions as a string of 0, 1, 2, or 3, where decisions[i] corresponds to the successor to follow at level i of the DD. Must be at least num_qubits long.

Returns:

The entry of the matrix.

get_matrix(num_qubits: int, threshold: float = 0.0) → Annotated[numpy.typing.NDArray[numpy.complex128], {'shape': (None, None)}]

Get the matrix represented by the DD.

Parameters:
  • num_qubits – The number of qubits.

  • threshold – The threshold for not including entries in the matrix. Defaults to 0.0.

Returns:

The matrix.

Raises:

MemoryError – If the memory allocation fails.

to_bytes(binary: bool = True) → bytes

Serialize the DD to bytes.

Parameters:

binary – Whether to use the binary serialization format. Defaults to True. If False, the textual serialization format is used.

Returns:

The serialized DD.

Notes

The binary format is not portable across different architectures or platforms.

static from_bytes(dd_package: DDPackage, data: bytes, binary: bool = True) → MatrixDD

Deserialize a DD from bytes.

Parameters:
  • dd_package – The DD package that owns the deserialized DD.

  • data – The serialized DD.

  • binary – Whether the data uses the binary serialization format. Defaults to True. If False, the textual serialization format is expected.

Returns:

The deserialized DD.

Notes

The binary format is not portable across different architectures or platforms.

to_dot(colored: bool = True, edge_labels: bool = False, classic: bool = False, memory: bool = False, format_as_polar: bool = True) → str

Convert the DD to a DOT graph that can be plotted via Graphviz.

Parameters:
  • colored – Whether to use colored edge weights

  • edge_labels – Whether to include edge weights as labels.

  • classic – Whether to use the classic DD visualization style.

  • memory – Whether to include memory information. For debugging purposes only.

  • format_as_polar – Whether to format the edge weights in polar coordinates.

Returns:

The DOT graph.

to_svg(filename: str, colored: bool = True, edge_labels: bool = False, classic: bool = False, memory: bool = False, format_as_polar: bool = True) → None

Convert the DD to an SVG file that can be viewed in a browser.

Uses PyGraphviz 2 or later when installed. Otherwise, requires the dot command from Graphviz to be available in the PATH.

Parameters:
  • filename – The filename of the SVG file. Any file extension will be replaced by .dot and then .svg.

  • colored – Whether to use colored edge weights.

  • edge_labels – Whether to include edge weights as labels.

  • classic – Whether to use the classic DD visualization style.

  • memory – Whether to include memory information. For debugging purposes only.

  • format_as_polar – Whether to format the edge weights in polar coordinates.

class DDPackage(num_qubits: int = 32)

Create and manipulate decision diagrams.

The package owns DD storage, unique tables, and cached computation results. It provides reference counting and garbage collection.

Notes

It is undefined behavior to pass VectorDD or MatrixDD objects that were created with a different DDPackage to the methods of the DDPackage. The only exception is the identity DD returned by identity(), which represents the global one-terminal and can be used with any DDPackage instance.

Parameters:

num_qubits – The maximum number of qubits that the DDPackage can handle. Defaults to 32; use resize to change the capacity.

resize(num_qubits: int) → None

Resize the DDPackage to accommodate a different number of qubits.

Parameters:

num_qubits – The new number of qubits. Must be greater than zero. It is undefined behavior to resize the DDPackage to a smaller number of qubits and then perform operations on decision diagrams that are associated with qubits that are no longer present.

property max_qubits: int

The maximum number of qubits that the DDPackage can handle.

zero_state(num_qubits: int) → VectorDD

Create the DD for the zero state \(| 0 \ldots 0 \rangle\).

Parameters:

num_qubits – The number of qubits. Must not be greater than the number of qubits the DDPackage is configured with.

Returns:

The DD for the zero state. The resulting state is guaranteed to have its reference count increased.

computational_basis_state(num_qubits: int, state: Sequence[bool]) → VectorDD

Create the DD for the computational basis state \(| b_{n - 1} \ldots b_0 \rangle\).

Parameters:
  • num_qubits – The number of qubits. Must not be greater than the number of qubits the DDPackage is configured with.

  • state – The state as a list of booleans. Must be at least num_qubits long.

Returns:

The DD for the computational basis state. The resulting state is guaranteed to have its reference count increased.

basis_state(num_qubits: int, state: Sequence[BasisStates]) → VectorDD

Create the DD for the basis state \(| B_{n - 1} \ldots B_0 \rangle\), where \(B_i \in \{0, 1, +\, -\, L, R\}\).

Parameters:
  • num_qubits – The number of qubits. Must not be greater than the number of qubits the DDPackage is configured with.

  • state – The state as an iterable of BasisStates. Must be at least num_qubits long.

Returns:

The DD for the basis state. The resulting state is guaranteed to have its reference count increased.

ghz_state(num_qubits: int) → VectorDD

Create the DD for the GHZ state \(\frac{1}{\sqrt{2}} (| 0 \ldots 0 \rangle + |1 \ldots 1 \rangle)\).

Parameters:

num_qubits – The number of qubits. Must not be greater than the number of qubits the DDPackage is configured with.

Returns:

The DD for the GHZ state. The resulting state is guaranteed to have its reference count increased.

w_state(num_qubits: int) → VectorDD

Create the DD for the W state \(|W\rangle\).

\[|W\rangle = \frac{1}{\sqrt{n}} (| 100 \ldots 0 \rangle + | 010 \ldots 0 \rangle + \ldots + | 000 \ldots 1 \rangle)\]
Parameters:

num_qubits – The number of qubits. Must not be greater than the number of qubits the DDPackage is configured with.

Returns:

The DD for the W state. The resulting state is guaranteed to have its reference count increased.

from_vector(state: Annotated[numpy.typing.NDArray[numpy.complex128], {'shape': (None,), 'writable': False}]) → VectorDD

Create a DD from a state vector.

Parameters:

state – The state vector. Read-only and strided arrays are supported. Must have a length that is a power of 2. Must not require more qubits than the DDPackage is configured with.

Returns:

The DD for the vector. The resulting state is guaranteed to have its reference count increased.

measure_collapsing(vec: VectorDD, qubit: int) → str

Measure a qubit and collapse the DD.

Notes

Automatically manages the reference count of the input and output DDs. The input DD must have a non-zero reference count.

Parameters:
  • vec – The input DD.

  • qubit – The qubit to measure.

Returns:

The measurement outcome.

measure_all(vec: VectorDD, collapse: bool = False) → str

Measure all qubits.

Notes

Automatically manages the reference count of the input and output DDs. The input DD must have a non-zero reference count.

Parameters:
  • vec – The input DD.

  • collapse – Whether to collapse the DD.

Returns:

The measurement outcome.

static identity() → MatrixDD

Create the DD for the identity matrix \(I\).

Notes

Returns the global one-terminal (identity matrix), which is package-agnostic and safe to use across DDPackage instances.

Returns:

The DD for the identity matrix.

single_qubit_gate(matrix: Annotated[numpy.typing.NDArray[numpy.complex128], {'shape': (2, 2)}], target: int) → MatrixDD

Create the DD for a single-qubit gate.

Parameters:
  • matrix – The \(2 \times 2\) matrix representing the single-qubit gate.

  • target – The target qubit.

Returns:

The DD for the single-qubit gate.

controlled_single_qubit_gate(matrix: Annotated[numpy.typing.NDArray[numpy.complex128], {'shape': (2, 2)}], control: Control | int, target: int) → MatrixDD

Create the DD for a controlled single-qubit gate.

Parameters:
  • matrix – The \(2 \times 2\) matrix representing the single-qubit gate.

  • control – The control qubit.

  • target – The target qubit.

Returns:

The DD for the controlled single-qubit gate.

multi_controlled_single_qubit_gate(matrix: Annotated[numpy.typing.NDArray[numpy.complex128], {'shape': (2, 2)}], controls: Set[Control | int], target: int) → MatrixDD

Create the DD for a multi-controlled single-qubit gate.

Parameters:
  • matrix – The \(2 \times 2\) matrix representing the single-qubit gate.

  • controls – The control qubits.

  • target – The target qubit.

Returns:

The DD for the multi-controlled single-qubit gate.

two_qubit_gate(matrix: Annotated[numpy.typing.NDArray[numpy.complex128], {'shape': (4, 4)}], target0: int, target1: int) → MatrixDD

Create the DD for a two-qubit gate.

Parameters:
  • matrix – The \(4 \times 4\) matrix representing the two-qubit gate.

  • target0 – The first target qubit.

  • target1 – The second target qubit.

Returns:

The DD for the two-qubit gate.

controlled_two_qubit_gate(matrix: Annotated[numpy.typing.NDArray[numpy.complex128], {'shape': (4, 4)}], control: Control | int, target0: int, target1: int) → MatrixDD

Create the DD for a controlled two-qubit gate.

Parameters:
  • matrix – The \(4 \times 4\) matrix representing the two-qubit gate.

  • control – The control qubit.

  • target0 – The first target qubit.

  • target1 – The second target qubit.

Returns:

The DD for the controlled two-qubit gate.

multi_controlled_two_qubit_gate(matrix: Annotated[numpy.typing.NDArray[numpy.complex128], {'shape': (4, 4)}], controls: Set[Control | int], target0: int, target1: int) → MatrixDD

Create the DD for a multi-controlled two-qubit gate.

Parameters:
  • matrix – The \(4 \times 4\) matrix representing the two-qubit gate.

  • controls – The control qubits.

  • target0 – The first target qubit.

  • target1 – The second target qubit.

Returns:

The DD for the multi-controlled two-qubit gate.

from_matrix(matrix: Annotated[numpy.typing.NDArray[numpy.complex128], {'shape': (None, None), 'writable': False}]) → MatrixDD

Create a DD from a matrix.

Parameters:

matrix – The matrix. Must be square and have a size that is a power of 2. Read-only and strided arrays are supported.

Returns:

The DD for the matrix.

inc_ref_vec(vec: VectorDD) → None

Increment the reference count of a vector.

inc_ref_mat(mat: MatrixDD) → None

Increment the reference count of a matrix.

dec_ref_vec(vec: VectorDD) → None

Decrement the reference count of a vector.

dec_ref_mat(mat: MatrixDD) → None

Decrement the reference count of a matrix.

garbage_collect(force: bool = False) → bool

Perform garbage collection on the DDPackage.

Parameters:

force – Whether to force garbage collection. If set to True, garbage collection is performed regardless of the current memory usage. If set to False, garbage collection is only performed if the memory usage exceeds a certain threshold.

Returns:

Whether any nodes were collected during garbage collection.

vector_add(lhs: VectorDD, rhs: VectorDD) → VectorDD

Add two vectors.

Notes

It is the caller’s responsibility to update the reference count of the input and output vectors after the operation.

Both vectors must have the same number of qubits.

Parameters:
  • lhs – The left vector.

  • rhs – The right vector.

Returns:

The sum of the two vectors.

matrix_add(lhs: MatrixDD, rhs: MatrixDD) → MatrixDD

Add two matrices.

Notes

It is the caller’s responsibility to update the reference count of the input and output matrices after the operation.

Both matrices must have the same number of qubits.

Parameters:
  • lhs – The left matrix.

  • rhs – The right matrix.

Returns:

The sum of the two matrices.

conjugate(vec: VectorDD) → VectorDD

Conjugate a vector.

Notes

It is the caller’s responsibility to update the reference count of the input and output vectors after the operation.

Parameters:

vec – The vector.

Returns:

The conjugated vector.

conjugate_transpose(mat: MatrixDD) → MatrixDD

Conjugate transpose a matrix.

Notes

It is the caller’s responsibility to update the reference count of the input and output matrices after the operation.

Parameters:

mat – The matrix.

Returns:

The conjugate transposed matrix.

matrix_vector_multiply(mat: MatrixDD, vec: VectorDD) → VectorDD

Multiply a matrix with a vector.

Notes

It is the caller’s responsibility to update the reference count of the input and output matrices after the operation.

The vector must have at least as many qubits as the matrix non-trivially acts on.

Parameters:
  • mat – The matrix.

  • vec – The vector.

Returns:

The product of the matrix and the vector.

matrix_multiply(lhs: MatrixDD, rhs: MatrixDD) → MatrixDD

Multiply two matrices.

Notes

It is the caller’s responsibility to update the reference count of the input and output matrices after the operation.

Parameters:
  • lhs – The left matrix.

  • rhs – The right matrix.

Returns:

The product of the two matrices.

inner_product(lhs: VectorDD, rhs: VectorDD) → complex

Compute the inner product of two vectors.

Notes

Both vectors must have the same number of qubits.

Parameters:
  • lhs – The left vector.

  • rhs – The right vector.

Returns:

The inner product of the two vectors.

fidelity(lhs: VectorDD, rhs: VectorDD) → float

Compute the fidelity of two vectors.

Notes

Both vectors must have the same number of qubits.

Parameters:
  • lhs – The left vector.

  • rhs – The right vector.

Returns:

The fidelity of the two vectors.

expectation_value(observable: MatrixDD, state: VectorDD) → float

Compute the expectation value of an observable.

Notes

The state must have at least as many qubits as the observable non-trivially acts on.

Parameters:
  • observable – The observable.

  • state – The state.

Returns:

The expectation value of the observable.

vector_kronecker(top: VectorDD, bottom: VectorDD, bottom_num_qubits: int, increment_index: bool = True) → VectorDD

Compute the Kronecker product of two vectors.

Notes

It is the caller’s responsibility to update the reference count of the input and output vectors after the operation.

Parameters:
  • top – The top vector.

  • bottom – The bottom vector.

  • bottom_num_qubits – The number of qubits of the bottom vector.

  • increment_index – Whether to increment the indexes of the top vector.

Returns:

The Kronecker product of the two vectors.

matrix_kronecker(top: MatrixDD, bottom: MatrixDD, bottom_num_qubits: int, increment_index: bool = True) → MatrixDD

Compute the Kronecker product of two matrices.

Notes

It is the caller’s responsibility to update the reference count of the input and output matrices after the operation.

Parameters:
  • top – The top matrix.

  • bottom – The bottom matrix.

  • bottom_num_qubits – The number of qubits of the bottom matrix.

  • increment_index – Whether to increment the indexes of the top matrix.

Returns:

The Kronecker product of the two matrices.

partial_trace(mat: MatrixDD, eliminate: Sequence[bool]) → MatrixDD

Compute the partial trace of a matrix.

Parameters:
  • mat – The matrix.

  • eliminate – The qubits to eliminate. Must be at least as long as the number of qubits of the matrix.

Returns:

The partial trace of the matrix.

trace(mat: MatrixDD, num_qubits: int) → complex

Compute the trace of a matrix.

Parameters:
  • mat – The matrix.

  • num_qubits – The number of qubits of the matrix.

Returns:

The trace of the matrix.

class BasisStates

Bases: enum.Enum

Enumeration of basis states.

zero = 0

The computational basis state \(|0\rangle\).

one = 1

The computational basis state \(|1\rangle\).

plus = 2

The superposition state \(|+\rangle = \frac{1}{\sqrt{2}} (|0\rangle + |1\rangle)\).

minus = 3

The superposition state \(|-\rangle = \frac{1}{\sqrt{2}} (|0\rangle - |1\rangle)\).

right = 4

The superposition state \(|R\rangle = \frac{1}{\sqrt{2}} (|0\rangle - i |1\rangle)\).

left = 5

The superposition state \(|L\rangle = \frac{1}{\sqrt{2}} (|0\rangle + i |1\rangle)\).