Code
conda install -c conda-forge qiskit qiskit-aer -y
June 26, 2025
Qiskit, Quantum Computation
\(\require{cancel}\)
Qiskit is a Python-based, open-source framework for quantum computing. It supports superconducting qubits and trapped ions as physical implementations. The qiskit library is available at GitHub [1]. This post is a detailed exploration of one of the examples [2] included the qiskit tutorials. All the credit for the code belongs to the qiskit team, and I made only small changes. If you would like to run the original code online, I pulled it into a binder page [3].
Note: This setup was tested on macOS with Apple Silicon (M1/M2 chips) using conda environment.
In Qiskit 2.x, the simulator backend (Aer) has been moved to a separate package. You need to install both:
Alternatively, you can use pip, but conda is recommended for Apple Silicon Macs:
If you’re using R with reticulate (as in this document), you need to set the correct Python path:
To find your Python path, run in terminal:
Test that everything works:
Qiskit version: 2.1.0
Available backends: [AerSimulator('aer_simulator'), AerSimulator('aer_simulator_statevector'), AerSimulator('aer_simulator_density_matrix'), AerSimulator('aer_simulator_stabilizer'), AerSimulator('aer_simulator_matrix_product_state'), AerSimulator('aer_simulator_extended_stabilizer'), AerSimulator('aer_simulator_unitary'), AerSimulator('aer_simulator_superop'), QasmSimulator('qasm_simulator'), StatevectorSimulator('statevector_simulator'), UnitarySimulator('unitary_simulator')]
from qiskit_aer import Aer
instead of from qiskit import Aer
backend.run(circuit)
instead of execute(circuit, backend)
circuit1.compose(circuit2)
instead of circuit1 + circuit2
Once you have the library properly installed, you can start playing with the code.
Any quantum algorithm will involve single qubit and multi qubit operations. This introduction code, for example, has a Hadamard-Walsh gate, which transforms \(|0\rangle\) to \(\frac{|0\rangle+|1\rangle}{\sqrt{2}}\). There will be other operations that act on two qubits at once, such as the controlled-not (CNOT) gate. We will start from a state \(|\psi\rangle_f\) which is a tensor product of \(3\) independent states, initialized at \(|0\rangle\), i.e.: \[\begin{equation} |\psi\rangle_i=|000\rangle \label{eq:psi0}. \end{equation}\] After a set of gate operations, we will arrive at a three-qubit GHZ state, which is given by \[\begin{equation} |\psi\rangle_f=\frac{|000\rangle+|111\rangle}{\sqrt{2}} \label{eq:psi1}. \end{equation}\]
We can then simulate the circuit and make measurements on the outputs. The physical implementation of the qubits and the measulrement is beyond the scope of this post, however, I already have a post on superconducting qubits which might be a good read.
We load the library and initiate a quantum system of \(3\) qubits.
The sequence of operations is as follows:
# Build the quantum circuit
gates = [
circ.h(0), # Add a H gate on qubit 0, putting this qubit in superposition.
circ.cx(0, 1), # Add a CX (CNOT) gate on control qubit 0 and target qubit 1, putting the qubits in a Bell state.
circ.cx(0, 2) # Add a CX (CNOT) gate on control qubit 0 and target qubit 2, putting the qubits in a GHZ state.
]
circ.draw('mpl', style=circuit_style) # draw the circuit with custom styling
Qiskit has a specific way of ordering qubits in the state representation. For example, if qubit zero is in state \(0\), qubit \(1\) is in state \(0\), and qubit \(2\) is in state \(1\), Qiskit would represent this state as \(|100\rangle\), compared to typical physics textbook representation of \(|001\rangle\). In this representation, the controlled-not operator, with qubit \(0\) being the control and qubit \(1\) being the target, reads: \[\begin{equation} C_X = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\\end{pmatrix} \label{eq:cnot}. \end{equation}\]
Qiskit Aer is the quantum circuits simulating package. It provides various backends for simulations. We will use statevector_simulator
. It computes and returns the quantum state. Note that the dimensionality of the state grows exponentially: with \(n\) qubits the result is a complex vector of dimension \(2^n\).
The result
object contains the data and Qiskit provides the method result.get_statevector(circ)
to return the state vector for the quantum circuit.
Statevector([0.707+0.j, 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j,
0. +0.j, 0. +0.j, 0.707+0.j],
dims=(2, 2, 2))
The visualization function can be used to plot the real and imaginary components of the state density matrix \(\rho\), which is defined as: \[\begin{equation} \rho\equiv |\psi\rangle\langle\psi|=\frac{|000\rangle\langle 000|+|000\rangle\langle 111|+|000\rangle\langle 000|+|111\rangle\langle 111| }{2} \label{eq:rho}. \end{equation}\]
To simulate a circuit that includes measurement, we add measurements to the original circuit above, and use a different Aer backend.
The measurement collapses the quantum states onto classical bits. and they are stored in classical registers,
The measurement can be simulated in qasm_simulator
. The shots
parameter sets the number of simulations.
get_counts(circuit)
returns aggregated binary outcomes of the simulated circuit
{'111': 517, '000': 507}
plot_histogram
can be used to plot the distribution of the outcomes.
From the output numbers, one can see that 49.5% of the time, we get the classical output \(000\). However, it is always a good practice to compute and include the confidence intervals, say \(95\%\). For a binary random variable, the confidence intervals are given by
\[\begin{equation} \hat p\pm z\sqrt{\frac{\hat p(1-\hat p)}{n_\text{trials}}} \label{eq:cconf}. \end{equation}\] where \(\hat p\) is the observed value of the probability and \(z\) is the z-score for the confidence level (i.e., \(1.96\) for \(95\%\)).
Therefore, the simulations with \(1024\) trials show that the probability of measuring state \(000\) is \([ 0.46 , 0.53 ]\) with \(95\%\) confidence.
\(\nextSection\)