Qiskit implementation
In this section, we'll take a look at some Qiskit implementations of the concepts introduced in this lesson. If you wish to run these implementations yourself, which is strongly encouraged, consult the Install Qiskit page in the IBM Quantum Documentation for details on how to set up Qiskit.
It should be understood that Qiskit is under continual development, and is principally focused on maximizing the performance of the quantum computers it is used to operate, which themselves continue to evolve. As a result, Qiskit is subject to changes that may occasionally lead to code deprecation. With this in mind, we'll always execute the following commands prior to presenting examples of Qiskit code in this course, so that it is clear which version of Qiskit has been used. Starting with Qiskit v1.0, this is a simple way to see what version of Qiskit is currently installed.
from qiskit import __version__
print(__version__)
2.1.1
If you are running this in a cloud-based Python environment, you might need to install some of the following packages:
#!pip install qiskit
#!pip install jupyter
#!pip install sympy
#!pip install matplotlib
#!pip install pylatexenc
Vectors and matrices in Python
Qiskit uses the Python programming language, so before discussing Qiskit specifically, it may be helpful to very briefly discuss matrix and vector computations in Python.
In Python, matrix and vector computations can be performed using the array class from the NumPy library, which provides functionality for many numerical and scientific computations.
The following code loads this library, defines two column vectors, ket0 and ket1, corresponding to the qubit state vectors and and then prints their average.
import numpy as np
ket0 = np.array([[1], [0]])
ket1 = np.array([[0], [1]])
print(ket0 / 2 + ket1 / 2)
[[0.5]
[0.5]]
We can also use array to create matrices that can represent operations.
M1 = np.array([[1, 1], [0, 0]])
M2 = np.array([[1, 0], [0, 1]])
M = M1 / 2 + M2 / 2
print(M)
[[1. 0.5]
[0. 0.5]]
Please note that all code appearing within a given lesson in this course is expected to be run sequentially.
Therefore, we don't need to import NumPy again here, because it has already been imported.
Matrix multiplication, including matrix-vector multiplication as a special case, can be performed using the matmul function from NumPy.
print(np.matmul(M1, ket1))
print(np.matmul(M1, M2))
print(np.matmul(M, M))
[[1]
[0]]
[[1 1]
[0 0]]
[[1. 0.75]
[0. 0.25]]
This output formatting leaves something to be desired, visually speaking.
One solution, for situations that demand something prettier, is to use thearray_to_latex function in Qiskit, from the qiskit.visualization module.
Note that, in the code that follow, we're using Python's generic display function.
In contrast, the specific behavior of print may depending on what is printed, such as it does for arrays defined by NumPy.
from qiskit.visualization import array_to_latex
display(array_to_latex(np.matmul(M1, ket1)))
display(array_to_latex(np.matmul(M1, M2)))
display(array_to_latex(np.matmul(M, M)))
States, measurements, and operations
Qiskit includes several classes that allow for states, measurements, and operations to be created and manipulated — so there is no need to program everything required to simulate quantum states, measurements, and operations in Python. Some examples to help you to get started are included below.
Define and display state vectors
TheStatevector class in Qiskit provides functionality for defining and manipulating quantum state vectors.
In the code that follows, the Statevector class is imported and a few vectors are defined.
(We're also importing the sqrt function from the NumPy library to compute a square root.
This function could, alternatively, be called as np.sqrt provided that NumPy has already been imported, as it has above; this is merely a different way to import and use this specific function alone.)
from qiskit.quantum_info import Statevector
from numpy import sqrt
u = Statevector([1 / sqrt(2), 1 / sqrt(2)])
v = Statevector([(1 + 2.0j) / 3, -2 / 3])
w = Statevector([1 / 3, 2 / 3])
The Statevector class includes a draw method for displaying state vectors in a variety of ways, including
text for plain text, latex for rendered LaTeX, and latex_source for LaTeX code, which can be handy for cutting and pasting into documents.
(Use print rather than display to show LaTeX code for best results.)
display(u.draw("text"))
display(u.draw("latex"))
print(u.draw("latex_source"))
[0.70710678+0.j,0.70710678+0.j]
\frac{\sqrt{2}}{2} |0\rangle+\frac{\sqrt{2}}{2} |1\rangle
The Statevector class also includes the is_valid method, which checks to see if a given vector is a valid quantum state vector (in other words, that it has Euclidean norm equal to 1):
display(u.is_valid())
display(w.is_valid())
True
False
Simulating measurements using Statevector
Next we will see one way that measurements of quantum states can be simulated in Qiskit, using the measure method from the Statevector class.
Let's use the same qubit state vector v defined previously.
display(v.draw("latex"))
Running the measure method simulates a standard basis measurement.
It returns the outcome of that measurement, plus the new quantum state vector of the system after the measurement.
(Here we're using Python's print function with an f prefix for formatted printing with embedded expressions.)
outcome, state = v.measure()
print(f"Measured: {outcome}\nPost-measurement state:")
display(state.draw("latex"))
Measured: 1
Post-measurement state:
Measurement outcomes are probabilistic, so this method can return different results when run multiple times.
For the particular example of the vector v defined above, the measure method defines the quantum state vector after the measurement takes place to be
(rather than ) or
(rather than ), depending on the measurement outcome. In both cases, the alternatives to and