How to design quantum circuits with Qiskit — Part 2
The second part of the tutorial on designing very simple quantum circuits
Introduction
In my previous post I started a tutorial on how to design quantum circuits with Qiskit. In that post we designed quantum circuits with one qubit and we saw important concepts such as quantum measurement, superposition and also some quantum gates, which included the X-Gate and RY-Gate.
In this post we will design quantum circuits with 2 qubits and we will see quantum superposition and entanglement effects combined in the same set of simulations. We will also use another quantum gates that we haven’t used in the last post.
Circuit 1: Understanding the CNOT Gate
The CNOT-Gate is one of the most important quantum gates in quantum computing, because is the most basic entanglement operator. So let’s test it with a few cases.
Circuit 1a: Both qubits as 0
In our first case we are designing a quantum circuit with two qubits, both of them as 0 and applying a CNOT, with the first as the control qubit and the second as the target (we will understand these concepts later):
from qiskit import QuantumCircuit
from qiskit import Aer
from qiskit.visualization import plot_histogram
import numpy as np
backend = Aer.get_backend('qasm_simulator')
qc = QuantumCircuit(2)
qc.cx(0, 1)
qc.measure_all()
qc.draw('mpl')
job = backend.run(qc, shots=1000)
result = job.result()
counts = result.get_counts(qc)
plot_histogram(counts)
Our circuit is:
And our simulation results are:
In this graphic, the left qubit is the second and the right one is the first.
Nothing changed after applying the CNOT. It doesn’t seem impressive, right? But I promess things will get better on the next cases.
Circuit 1b: Qubit 1 as 1 and qubit 2 as 0
Now we have the following code:
from qiskit import QuantumCircuit
from qiskit import Aer
from qiskit.visualization import plot_histogram
import numpy as np
backend = Aer.get_backend('qasm_simulator')
qc = QuantumCircuit(2)
qc.x(0)
qc.cx(0, 1)
qc.measure_all()
qc.draw('mpl')
job = backend.run(qc, shots=1000)
result = job.result()
counts = result.get_counts(qc)
plot_histogram(counts)
We applied an X-Gate to the first qubit to invert it before applying the CNOT. Now we have the following circuit:
With these results:
This result is more interesting because for all simuation shots, the first qubit remained 1 and second qubit is also 1. So the second qubit was inverted.
But what happens if we have others combinations of values?
Circuit 1c: First qubit as 0 and the second as 1
In this case I will leave the code to you, because we just have to remove the X-Gate from the first qubit and insert it to the second one, before applying the CNOT.
Now we have the following circuit:
With these results:
In this case our quantum states remained the same after applying the CNOT, the second qubit wasn’t inverted. Note that in all cases the first qubit never changed and the second qubit only changed when the first qubit was 1. So let’s check when both qubits are 1.
Circuit 1d: Both qubits as 1
Now we must apply the X-Gate to both qubits before the CNOT, obtaining this circuit:
With the following results for 1000 shots:
Now the second qubit was inverted. Thereby, the CNOT gate is a two qubit operator, involving a target qubit, whose state is kept the same if the control qubit is 0 and it is inverted if the control qubit is 1.
But what happens if these qubits are in superposition?
Circuit 1e: First qubit in superposition and second as 0
In this circuit we are inserting our first qubit into a superposition state using the Hadamard Gate. This is a very basic and also important operator in quantum computing, because it operates as a change of basis in the vector space, making the following transformation from the basis states to a new one:
So, in our case, the first qubit is in the |+> state, which is a superposition state with the same probability of being 0 or 1.
Now, our code is:
from qiskit import QuantumCircuit
from qiskit import Aer
from qiskit.visualization import plot_histogram
import numpy as np
backend = Aer.get_backend('qasm_simulator')
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()
qc.draw('mpl')
job = backend.run(qc, shots=1000)
result = job.result()
counts = result.get_counts(qc)
plot_histogram(counts)
Our circuit is:
With the following results for 1000 shots:
In this case we have a probability of nearly 50% of having the state |00> and nearly 50% of having |11>. But what happened in this circuit? After applying the Hadamard Gate, our control qubit had 50% of chance of being in |0> and 50% of being in |1>. Thereby, for all cases we measured 0 in the first qubit we also has a 0 in the second qubit, resulting in the state |00>. On the other side, for all cases we had the first qubit as 1 we also had the second as 1, resuntling in the state |11> and both scenarios had approximately the same probability.
And what happens if both qubits are in superposition?
Circuit 1f: Both circuits in superposition
Now we will apply the Hadamard Gate to both qubits, obtaining the following circuit:
In this case I increased the number of shots to 10000 to have more precise results:
We obtained nearly the same probability for each state, because the CNOT worked with every combination (|00>, |01>, |10> and |11>) of both qubits with the same probability.
Note that, for all circuits, but mainly 1e and 1f, where we have quantum states in superposition, after applying the CNOT gate, the state of the second qubit inherently depends on the state of the first, we can’t determine the state of the second qubit by itself. This is quantum entanglement. And the same can be said of the first qubit, after applying the CNOT, it is also entangled with the second qubit. If we continue applying quantum gates, we will be altering the combination of states |00>, |01>, |10> and |11> and not each qubit separately. Let’s verify that with our second circuit.
Circuit 2: Verifying quantum entanglement
In this circuit, we are applying a Hadamard in our first qubit, a CNOT on both qubits and an RY-Gate into the second qubit.
from qiskit import QuantumCircuit
from qiskit import Aer
from qiskit.visualization import plot_histogram
import numpy as np
backend = Aer.get_backend('qasm_simulator')
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.ry(np.pi/3, 1)
qc.measure_all()
qc.draw('mpl')
job = backend.run(qc, shots=10000)
result = job.result()
counts = result.get_counts(qc)
plot_histogram(counts)
This is our circuit:
With this result:
Even that the RY-Gate affects only the second qubit, now we are working with a four states vector space and applyng the RY will affect all states.
Conclusions
This was a very simple explation on how CNOT Gate works and we also verified quantum entanglement, which is a very important concept. However, the use of this gate has several implications in other quantum systems, such as the quantum phase kickback. I encourage you to study about this gate deeply, for although it is simple, its use has a series of complex developments.
If you want to dive further in designing quantum circuits, Frank Zickert’s book is also a nice reading, with interesting examples of quantum circuit designs.