Quantum States
Attention
This section is under construction.
This section explains how quantum states are represented in Unitair. To work with Unitair comfortably, it’s necessary to understand a subset of this section. At minimum, a user should understand
Basics of
torch.Tensorobjects
Important
It cannot be emphasized enough that Unitair is not particularly
object-oriented and that there are no QuantumCircuit or
QuantumState classes. “Everything is a tensor” is a key principle, and
a downside to this principle having to get used to our conventions.
If you prefer to learn by playing around with functions, we recommend looking at
rand_stateunit_vectorunit_vector_from_bitstring
all of which are in the unitair.initializations module.
Computational Basis Order
The Hilbert space for \(n\) qubits is \({\bf C}^{2^n}\); it has \(2^n\) dimensions so there are \(2^n\) basis vectors. This is a quantum analogue of the statement that \(n\) bits have \(2^n\) possible values.
For two qubits, the “computational basis vectors” are \(\ket{00}, \ket{01}, \ket{10}, \ket{11}\). When it comes to bases, order matters, and Unitair adopts the convention that basis elements go in the order of standard binary counting. For example:
(We are not concerned here with writing states as column vectors.) Not all quantum computing references and software tools use this basis order.
Now consider an arbitrary pure quantum state \(\psi\) for \(n\) qubits. We can write \(\psi\) as a unique linear combination of computational basis vectors with complex coefficients:
where each \(\alpha_x\) is complex and somewhat confusingly, the index \(x\) runs over all binary strings
By keeping with this ordering, we can represent \(\psi\) with a vector as in
In this equation, we are using, e.g., \(\alpha_3\) instead of writing \(\alpha_{(0,0,\ldots,0,1,1)}\) to keep notation readable. (This is a small abuse of notation.)
Examples
Example 1
The quantum state \(\ket{00}\) should be represented in Unitair as
tensor([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j])
Example 2
The entangled state
corresponds to
tensor([ 0.+0.j, 0.7071+0.j, -0.7071+0.j, 0.+0.j])
Example 3
The state
corresponds to
tensor([0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
0.+0.j, 0.+0.j, 0.5403+0.8415j, 0.+0.j,])
Tip
You may find unit_vector_from_bitstring convenient
when experimenting with states. For example
>>> unit_vector_from_bitstring('01')
tensor([0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j])
We only recommend using this function for experimentation
as it isn’t as fast as unit_vector.
Batch Dimensions
States in Unitair allow for arbitrary batch dimensions. Batched states can have size
where \(B\) is some positive integer. More generally, there can be an arbitrary number of batch dimensions so that states have size
This is the most general form of the size of a state. A PyTorch Tensor
object with this size is referred to, in the Unitair context, as
a state in vector layout.
Note
The concept of “vector layout” refers to the \(2^n\) at the end of the size, which casts individual quantum states as a vector with one index (ignoring batches). Unitair also uses, especially internally, a tensor layout where the dimension with length \(2^n\) is reshaped to have \(n\) indices, each of which runs over two values.
Examples
Example 1
The two Bell pairs
can be written constructed as a batch:
tensor([[ 0.7071+0.j, 0.+0.j, 0.+0.j, 0.7071+0.j],
[ 0.7071+0.j, 0.+0.j, 0.+0.j, -0.7071+0.j]])
Example 2
When dealing with lots of batch entries and qubits, tensors can quickly get very large.
from unitair.initializations import rand_state
state_batch = rand_state(
num_qubits=10,
batch_dims=(30, 5),
)
print(state_batch.size())
torch.Size([30, 5, 1024])