Many qubits
Two qubits do not have 2 amplitudes each; together they have 4. Every extra qubit doubles the count, and that doubling is both the power of quantum computing and the reason simulators run out of memory.
The basis states
Two qubits have four basis states, one for each pair of classical values:
and a general state is a combination of all four:
With qubits there are basis states and amplitudes. qsengine stores each as two 64-bit numbers, 16 bytes, so 20 qubits take 16 MiB and 30 take 16 GiB.
Combining qubits: the tensor product
When qubits are independent, the joint state is their tensor product, written . Each amplitude of the result is a product of one amplitude from each qubit:
A Hadamard on each of two qubits gives every basis state the same amplitude, :
import qsengine
qc = qsengine.QuantumCircuit(2)
qc.h(0)
qc.h(1)
print(qc.probabilities())
print(qc.run(shots=1000, seed=5))Output
[0.25 0.25 0.25 0.25]
{'10': 262, '00': 235, '11': 245, '01': 258}Four outcomes, each about a quarter of the time: two independent coin flips.
Which bit is which
In , qsengine reads the rightmost digit as qubit 0, like Qiskit. So flipping qubit 0 of two gives , which is basis index 1:
qc = qsengine.QuantumCircuit(2)
qc.x(0)
print(qc.statevector())
print(qc.run(shots=100, seed=0))Output
[0.+0.j 1.+0.j 0.+0.j 0.+0.j]
{'01': 100}Amplitude 1 at index 1, and every shot reads 01.
Running circuits has the same rule for the arrays qsengine returns.
Gates on one qubit of many
A single-qubit gate on qubit acts as the tensor product of that gate with the identity on every other qubit. qsengine never builds that matrix: it updates the amplitudes in pairs, which is why it stays fast at 20 qubits and beyond.
Not every two-qubit state can be written as a tensor product. The ones that cannot are entangled.