Skip to main contentIBM Quantum Documentation Mirror

Qiskit implementation

In the previous lesson, we took a first look at the Statevector and Operator classes in Qiskit, and used them to simulate operations and measurements on single qubits. In this section, we'll use these classes to explore the behavior of multiple qubits.

from qiskit import __version__
 
print(__version__)

Output:

2.1.1

We'll start by importing the Statevector and Operator classes, as well as the square root function from NumPy. Hereafter, generally speaking, we'll take care of all of our required imports first within each lesson.

from qiskit.quantum_info import Statevector, Operator
from numpy import sqrt

Tensor products

The Statevector class has a tensor method, which returns the tensor product of that Statevector with another, given as an argument. The argument is interpreted as the tensor factor on the right.

For example, below we create two state vectors representing 0\vert 0\rangle and 1,\vert 1\rangle, and use the tensor method to create a new vector, ψ=01.\vert \psi\rangle = \vert 0\rangle \otimes \vert 1\rangle. Notice here that we're using the from_label method to define the states 0\vert 0\rangle and 1,\vert 1\rangle, rather than defining them ourselves.

zero = Statevector.from_label("0")
one = Statevector.from_label("1")
psi = zero.tensor(one)
display(psi.draw("latex"))

Output:

01 |01\rangle

Other allowed labels include "+" and "-" for the plus and minus states, as well as "r" and "l" (short for "right" and "left") for the states

+i=120+i20andi=120i20.\vert {+i} \rangle = \frac{1}{\sqrt{2}} \vert 0 \rangle + \frac{i}{\sqrt{2}} \vert 0 \rangle \qquad\text{and}\qquad \vert {-i} \rangle = \frac{1}{\sqrt{2}} \vert 0 \rangle - \frac{i}{\sqrt{2}} \vert 0 \rangle.

Here's an example of the tensor product of +\vert {+} \rangle and i.\vert {-i} \rangle.

plus = Statevector.from_label("+")
minus_i = Statevector.from_label("l")
phi = plus.tensor(minus_i)
display(phi.draw("latex"))

Output:

1200i201+1210i211\frac{1}{2} |00\rangle- \frac{i}{2} |01\rangle+\frac{1}{2} |10\rangle- \frac{i}{2} |11\rangle

An alternative is to use the ^ operation for tensor products, which naturally gives the same results.

display((plus ^ minus_i).draw("latex"))

Output:

1200i201+1210i211\frac{1}{2} |00\rangle- \frac{i}{2} |01\rangle+\frac{1}{2} |10\rangle- \frac{i}{2} |11\rangle

The Operator class also has a tensor method (as well as a from_label method), as we see in the following examples.

H = Operator.from_label("H")
Id = Operator.from_label("I")
X = Operator.from_label("X")
display(H.tensor(Id).draw("latex"))
display(H.tensor(Id).tensor(X).draw("latex"))

Output:

[220220022022220220022022] \begin{bmatrix} \frac{\sqrt{2}}{2} & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & \frac{\sqrt{2}}{2} \\ \frac{\sqrt{2}}{2} & 0 & - \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & - \frac{\sqrt{2}}{2} \\ \end{bmatrix} [02200022002200022000000220002200220002200220002200220002200000022000220022000220] \begin{bmatrix} 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 \\ \end{bmatrix}

Again, like in the vector case, the ^ operation is equivalent.

display((H ^ Id ^ X).draw("latex"))

Output:

[02200022002200022000000220002200220002200220002200220002200000022000220022000220] \begin{bmatrix} 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 \\ 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 \\ \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 & 0 & 0 \\ 0 & 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} \\ 0 & 0 & \frac{\sqrt{2}}{2} & 0 & 0 & 0 & - \frac{\sqrt{2}}{2} & 0 \\ \end{bmatrix}

Compound states can be evolved using compound operations as we would expect — just like we saw for single systems in the previous lesson. For example, the following code computes the state (HI)ϕ(H\otimes I)\vert\phi\rangle for ϕ=+i\vert\phi\rangle = \vert + \rangle \otimes \vert {-i}\rangle (which was already defined above).

display(phi.evolve(H ^ Id).draw("latex"))

Output:

22002i201\frac{\sqrt{2}}{2} |00\rangle- \frac{\sqrt{2} i}{2} |01\rangle

Here is some code that defines a CXCX operation and calculates CXψCX \vert\psi\rangle for ψ=+0.\vert\psi\rangle = \vert + \rangle \otimes \vert 0 \rangle. To be clear, this is a CXCX operation for which the left-hand qubit is the control and the right-hand qubit is the target. The result is the Bell state ϕ+.\vert\phi^{+}\rangle.

CX = Operator([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
psi = plus.tensor(zero)
display(psi.evolve(CX).draw("latex"))

Output:

2200+2211\frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |11\rangle


Partial measurements

In the previous lesson, we used the measure method to simulate a measurement of a quantum state vector. This method returns two items: the simulated measurement result, and the new Statevector given this measurement.

By default, measure measures all qubits in the state vector. We can, alternatively, provide a list of integers as an argument, which causes only those qubit indices to be measured. To demonstrate this, the code below creates the state

w=001+010+1003\vert w\rangle = \frac{\vert 001\rangle + \vert 010\rangle + \vert 100\rangle}{\sqrt{3}}

and measures qubit number 0, which is the rightmost qubit. (Qiskit numbers qubits starting from 0, from right to left. We'll return to this numbering convention in the next lesson.)

w = Statevector([0, 1, 1, 0, 1, 0, 0, 0] / sqrt(3))
display(w.draw("latex"))
 
result, state = w.measure([0])
print(f"Measured: {result}\nState after measurement:")
display(state.draw("latex"))
 
result, state = w.measure([0, 1])
print(f"Measured: {result}\nState after measurement:")
display(state.draw("latex"))

Output:

33001+33010+33100\frac{\sqrt{3}}{3} |001\rangle+\frac{\sqrt{3}}{3} |010\rangle+\frac{\sqrt{3}}{3} |100\rangle

Measured: 0
State after measurement:

22010+22100\frac{\sqrt{2}}{2} |010\rangle+\frac{\sqrt{2}}{2} |100\rangle

Measured: 00
State after measurement:

100 |100\rangle