MultiQubitDual

class MultiQubitDual(list_operators: list[Operator])[source]

Bases: MultiQubitFrame, BaseDual

Class that collects all information that any Dual over multiple qubits should specify.

This is a representation of a dual frame. Its elements are specified as a list of Operator.

Initialize from explicit operators.

Parameters:

list_operators (list[Operator]) – list that contains the explicit frame operators. The length of the list is the number of operators of the frame.

Raises:

ValueError – if the frame operators do not have a correct shape. They should all be hermitian and of the same dimension.

Inherited Attributes

dimension

The dimension of the Hilbert space on which the effects act.

informationally_complete

If the frame spans the entire Hilbert space.

num_operators

The number of effects of the frame.

num_outcomes

The number of outcomes of the Dual.

num_subsystems

The number of subsystems which the frame operators act on.

For qubits, this is always \(\log_2(\)dimension\()\).

operators

Return the list of frame operators.

pauli_operators

Convert the internal frame operators to Pauli form.

Warning

The conversion to Pauli form can be computationally intensive.

Returns:

The frame operators in Pauli form. Each frame operator is returned as a dictionary mapping Pauli labels to coefficients.

Raises:

ValueError – when the frame operators could not be converted to Pauli form (e.g. when they are not N-qubit operators).

Methods

classmethod build_dual_from_frame(frame: BaseFrame, alphas: tuple[float, ...] | None = None) MultiQubitDual[source]

Construct a dual frame to another (primal) frame.

Parameters:
  • frame (BaseFrame) – The primal frame from which we will build the dual frame.

  • alphas (tuple[float, ...] | None) – parameters of the frame super-operator used to build the dual frame. If None, the parameters are set as the traces of each operator in the primal frame.

Returns:

A dual frame to the supplied frame.

Return type:

MultiQubitDual

is_dual_to(frame: BaseFrame) bool[source]

Check if self is a dual to another frame.

Parameters:

frame (BaseFrame) – the other frame to check duality against.

Returns:

Whether self is dual to frame.

Return type:

bool

Inherited Methods

analysis(hermitian_op: SparsePauliOp | Operator, frame_op_idx: int | set[int] | None = None) float | dict[int, float] | ndarray

Return the frame coefficients of hermitian_op.

This method implements the analysis operator \(A\) of the frame \(\{F_k\}_k\):

\[A: \mathcal{O} \mapsto \{ \mathrm{Tr}\left[F_k \mathcal{O} \right] \}_k,\]

where \(c_k = \mathrm{Tr}\left[F_k \mathcal{O} \right]\) are called the frame coefficients of the Hermitian operator \(\mathcal{O}\).

Parameters:
  • hermitian_op (SparsePauliOp | Operator) – a hermitian operator whose frame coefficients to compute.

  • frame_op_idx (int | set[int] | None) – label or set of labels indicating which coefficients are queried. If None, all coefficients are queried.

Returns:

Frame coefficients, specified by frame_op_idx, of the Hermitian operator hermitian_op. If a specific coefficient was queried, a float is returned. If a specific set of coefficients was queried, a dictionary mapping labels to coefficients is returned. If all coefficients were queried, an array with all coefficients is returned.

Raises:
  • TypeError – when the provided single or sequence of labels frame_op_idx does not have a valid type.

  • ValueError – when the dimension of the provided hermitian_op does not match the dimension of the frame operators.

Return type:

float | dict[int, float] | ndarray

classmethod from_vectors(frame_vectors: ndarray) Self

Initialize a frame from non-normalized bloch vectors.

The non-normalized Bloch vectors are given by \(|\tilde{\psi}_k \rangle = \sqrt{\gamma_k} |\psi_k \rangle\). The resulting frame operators are \(F_k = \gamma_k |\psi_k \rangle \langle \psi_k |\) where \(\gamma_k\) is the trace of the \(k\)’th frame operator.

Parameters:

frame_vectors (ndarray) – list of vectors \(|\tilde{\psi_k} \rangle\). The length of the list corresponds to the number of operators of the frame. Each vector is of shape \((\mathrm{dim},)\) where \(\mathrm{dim}\) is the dimension of the Hilbert space on which the frame acts.

Returns:

The frame corresponding to the vectors.

Return type:

Self

get_omegas(observable: SparsePauliOp | Operator, outcome_idx: LabelT | set[LabelT] | None = None) float | dict[LabelT, float] | ndarray

Return the decomposition weights of the provided observable.

Computes the \(\omega_k\) in

\[\mathcal{O} = \sum_{k=1}^n \omega_k M_k\]

where \(\mathcal{O}\) is the observable and \(M_k\) are the effects of the POVM of which self is the dual. The closed form for computing \(\omega_k\) is

\[\omega_k = \text{Tr}\left[\mathcal{O} D_k\right]\]

where \(D_k\) make of this dual frame (i.e. self).

Note

In the frame theory formalism, the mapping \(A: \mathcal{O} \mapsto \{\text{Tr}\left[\mathcal{O} D_k\right]\}_k\) is referred to as the analysis operator, which is implemented by the analysis() method.

Parameters:
  • observable (SparsePauliOp | Operator) – the observable for which to compute the decomposition weights.

  • outcome_idx (LabelT | set[LabelT] | None) – label or set of labels indicating which decomposition weights are queried. If None, all weights are queried.

Returns:

Decomposition weight(s) associated to the effect(s) specified by outcome_idx. If a specific outcome was queried, a float is returned. If a specific set of outcomes was queried, a dictionary mapping outcome labels to weights is returned. If all outcomes were queried, an array with all weights is returned.

Return type:

float | dict[LabelT, float] | ndarray