unitaria.Node

class unitaria.Node(dimension_in: int, dimension_out: int)[source]

Bases: ABC

Abstract class for all nodes in the computational graph

The encoded vector or the action of the encoded matrix can be obtained either through matrix arithmetic using compute or as a quantum block encoding using circuit, normalization, subspace_in, and subspace_out.

When creating your own subclass of Node, you should implement the functions _subspace_in, _subspace_out, _normalization, _circuit, compute, and compute_adjoint. Potentially also children and parameters.

Note the prefixed underscores for some of these methods, which are necessary due to how the properties of Node are cached.

To check that these methods are implemented correctly, use verify.

As an alternative if you can represent your custom node in terms of other nodes, and just want to provide a more efficient implementation of some of the functions – say compute and compute_adjoint – you can instead create a subclass of ProxyNode.

abstractmethod _circuit(target: Sequence[int], clean_ancillae: Sequence[int], borrowed_ancillae: Sequence[int]) Circuit[source]

Method for computing circuit.

To be implemented in all subclasses of Node.

abstractmethod _normalization() float[source]

Method for computing normalization.

To be implemented in all subclasses of Node.

abstractmethod _subspace_in() Subspace[source]

Method for computing subspace_in.

To be implemented in all subclasses of Node.

abstractmethod _subspace_out() Subspace[source]

Method for computing subspace_out.

To be implemented in all subclasses of Node.

adjoint()
abstractmethod borrowed_ancilla_count() int[source]

Returns the number of borrowed ancillae used by the circuit of this node, i.e. qubits that can be in any state and will be returned to this state by the end of the circuit.

children() list[Node][source]

The children nodes of this node

Mostly used for serialization and systematic verification of the computational graph. Children and parameters together should fully define the matrix encoded by any node.

circuit(target: Sequence[int] = None, clean_ancillae: Sequence[int] = None, borrowed_ancillae: Sequence[int] = None) Circuit[source]

The circuit corresponding to the unitary of the block encoding.

Qubit indices for the target and ancillae can be passed via arguments, otherwise the default is simply use the indices 0, 1, … in the order target, clean_ancillae, borrowed_ancillae. If indices are passed, the length of the ancillae needs to match the values returned by clean_ancillae_count() and borrowed_ancillae_count().

abstractmethod clean_ancilla_count() int[source]

Returns the number of borrowed ancillae used by the circuit of this node, i.e. qubits that must be in state |0> at the beginning of the circuit and will be returned to this state by the end of the circuit.

abstractmethod compute(input: ndarray) ndarray[source]

Apply the action of this nodes matrix to the input.

If this node encodes a vector, then input = None is valid, in which case the method should simply return the encoded vector.

Input may be a vector or a higher order tensor. If it is a vector it will have dimension equal to the dimension of qubits_in. If it is a tensor, the last dimension will be equal to the dimension of qubits_in. In this case, the operation should be applied to all vectors input[i, j, ..., k, :] in parallel. The shape of the returned array should match the input shape in all but the last dimension.

abstractmethod compute_adjoint(input: ndarray) ndarray[source]

Apply the adjoint action of this nodes matrix to the input.

See compute for input and output formats.

compute_norm(input: np.array | None = None) float[source]

Method to compute the norm of this vector given the arithmetic definition of this node using compute.

draw(verbose: bool = False) str[source]

Rich text output of the computational graph

Parameters:

verbose – if set to True, the definition of any ProxyNode is inserted into the

is_guaranteed_unitary() bool[source]

If this returns true, the matrix the node represents divided by its normalization must be unitary.

This must be ensured by the implementor of this method. A unitary node is useful, since it avoids having to use projections in multiplications.

is_vector() bool[source]

Tests whether this node encodes a vector or a matrix.

parameters() dict[source]

The parameters of this graph

Mostly used for serialization and systematic verification of the computational graph. Children and parameters together should fully define the matrix encoded by any node.

simulate(input: int | None = None) ndarray[source]

Returns a numpy array representing this node, as given by simulate.

When input is None, the output of this method should match compute, which can be checked using verify.

Parameters:

input – The index of the optional initial state, with which this node should be simulated. Should be a number between 0 and node.dimension_out - 1

simulate_norm(input: int | None = None) float[source]

Method to simulate the norm of the encoded vector in the subspace using a circuit.

When calling this function on a node encoding a matrix, input has to be a vector. In this case the norm of the matrix applied to input is given.

Parameters:

input – A vector to which the encoded matrix is applied before computing the norm.

target_qubit_count() int[source]
toarray(force_matrix: bool = False) ndarray[source]

Returns a numpy array representing this node, as given by compute.

The output of this method should match simulate, which can be checked using verify.

By default this will return a one-dimension array if the node represents a vector. However, this behaviour can be suppressed by setting force_matrix = True

Parameters:

force_matrix – Force the method to return a two-dimensional array, even when the node corresponds to a vector.

tree(verbose: bool = False, tree: Tree | None = None, holes: list[Node] = []) Tree[source]

Method for rich text output of the computational graph.

Typically you should call draw instead of this method.

tree_label(verbose: bool = False)[source]

Label by which this node should be represented in textual (debug) output.

Defaults to the name of the nodes class plus its parameters.

_cached_circuit[source]

Calls _circuit with target, clean_ancillae and borrowed_ancillae being the qubits 0, 1, … so that the result can be cached. This is then mapped by circuit to the actually requested qubit indices.

normalization[source]

Normalization of the block encoding.

Non-negative number, which has to be multiplied with the outputs of the circuit to ensure proper scaling of the result.

subspace_in[source]

The embedding of the input vectorspace.

Specifically this specifies how the vectorspace is included in state space nodes circuit, which has dimension 2^n where n is the number of qubits. In other words, this defines whether a particular basis state is “valid” or “invalid”.

In the formalism of block encodings this corresponds to the projection \Pi_1.

subspace_out[source]

The embedding of the output vectorspace.

Specifically this specifies how the vectorspace is included in state space nodes circuit, which has dimension 2^n where n is the number of qubits. In other words, this defines whether a particular basis state is “valid” or “invalid”.

In the formalism of block encodings this corresponds to the projection \Pi_2.