Skip to the content.

Episode I: Introduction to Quantum Computing

In this chapter, we will introduce Qiskit and create a basic quantum circuit that:

Quantum Bits (qubits)

As you might know, classical bits are represented with either 0 or 1. For the longest time, we have utilized classical bits for many different applications of computing. However, they contain some limitations–adversaries can copy them.

Quantum computers introduce qubits. As opposed to classical bits, qubits are the fundamental units of quantum information. Unlike classical bits, qubits cannot be copied according to the no-cloning theorem. This will prove to be beneficial in our quantum computing endeavor.

Remember when I mentioned classical bits can be either 0 or 1? What about qubits?

Qubit states

Qubits can be 0, 1, or a superposition of 0 and 1. Their states are represented through ket-notation:

State 0: |0⟩ 
State 1: |1⟩
Superposition: α|0⟩ + β|1⟩ where α and β are probability amplitudes. 

How can this be represented in Qiskit? Let’s hop into the IBM Quantum Lab.

By default, new notebooks in the Quantum Lab only import a handful of standard Qiskit libraries. You’ll want to adjust the first import statement so we can use the ClassicalRegister and QuantumRegister objects. Additionally, import the math module.

from qiskit import QuantumCircuit, execute, Aer, IBMQ, ClassicalRegister, QuantumRegister
import math

Qubits in Qiskit

You can use the QuantumCircuit object to create qubits by passing a number as an argument (the number of qubits you want). For example:

circuit = QuantumCircuit(1, 1) # Creates a quantum circuit with one qubit, one classic bit

Alternatively, you can use the QuantumRegister and ClassicalRegister objects. QuantumRegister is used to create a qubit on the quantum register, and ClassicalRegister is used to create a classical bit on the classical register. These two objects can be passed as arguments to QuantumCircuit to create a circuit.

qubit0 = QuantumRegister(1, name = "qubit0")
classic_bit0 = ClassicalRegister(1, name = "classic_bit0")
circuit = QuantumCircuit(qubit0, classic_bit0)

QuantumRegister and ClassicalRegister take two arguments: a number of qubits/bits, and a label for the circuit drawing.

Initialized states

An important thing to note is that Qiskit always initializes qubits into the state |0⟩. If you want to manually change the initialization state of a qubit, you can use the initialize() method. For example, if we want to intialize one of our qubits to be in the state |1⟩, we can write:

state = [0, 1] # This is a vector in the form of a list: [alpha, beta]
circuit.initialize(state, qubit0) # Initializes qubit0 to state |1⟩

Note that our state is in the form of [alpha, beta]. If you wanted to put your qubit into a superposition, you need to satisfy the property:

|α|^2 + |β|^2 = 1

For example, this is valid:

state = [math.sqrt(1/3), math.sqrt(2/3)]

This is not valid:

state = [math.sqrt(1/4), math.sqrt(1/4)]

For now, let us consider the state: [math.sqrt(1/2), math.sqrt(1/2)]. (This is equivalent to a Hadamard gate…more on that later)

Z measurements

In seminar, you have been introduced to the notion of a Z measurement. Recall that a Z measurement takes a quantum state and maps it to a 0 (with probability α) or 1 (with probability β). Luckily, this is easy to do in Qiskit.

circuit.measure(qubit0, classic_bit0) # Perform Z-measurement on qubit0

At this point, we have:

It’s time to simulate!

image

Simulating

All that’s left to do is to simulate our circuit. This is done through Aer, a standard Qiskit library. Aer will take our circuit and simulate it as many times as we want (in this case, 1000).

backend = Aer.get_backend('qasm_simulator') # Loads the qasm simulator
job = execute(circuit, backend, shots=1000) # Simulate our circuit 1000 times
result = job.result() # Retrieve results from simulation
data = result.get_counts() # Retrieve counts
print("Counts: ", data) # Present data

circuit.draw()

Run the circuit and read the output. Notice that out of 1000, the amount of 0s and 1s are very close to 500 (or even exactly 500). This demonstrates that ~50% of the time, we will observe a 0 while ~50% of the time, we will observe a 1.

If we instead had our state as: [math.sqrt(1/3), math.sqrt(2/3)], we would observe that ~33% of simulation runs will result in 0, and ~67% will result in 1.

Note: As we progress through this guide, you might find it easier to wrap your code up into functions like so:

def qasm(circuit):
    backend = Aer.get_backend('qasm_simulator') # Loads the qasm simulator
    job = execute(circuit, backend, shots=1000).result().get_counts()
    print("Counts: ", job) # Present data

Conclusion

In this git repository, there is a folder containing all programs written in this guide. Feel free to use them as “skeletons” for your future use.

I would encourage you to tinker with this circuit to develop a deeper understanding of how it works.

Onward to Episode II!

Return to the Homepage!