This chapter introduces Qiskit for designing and running quantum circuits (simulation or hardware where available).
Goals¶
Give just enough quantum computing background to read a short circuit.
Show a runnable Qiskit example with measurement and interpretation of results.
Explore a further aspect depending on your interest.
Link to IBM Qiskit documentation, textbooks, and simulators.
Draft¶
Introduction¶
Qiskit is an open-source Python library developed by IBM for interacting with quantum computers. It supports simulating small quantum circuits on classical hardware in addition to interacting with cloud quantum providers for more complex workloads. Popular use cases for the library include quantum information science experimentation, hybrid orchestration of quantum and classical resources, and the development of quantum algorithms. Qiskit is advertised as a complete quantum computing solution including tools for preprocessing, hardware optimization, postprocessing, and visualization.
This chapter starts with background information about classical and quantum computing, qubits, and common quantum gates. The remainder of the text provides tutorials and examples for using the Qiskit library to simulate simple circuits on local hardware, connecting to the IBM Quantum Platform, and executing one of the foundational algorithms in the field of quantum computing on real hardware.
Background¶
Classical Computing¶
The fundamental unit of information in classical computing systems is the bit (binary digit), which can represent either 0 or 1. Depending on the underlying physical medium, bits can be represented in a variety of ways: electrical charge, magnetization, light intensity, etc. Bits are used to store data and perform logical operations that modify the state of the system. Logic gates perform operations on one or more binary inputs to produce a single output. Common logic gates include AND, OR, and NOT gates. These operations can be modeled using boolean algebra to design complex logic circuits that perform desired functions.
Gordon Moore, the co-founder and former CEO of Intel, famously predicted that the number of transistors in integrated circuits would double roughly every two years (a prediction that would later be known as Moore’s law). This rule of thumb has held for several decades, but we are approaching the physical limits to how small transistors can be. Therefore, a new architectural approach is needed to move beyond Moore’s Law and build upon many-core architectures.
Quantum Theory¶
Our physical world is governed by the fundamental laws of physics. While classical physics can be used to describe pheneomena at macroscopic and microscopic scales, quantum physics models submicroscopic and subatomic properties. A foundational understanding in quantum theory is required to explain electromagnetism, the strong force, the weak force, and gravity. Quantum systems are known to exhibit properties of both particles and waves (a concept known as wave-particle duality). One of the field’s defining features that is not present in classical mechanics is quantum entanglement, or the idea that quantum states in a group cannot be described independently, regardless of the distances between them.
Quantum Computing¶
Qubits¶
The basic unit of information in quantum computing systems is the qubit (quantum bit). Unlike a classical bit, which exists in exactly one of two possible states, a qubit can be in an arbitrary superposition of all computable states simultaneously. Quantum computers are fundamentally different from classical computers because they can act on every state in the superposition at once. While it is possible to represent qubits classically, as the size of the system grows, quantum computers become extremely difficult to simulate with a classical computer. Qubits can be represented by a linear combination of two basis vectors: and . Therefore, the state of a qubit is a vector in a two-dimensional vector space, which is known as the state space.
The conventional notation used to represent qubits is known as bra-ket notation or Dirac notation. A ket (column vector) is of the form and represents a quantum states, while a bra (row vector) is of the form and corresponds to the complex conjugate transpose of a ket. While it is convention to use bra-ket notation to describe quantum states as elements of a complex Hilbert space, the underlying representation is always two-dimensional row and column vectors. is often used to denote an arbitrary quantum state.
The two orthonormal basis states, and , form the computation basis that span the two-dimensional linear vector space of the qubit. Therefore, all possible qubit states can be described by a linear combination of these two states: .
Quantum Gates¶
Quantum gates perform logical operations on qubits. Common quantum gates are shown in the table below.
| Name | Symbol | # qubits | Description |
|---|---|---|---|
| Identity | 1 | Returns the input | |
| Pauili X / NOT | 1 | Inverses the input (equivalent to a classical bit flip) | |
| Pauli Y | 1 | Flips the bit and phase of the input | |
| Pauli Z | 1 | Flips the phase of the input | |
| Controlled NOT | 2 | Inverses the second qubit when the first qubit is | |
| Hadamard | 1 | Transforms the input into a superposition of states |
Qiskit¶
A Simple Quantum Circuit¶
The following code snippet represents a Bell state (two entangled qubits):
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler
qc = QuantumCircuit(2) # Instantiate a quantum circuit with 2 qubits
qc.h(0) # Apply a Hadamard gate
qc.cx(0, 1) # Apply a Controlled-X gate
qc.measure_all() # Adds measurement to all qubits
sampler = StatevectorSampler()
result = sampler.run([qc], shots=1024).result()
print(result[0].data.meas.get_counts())The expected output is a near-even split between ‘00’ and ‘11’. The corresponding quantum circuit (generated by qc.draw("mpl")) is shown in the figure below.

