Quantum states — Representation and Programming

Navaneeth Dinesh
Analytics Vidhya
Published in
7 min readMar 27, 2021

--

Image Courtesy:
Andrew Daley’s — University of Strathclyde

The previous articles on Linear Algebra might have been a bit boring to at least some of you, especially since it was covering topics from various parts of Quantum mechanics and computing. Time to put it all into a form that finally makes some sense. And good news for all the programmers out there, we will finally get to code in this article. So let’s get the party started.

Remember the 2 qubit states, |0⟩ and |1⟩, that we had introduced in Linear Algebra Part 1. For the forgetful ones, they were introduced as bases (singular — basis), more specifically, as orthonormal bases. Mathematically they can be represented as:

But wait! From where did the term “orthonormal” suddenly pop into existence?

Don’t worry we will cover that in a bit. Clearly |0⟩ and |1⟩ are bases, which means that they form a linearly independent spanning set that spans the Hilbert space. This implies that they are normalized, i.e,

By orthonormality, we mean that these vectors are not just normalized but orthogonal to each other as well.

Intuitively, just like we can represent any line on a cartesian plane using the x and y-axis that are perpendicular to each other, we can also represent any quantum state in 2D space using the |0⟩ and |1⟩ bases, through vector addition and scalar multiplication.

and n_bimage courtesy: Qiskit textbook

Now let q₀ be a qubit with its state vector represented by

Such a linear combination has a fancy name in quantum mechanics called superposition. We can say that such a superposed state is neither entirely |0⟩ nor entirely |1⟩. Here the amplitudes, α, and β, are directly related to the probabilities of measuring the state |q₀⟩ in any qubit state. This relation is given by one of the key postulates in quantum mechanics called the Born rule.

According to the Born rule, the probability of measuring a state |ψ⟩ in any qubit state |x⟩ is given by

Thus, for a state |q₀⟩ given by

the probability that it will collapse into |1⟩ on measurement can be calculated as follows using the Born rule

The normalization condition that we had discussed in the Linear Algebra article is a direct implication of this rule.

Ok, enough theory for now. Let's get started with some programming. We will code using an open-source SDK called qiskit. To install qiskit you can follow this tutorial.

First of all, let us explore how the states, that we had discussed above, can be represented in qiskit programming. To achieve this we will build what is known as a Quantum circuit. A Quantum circuit has three parts to it:

  1. encoding the input
  2. performing computation, and
  3. extracting the output.

Let us take a simple example of a NOT gate to understand how this is done. The truth table of a NOT gate is given as follows

Notice that whatever be the input, the output is the flipped version of the input. However, one should note that this is a classical NOT gate. The quantum analog of NOT gate is called the Pauli X gate or simply the X gate (We will cover more about gates in another article).

Encoding the input

The X gate just like the NOT gate takes 1 input and gives 1 output. Hence the number of qubits we need, to encode the input, is one. The term ‘qubit’ is emphasized in the previous statement because we are basically providing a qubit state, like |0⟩ or |1⟩, as the input to the circuit and not single bits like 0 or 1. Now, let’s import the necessary modules.

from qiskit import QuantumCircuit, assemble, Aer
from qiskit.visualization import plot_histogram

We will use ‘QuantumCircuit’ from qiskit to build our circuit. ‘assemble’ and ‘Aer’ will be used for assembling the code and setting up our quantum simulator. ‘plot_histogram’ will be used for viewing the results. We will explain them in detail, as we code.

Earlier, we saw that we have to give one input to the quantum circuit to implement the X gate. A quantum circuit with one input can be created as follows

n_q = 1
n_b = 1
qc = QuantumCircuit(n_q,n_b)

The number n_q defines the number of qubits in the circuit. With n_b, we define the number of output bits we will extract from the circuit at the end. For an X gate, both n_q and n_b are 1.

In our quantum circuit, qubits always start out in the state |0⟩. However, we can use the initialize() method to transform this into any state. We will see how it’s done once we build our circuit.

Performing computation

The computation here to be performed is flipping of qubit states, i.e, if input state is |0⟩ then output state would be |1⟩ and vice versa. For applying the bit-flip gate or the X gate on the only qubit in the circuit, we use the method x().

qc.x(0)

The above command will apply the X gate on the 0th qubit in the quantum circuit. Now you know why we pass 0 to the x() method. If there were 2 qubits in our circuit and we had to perform the Pauli X gate operation on the 2nd qubit, we would pass 1 to the x() method since the qubits are numbered from zero.

But how does the circuit so far look like? Let’s see with the following command.

qc.draw(output='mpl')

The output of this command would be

Extracting the output

The final task is to extract and visualize the output. This extraction is done using an operation called measure. Each measurement tells a specific qubit to give an output to a specific output bit. Let’s add the measure operation to our qubit in the circuit.

qc.measure(0,0)

This extracts the output of the 0th qubit into the 0th bit. If we invoke the draw() method at this point, our circuit looks like this:

Time to see the output! We execute this set of commands to see the results:

# this is the simulator we'll use
sim = Aer.get_backend('qasm_simulator')
# this turns the circuit into an object our backend can run
qobj = assemble(qc)
# we run the experiment and get the result from that experiment
# from the results, we get a dictionary containing the number of
# times (counts) each result appeared
result = sim.run(qobj).result()
counts = result.get_counts()
# and display it on a histogram
plot_histogram(counts)

Notice that the probability of the output 1, is equal to 1. This is consistent with what we have learned since |0⟩ is flipped to|1 ⟩. But why probability? It could have directly produced the output 1 right? This is because quantum computers may have some randomness in their results. Hence they are run many times and the result is shown as a histogram. Also note that this result comes from a quantum simulator, which is a standard computer calculating what an ideal quantum computer would do.

Now that we have tried for input |0⟩ let’s try it for input |1⟩. We know that,

To initialize the starting state to be |1⟩, we do the following:

qc = QuantumCircuit(1,1)  # Create a quantum circuit with one qubitinitial_state = [0,1]   # Define initial_state as |1>qc.initialize(initial_state, 0) # Apply initialisation operation to the 0th qubitqc.draw()  # Let's view our circuit

The corresponding output would be

Applying the X gate and proceeding the same way we did for the previous circuit gives us the following result:

qc.x(0)
qc.measure(0,0)
qc.draw(output='mpl')
sim = Aer.get_backend('qasm_simulator')  
qobj = assemble(qc)
result = sim.run(qobj).result()
counts = result.get_counts()
plot_histogram(counts)

Notice that here the probability of the output 0, is equal to 1. This in turn validates our previous discussion since the qubit state|1⟩ is flipped to|0⟩.

Now that was a very simple example. We will build more complex circuits once we learn a bit more about quantum gates. So until then, Stay hungry Stay Foolish!!!

Reference:

  1. Qiskit textbook — https://qiskit.org/textbook/ch-states/atoms-computation.html
  2. Qiskit textbook — https://qiskit.org/textbook/ch-states/representing-qubit-states.html

--

--

Navaneeth Dinesh
Analytics Vidhya

Artificial Intelligence | Machine learning | Quantum Computing