Qubit Hilbert Spaces

States, gates, and various other methods accept a list of qubits labels upon which the given State or Gate acts. A Qubit label can be any hashable python object, but typically an integer or string. e.g. [0, 1, 2], or [‘a’, ‘b’, ‘c’]. Note that some operations expect the qubits to be sortable, so don’t mix different uncomparable data types.

class quantumflow.QubitVector(tensor: TensorLike, qubits: Qubits, rank: int = None)

A container for a tensor representation of a quantum state or operation on qubits. The QubitTensor contains a list of qubits, and a backend complex tensor in product form.

The rank of the quantum tensor represents the order of the quantum state of operation:

1   vectors
2   operators
4   super-operators
8   super-duper-operators

A vector is an element of a vector space. An operator (normally represented by a 2 dimensional matrix) is a linear map on a vector space. Super-operators are operators of operators – linear maps on the vector space of operators. Similarly rank 8 super-duper operators are operators of super-operators.

Pure states are represented by vectors; gates and mixed states by rank 2 operators; and quantum channels by rank 4 super-operators.

A tensor of rank R on N qubits is stored as a tensor product with (N*R) dimensions, each of length 2. (Except for scalers, rank=0, which have only a single element) In other words the shape of the tensor array is [2]*(N*R). This representation is convenient for addressing individual qubits (e.g. For a state of 4 qubits, the state amplitude of 0110 is located in tensor element [0,1,1,0])

A quantum logic gate is a unitary operator acting on a collection of K qubits, which can be represented by a matrix of shape (2**K, 2**K). This operator is stored as a mixed tensor of shape ([2]*(2*K)). e.g. for 4 qubits, the gate shape is (2, 2, 2, 2, 2, 2, 2, 2). Gates have ket and bra components, which are ordered kets then bras, e.g. gate[k0, k1, k2, k3, b0, b1, b2, b3]. This is so we can go back and forth between the product tensor and more common matrix representations with a simple reshape.:

operator_matrix = np.reshape(gate_tensor, shape=(2**K, 2**K))
gate_tensor = np.reshape(operator_matrix, shape=([2]*(2*K))

The indices of superoperators are ordered [ket_out, bra_out, bra_in, ket_in].

  • qubits – A sequence of qubit labels
  • array – An tensor or tensor like object
  • qubits – Qubit labels
  • qubit_nb – The number of qubits
  • rank – Order of the tensor, which has (qubit_nb*rank) dimensions

Return the conjugate transpose of this tensor.

asarray() → numpy.ndarray

Return the tensor as a numpy array

flatten() → BKTensor

Return tensor with with qubit indices flattened

norm() → BKTensor

Return the norm of this vector

partial_trace(qubits: Qubits) → qf.QubitVector

Return the partial trace over some subset of qubits

permute(qubits: Qubits) → qf.QubitVector

Permute the order of the qubits

relabel(qubits: Qubits) → qf.QubitVector

Return a copy of this vector with new qubits

trace() → BKTensor

Return the trace, the sum of the diagonal elements of the (super) operator.