Running Circuits on Quantum Hardware¶
While small quantum circuits can be simulated on classical hardware, scaling up to larger circuits requires quantum computing hardware. The IBM Quantum Platform allows you to execute circuits defined with Qiskit on their quantum processing units (QPUs).
The following function creates an an n-qubit GHZ state (extended Bell state).
def get_qc_for_n_qubit_GHZ_state(n: int) -> QuantumCircuit:
if isinstance(n, int) and n >= 2:
qc = QuantumCircuit(n)
qc.h(0)
for i in range(n - 1):
qc.cx(i, i + 1)
else:
raise Exception("n is not a valid input")
return qcThis code snippet uses the ZZ operators between qubits to examine the behavior as they get farther apart.
# ZZII...II, ZIZI...II, ... , ZIII...IZ
operator_strings = [
"Z" + "I" * i + "Z" + "I" * (n - 2 - i) for i in range(n - 1)
]
operators = [SparsePauliOp(operator) for operator in operator_strings]Then, the circuit must be prepared to run on quantum hardware and the output must be post-processed (these steps excluded here for brevity, see the documentation for more details). The following plot shows that as the distance between qubits increases, the signal quickly decays because of the presence of noise.

Grover’s Algorithm¶
Created by Lov Grover at Bell Labs in 1996, Grover’s algorithm is one of the most fundamental algorithms in the field of quantum computing. The algorithm is designed for unstructured search problems, where it can be used to determine whether an input that satisfies a black box function (also known as an oracle function), exists in time complexity (where is the size of the function’s domain). By contrast, classical computing approaches would require searching the entire input space for a solution, resulting in a worst-case time complexity of , with an average of steps. A more formal statement of this problem, which can be described as searching for string that causes to evaluate to 1, is shown below.
The following code snippet creates a quantum circuit with 3 qubits and marks two target states (011 and 100) that Grover’s algorithm will search for. This circuit serves as the input oracle function.
marked_states = ["011", "100"]
qc = QuantumCircuit(3)
for target in marked_states:
# Flip target bit-string to match Qiskit bit-ordering
rev_target = target[::-1]
# Find the indices of all the '0' elements in bit-string
zero_inds = [
ind
for ind in range(num_qubits)
if rev_target.startswith("0", ind)
]
# Add a multi-controlled Z-gate with pre- and post-applied X-gates (open-controls)
# where the target bit-string has a '0' entry
if zero_inds:
qc.x(zero_inds)
qc.compose(MCMTGate(ZGate(), num_qubits - 1, 1), inplace=True)
if zero_inds:
qc.x(zero_inds)This results in the circuit shown below.

Applying Qiskit’s built-in grover_operator() function to the circuit results in a new circuit that amplifies the states marked by the oracle function.

Repeated execution of the Grover operator amplify the marked states, increasing their probability in the circuit’s output distribution. The optimal number of applications is determined by the ratio of the number of marked states (which is 2 in this case) to the total number of possible computational states (3 qubits results in 8 possible states).
After optimizing the circuit for execution on quantum hardware and sampling the output, a probability distribution similar to the following plot will be returned. The algorithm dramatically amplified the amplitudes of the two marked states (011 and 100), which shows a successful application of Grover’s algorithm on quantum hardware.

Conclusion¶
Quantum computing is an emerging field with foundations in quantum mechanics and classical computing. Qiskit is a Python library for specifying, executing, and visualizing quantum circuits. This chapter briefly introduced the theoretical foundations of quantum computing, basics of the Qiskit library, and executing circuits on quantum hardware.