Quantum Circuits Explained: 40 Essential Design Patterns

Quantum circuits are the assembly language of quantum computing, the level where abstract algorithms turn into concrete sequences of gates a machine can run. Read enough of them and the same shapes keep returning, a Hadamard opening here, a controlled rotation there, a measurement feeding a correction at the end.

This guide collects forty of those recurring shapes, drawn one to a diagram and grouped into six families, from foundational entangling moves through communication protocols, algorithmic primitives, arithmetic, variational templates, and error correction. Each entry explains what the circuit does, how it works, and when you would actually reach for it. Taken together they form a visual vocabulary of quantum circuits that carries over directly to frameworks like Cirq for building quantum circuits, Qiskit, and the diagrams you meet in research papers.

Key takeaways

A handful of gates does almost everything. Nearly every quantum circuit is built from Hadamards, controlled-NOTs, a few rotations, and measurements. Recognising these pieces lets you read an unfamiliar diagram at a glance.

Entanglement is a resource you prepare and spend. Bell and GHZ states are manufactured on purpose, then consumed by protocols like teleportation and superdense coding. Thinking of entanglement as fuel clarifies why so many circuits open the same way.

Measurement is an active ingredient, not just an ending. Modern dynamic circuits measure partway through and feed the result forward to steer later gates. This feedforward turns quantum circuits into something closer to interactive programs.

Interference does the real work. Oracles hide answers in phases, and diffusion or Fourier steps turn those phases into measurable probabilities. Almost every speedup traces back to arranging amplitudes so wrong answers cancel.

Variational patterns keep today’s noisy hardware useful. Trainable templates, parameter-shift gradients, and error mitigation squeeze results from imperfect devices. These are the quantum circuits running on real machines right now.

Error correction is built from repeated parity checks. Syndrome extraction and stabiliser measurements detect faults without reading the protected data. Scaling these checks is the path from today’s prototypes to fault-tolerant quantum circuits.

How to read these quantum circuit diagrams

Every diagram in this guide follows the same conventions, so a few minutes here pays off across all forty. Each horizontal line is a qubit, time runs from left to right, and gates are the boxes and symbols drawn along the wires in the order they execute.

A filled dot marks a control, and the operation on the wire it connects to fires only when that control reads one, so a CNOT appears as a control dot linked to a target circle. Single-qubit gates sit in labelled boxes such as H for Hadamard or RY for a rotation, while a meter symbol marks a measurement. A double line leaving a meter is a classical wire carrying a bit that can condition gates further along, which is how these quantum circuits express measurement and feedforward.

Every figure is genuine Qiskit output

Every diagram here is drawn with Qiskit’s own circuit renderer, the same mpl drawer you get from calling draw on a QuantumCircuit, so the picture on the page matches exactly what the framework produces. Each pattern also carries a runnable snippet under a Build it in Qiskit toggle, and the code targets a recent Qiskit 2.x release so you can paste it straight into a notebook.

The Bloch sphere behind every wire

Each wire in these quantum circuits carries a single qubit, and the state of that one wire is exactly what the Bloch sphere draws as a point on a globe. The two poles are the classical answers |0⟩ and |1⟩, the equator holds the equal superpositions a Hadamard creates, and every gate you meet below is really a rotation that slides this point to a new place on the sphere.

Bloch sphere view of the zero state used throughout quantum circuits, the vector at the north pole for the ket zeroThe default |0⟩ state, where the Bloch vector sits at the north pole of the sphere. Explore this live on our interactive Bloch sphere.
Bloch sphere showing the plus state after a Hadamard in quantum circuits, the vector on the equatorAfter one Hadamard gate the vector lands on the equator at |+⟩, an equal superposition of |0⟩ and |1⟩. Explore this live on our interactive Bloch sphere.

Reading the math in this guide

Every state in these quantum circuits sits inside a ket like |0⟩, |1⟩ or |ψ⟩, and a string such as |01⟩ simply lists several qubits left to right. The mirrored bra ⟨ψ| is its partner, and a bracket ⟨φ|ψ⟩ is the overlap between two states, a single number that measures how similar they are.

⊗ is the tensor product, the operation that combines separate qubits into one system. Writing |0⟩ ⊗ |1⟩ means the first qubit is in |0⟩ and the second is in |1⟩, and the guide usually shortens it to |01⟩. Componentwise it multiplies every entry of one state by every entry of the other, which is why n qubits span 2^n dimensions.

Show the math
(a, b) \otimes (c, d) = (ac, ad, bc, bd)
H \otimes I = \text{apply H to the first qubit, leave the second alone}

A two-qubit state that can be written as one thing ⊗ another is unentangled, each qubit owning its own state, and entangled states such as (1/√2)(|00⟩ + |11⟩) are exactly the ones that cannot be factored that way, so the ⊗ symbol is the yardstick entanglement is measured against. The remaining symbols are lighter fare, ⊕ is addition modulo two, the XOR of classical logic, and e^(iφ) is a phase, a point on the unit circle that rotates a state’s contribution without changing its measurement weight on its own.

Foundational quantum circuits

The foundational quantum circuits are the moves every practitioner learns first, because everything else is assembled from them. They create superposition, build entanglement, and set up the control structure that later algorithms depend on.

Bell State Preparation

The Bell state is the smallest piece of entanglement you can build, and almost every protocol in this guide starts from it. A Hadamard puts the control qubit into an equal superposition, then a CNOT copies that indecision onto the target so the two qubits become perfectly correlated. Reach for this pattern whenever you need a shared entangled resource, since teleportation and superdense coding both consume a Bell pair as fuel. The two gates turn the |00⟩ input into a Bell pair in two short steps.

Show the math
(H \otimes I)\,|00\rangle = \tfrac{1}{\sqrt{2}}(|0\rangle + |1\rangle) \otimes |0\rangle
\mathrm{CNOT}\cdot \tfrac{1}{\sqrt{2}}(|00\rangle + |10\rangle) = \tfrac{1}{\sqrt{2}}(|00\rangle + |11\rangle)

The output cannot be factored as (state of q0) ⊗ (state of q1), no matter how the terms are grouped. That impossibility is exactly what entanglement means, and it is why these quantum circuits behave unlike any classical wiring.

Bell state preparation, one of the first quantum circuits: a Hadamard and a CNOT entangle two qubits
A Hadamard on the control followed by a CNOT turns |00⟩ into the entangled pair (|00⟩ + |11⟩)/√2.

Qiskit reports this circuit at two qubits and a depth of two. The gate count comes to one Hadamard and one controlled-NOT.

Build it in Qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.draw("mpl")
See it run

Both qubits start in zero, and one of the simplest quantum circuits, a Hadamard followed by a CNOT, entangles them. Across 4,096 shots the sampler returned 00 on 2,066 shots and 11 on 2,030, and the mixed outcomes 01 and 10 never appeared. Each qubit alone is a fair coin, yet the two coins always land the same way, which is exactly what entanglement means here.

Bell state sampling from quantum circuits: 4,096 shots split between 00 and 11 onlySampling the Bell pair 4,096 times: every shot reads 00 or 11, never 01 or 10.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])

counts = StatevectorSampler(seed=7).run([qc], shots=4096).result()[0].data.c.get_counts()
print(counts)  # only 00 and 11 ever appear

GHZ State

The GHZ state stretches Bell-style entanglement across three or more qubits at once. One Hadamard seeds a superposition and a short ladder of CNOTs spreads it outward, so measuring any single qubit instantly fixes the rest to agree. It is the standard test bed for multi-qubit entanglement and turns up in quantum metrology and in anonymous-voting protocols. Reading left to right, one Hadamard opens the superposition and the CNOT ladder threads it across every wire in a single pass.

Show the math
\tfrac{1}{\sqrt{2}}(|0\rangle + |1\rangle) \otimes |00\rangle
\xrightarrow{\ \text{CNOT ladder}\ } \tfrac{1}{\sqrt{2}}(|000\rangle + |111\rangle)

Each CNOT copies the branch bit onward, never the state itself, so no quantum information is duplicated. That distinction is why the ladder scales cleanly to any number of wires in larger quantum circuits.

GHZ state quantum circuits diagram: a Hadamard and a CNOT ladder entangle three qubits
One Hadamard and two chained CNOTs spread a single superposition across three qubits, giving (|000⟩ + |111⟩)/√2.

Qiskit reports this circuit at three qubits and a depth of three. The gate count comes to one Hadamard and two controlled-NOTs.

Build it in Qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(3)
qc.h(0)
qc.cx(0, 1)
qc.cx(1, 2)
qc.draw("mpl")
See it run

A Hadamard on the first qubit followed by a CNOT ladder puts all three qubits into one shared superposition. The sampler saw 000 on 2,066 of 4,096 shots and 111 on 2,030, while the other six bitstrings scored zero. Three qubits behave as a single coin, so measuring any one of them decides all three, which makes these quantum circuits the standard first test of multi-qubit entanglement.

GHZ state result from quantum circuits: all 4,096 shots read 000 or 111, nothing betweenThe CNOT ladder stretches one coin flip across three qubits: 4,096 shots, only 000 and 111.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

qc = QuantumCircuit(3, 3)
qc.h(0)
qc.cx(0, 1)
qc.cx(1, 2)
qc.measure(range(3), range(3))

counts = StatevectorSampler(seed=7).run([qc], shots=4096).result()[0].data.c.get_counts()
print(counts)  # only 000 and 111 ever appear

W State Preparation

The W state shares a single excitation evenly across three qubits rather than piling all the weight into two extremes. A tuned RY rotation and a controlled rotation set the amplitudes, then CNOTs and a final X distribute that lone excitation across the register. Its appeal is that it survives loss gracefully, because discarding one qubit still leaves the other two entangled. The amplitudes are fixed by a chain of tuned rotations, and the very first angle carries the whole story.

Show the math
|W\rangle = \tfrac{1}{\sqrt{3}}(|001\rangle + |010\rangle + |100\rangle)
\cos(\theta_1/2) = \tfrac{1}{\sqrt{3}} \quad \text{sets the first rotation}
W state preparation in quantum circuits: a rotation cascade and CNOTs share one excitation across three qubits
An RY rotation and a controlled rotation set the amplitudes, then CNOTs and a final X distribute one excitation across the register.

Qiskit reports this circuit at three qubits and a depth of five. The gate count comes to one X gate, one RY rotation, one controlled-RY rotation and two controlled-NOTs.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter

theta1 = Parameter("θ1")  # 2*arccos(1/sqrt(3)) gives the exact W state
theta2 = Parameter("θ2")  # pi/2
qc = QuantumCircuit(3)
qc.ry(theta1, 0)
qc.cry(theta2, 0, 1)
qc.cx(1, 2)
qc.cx(0, 1)
qc.x(0)
qc.draw("mpl")
See it run

Two calibrated rotations set the amplitudes and the CNOTs spread a single excitation across three qubits. Out of 4,096 shots the sampler returned 001 on 1,387, 010 on 1,345 and 100 on 1,364, each close to the expected one third of 1,365. Every shot has exactly one qubit reading 1, which is the signature of the W state.

W state result from quantum circuits: 4,096 shots split across 001, 010 and 100 onlySampling the W state: exactly one qubit reads 1 on every shot, and each position gets a fair third.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

qc = QuantumCircuit(3, 3)
qc.ry(2 * np.arccos(1 / np.sqrt(3)), 0)
qc.cry(np.pi / 2, 0, 1)
qc.cx(1, 2)
qc.cx(0, 1)
qc.x(0)
qc.measure(range(3), range(3))

counts = StatevectorSampler(seed=7).run([qc], shots=4096).result()[0].data.c.get_counts()
print(counts)  # only 001, 010 and 100 ever appear

Uniform Superposition

A layer of Hadamards, one per wire, is the most common opening move in the whole field. Acting in parallel they load all two-to-the-n basis states into the register at equal weight, giving an algorithm every possible input at once. Use it as the first step of Grover search, quantum Fourier work, and most textbook algorithms. Written across three wires, one Hadamard layer loads every basis state at once, the opening move of most quantum circuits.

Show the math
\displaystyle H\otimes H\otimes H\,|000\rangle = \tfrac{1}{\sqrt{8}}(|000\rangle + |001\rangle + |010\rangle + \dots + |111\rangle) = \tfrac{1}{\sqrt{2^{n}}}\sum_{x}|x\rangle
Uniform superposition in quantum circuits: a Hadamard on each of three qubits reaches all eight basis states
Three Hadamards acting in parallel put the register into an equal superposition of all eight basis states.

Qiskit reports this circuit at three qubits and a depth of one. The gate count comes to three Hadamards.

Build it in Qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(3)
for i in range(3):
    qc.h(i)
qc.draw("mpl")
See it run

Three Hadamard gates turn the all-zeros input into an equal superposition of all eight bitstrings. Across 4,096 shots every outcome appeared, with counts ranging from 487 to 543 around the expected 512. This one-gate-per-wire layer is how nearly every algorithm built from quantum circuits loads its full search space in a single step.

Uniform superposition from quantum circuits: eight outcomes near 512 shots each over 4,096 runsOne Hadamard per wire loads all eight bitstrings at equal weight; the shot counts confirm it.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

qc = QuantumCircuit(3, 3)
qc.h(0)
qc.h(1)
qc.h(2)
qc.measure(range(3), range(3))

counts = StatevectorSampler(seed=7).run([qc], shots=4096).result()[0].data.c.get_counts()
print(dict(sorted(counts.items())))  # all eight outcomes, near 512 each

Measuring in the X Basis

Real hardware almost always measures in the Z basis, yet many questions are asked in a different basis. Inserting a Hadamard just before readout rotates the X basis onto the Z basis, so a standard measurement now answers an X-basis question. The same idea with an S then an H reads the Y basis, and it sits behind state tomography and stabiliser checks. A Hadamard placed just before the meter rotates the axis so a Z-basis readout answers an X-basis question.

Show the math
P(0\ \text{after}\ H) = |\langle 0|H|\psi\rangle|^{2} = |\langle +|\psi\rangle|^{2}

The H converts an X-basis question into the Z-basis question the hardware can actually ask. Real devices only measure in one fixed basis, so this rotation is how quantum circuits probe any other direction.

Basis change in quantum circuits: a Hadamard before measurement reads a qubit in the X basis
A Hadamard inserted just before readout converts the hardware’s Z-basis measurement into an X-basis one.

Qiskit reports this circuit at one qubit, one classical bit and a depth of three. The gate count comes to one Hadamard, one state-preparation box and one measurement.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Gate

qc = QuantumCircuit(1, 1)
qc.append(Gate("u_box", 1, [], label="U"), [0])  # any state-prep unitary
qc.h(0)
qc.measure(0, 0)
qc.draw("mpl")
See it run

Both runs prepare the identical plus state, an equal superposition of 0 and 1. Measured directly, 4,096 shots split 2,066 against 2,030, pure coin-flip noise; with one Hadamard applied before the readout, all 4,096 shots read 0. The information was there all along, and the basis change is what converts hidden phase structure into a definite answer.

Basis change in quantum circuits: direct measurement is 50/50 noise, Hadamard first reads 0 every shotSame state, two measurements: raw Z-basis readout is a coin flip, one Hadamard first makes it certain.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

direct = QuantumCircuit(1, 1)
direct.h(0)                # prepare the plus state
direct.measure(0, 0)       # measure straight away in the Z basis

rotated = QuantumCircuit(1, 1)
rotated.h(0)               # prepare the same plus state
rotated.h(0)               # rotate the X basis onto Z first
rotated.measure(0, 0)

sampler = StatevectorSampler(seed=7)
for name, qc in [("direct ", direct), ("rotated", rotated)]:
    counts = sampler.run([qc], shots=4096).result()[0].data.c.get_counts()
    print(name, dict(counts))
Bloch sphere showing the plus state after a Hadamard in quantum circuits, the vector on the equatorThe Hadamard leaves the state on the equator at |+⟩, equidistant from both poles. A raw Z-basis readout is then a coin flip until a second Hadamard rotates that equatorial vector back onto a pole, which is exactly the X-basis measurement built here. Explore this live on our interactive Bloch sphere.

Phase Kickback

A CNOT gate is one of the most familiar building blocks in quantum circuits, meant to change its target while leaving its control untouched, yet this circuit does the reverse. The target ancilla emerges exactly as it went in, while the control flips from |+⟩ to |−⟩, as though information had run backwards through the gate. That reading looks impossible, and it stays impossible right up until you stop watching the computational basis and start watching the phase.

The ancilla is prepared in |−⟩, which is an eigenstate of the X operator with eigenvalue −1. Applying X to one of its own eigenstates cannot change the state at all, so the only thing that happens is multiplication by that eigenvalue, a bare factor of −1. Standing alone, that factor would be a global phase, and no measurement anywhere can depend on a global phase. The point is that the X fires only on the |1⟩ branch of the control’s superposition, so the −1 attaches to that branch by itself, and the control moves from (|0⟩ + |1⟩)/√2 to (|0⟩ − |1⟩)/√2, which is |−⟩. A phase that would have been unobservable has become a relative phase between the control’s two branches, and relative phases are precisely what a measurement in the right basis can read.

Walking it one branch at a time makes the bookkeeping plain. On the control’s |0⟩ branch the CNOT does nothing, so the ancilla stays |−⟩. On the control’s |1⟩ branch the X lands on |−⟩ and hands back −|−⟩, with the eigenvalue pulled out to the front. Gather the two branches together again and the minus sign now rides on the control’s |1⟩ component while the ancilla factors out unchanged, and that is the whole calculation. The figures in the run below, where the control reads 1 in the X basis on every shot, are that same arithmetic made physical.

The same bookkeeping works for any controlled unitary, not just the CNOT. Write the control as an equal superposition and let the target |ψ⟩ be an eigenstate of U with eigenvalue e^(iφ), and four short lines of algebra show exactly where that phase ends up.

Show the math
\begin{aligned}\text{C-U}\cdot \tfrac{1}{\sqrt{2}}(|0\rangle + |1\rangle)\otimes|\psi\rangle&= \tfrac{1}{\sqrt{2}}\big(|0\rangle\otimes|\psi\rangle + |1\rangle\otimes U|\psi\rangle\big)\\&= \tfrac{1}{\sqrt{2}}\big(|0\rangle\otimes|\psi\rangle + e^{i\varphi}|1\rangle\otimes|\psi\rangle\big)\\&= \tfrac{1}{\sqrt{2}}\big(|0\rangle + e^{i\varphi}|1\rangle\big)\otimes|\psi\rangle\end{aligned}

On the right the target |ψ⟩ factors out completely and comes through unchanged, while the eigenvalue phase e^(iφ) now rides on the control’s |1⟩ branch rather than on the target. The circuit built in this section is the special case U = X and |ψ⟩ = |−⟩, where φ = π and e^(iπ) = −1, which is exactly the |+⟩ to |−⟩ flip traced out above. Phase estimation pushes the same trick further, since repeated controlled powers of U write the binary digits of φ onto a whole register of control qubits, one digit at a time.

The pattern earns its keep because eigenvalues are where quantum algorithms tuck away their answers. Grover’s phase oracle is kickback put to work, marking a chosen state with a −1 without ever reading it, and phase estimation is kickback run at scale, where controlled powers of a unitary kick eigenvalue phases into a counting register one binary digit at a time. Whenever a diagram of quantum circuits shows a control qubit changing while its target sits perfectly still, kickback is the thing you are looking at. Reading that signature turns a piece of quantum misdirection into a tool you can reach for on purpose.

Phase kickback in quantum circuits: a CNOT on a minus-state ancilla hands its phase back to the control qubit
With the ancilla prepared in |−⟩ by X then H, the CNOT leaves the ancilla unchanged and flips the control from |+⟩ to |−⟩.

Qiskit reports this circuit at two qubits and a depth of three. The gate count comes to two Hadamards, one X gate and one controlled-NOT.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister

q = QuantumRegister(1, "q")
anc = QuantumRegister(1, "anc")
qc = QuantumCircuit(q, anc)
qc.h(q[0])
qc.x(anc[0])
qc.h(anc[0])
qc.cx(q[0], anc[0])
qc.draw("mpl")
See it run

The control starts in the plus state and the ancilla in the minus state, and the control is read in the X basis with a final Hadamard. Without the CNOT all 4,096 shots read 0; with the CNOT in place all 4,096 read 1, even though the target ancilla is left completely unchanged. The gate’s action lands on the control as a phase, and that backwards flow of information is the engine inside the quantum circuits for Deutsch-Jozsa, Grover and phase estimation.

Phase kickback in quantum circuits: X-basis readout of the control flips from all 0 to all 1 with the CNOTThe ancilla never changes; the CNOT writes its phase onto the control, flipping the X-basis readout from 0 to 1.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

def kickback(with_cnot):
    qc = QuantumCircuit(2, 1)
    qc.h(0)              # control in the plus state
    qc.x(1)
    qc.h(1)              # ancilla in the minus state
    if with_cnot:
        qc.cx(0, 1)      # the phase kicks back onto the control
    qc.h(0)              # read the control in the X basis
    qc.measure(0, 0)
    return qc

sampler = StatevectorSampler(seed=7)
for flag in (False, True):
    counts = sampler.run([kickback(flag)], shots=4096).result()[0].data.c.get_counts()
    print("with CNOT" if flag else "no CNOT  ", dict(counts))
Bloch sphere showing an S phase gate in quantum circuits rotating the vector to the ket i state on the equatorH then S: the phase gate spins the equatorial vector a quarter turn around the Z axis, from |+⟩ to |i⟩. The latitude never moves, so the Z-basis probabilities stay put and the phase only surfaces once you change basis, which is the mechanism behind phase kickback. Explore this live on our interactive Bloch sphere.

SWAP From Three CNOTs

Sometimes you simply need to exchange the states of two qubits, and most hardware offers no native SWAP to do it. Classically you would copy one value into a scratch register and shuffle the pieces around, but the no-cloning theorem forbids copying an unknown quantum state, so the exchange has to happen in place. The move that survives the crossing onto quantum hardware is the classical programmer’s XOR-swap trick, which exchanges two variables using no temporary storage at all. Three exclusive-ORs are enough to walk the two values past each other, and every one of them is a CNOT.

Follow the three gates in order and the exchange falls out one XOR at a time. The first CNOT writes the parity a⊕b onto the bottom wire while the top wire still carries its original value a. The second CNOT fires back upward, and a⊕(a⊕b) collapses to b, so the top wire now carries the second value and the first has vanished from it entirely. The third CNOT fires downward once more, (a⊕b)⊕b collapses to a, and the swap is finished with the two values having walked past each other. Tracking the two wires through each gate makes the walk explicit.

Show the math
|a, b\rangle \to |a,\ a\oplus b\rangle \to |b,\ a\oplus b\rangle \to |b, a\rangle

Three XORs swap the two values with no scratch qubit, the classical trick running straight on the wires. Hardware without a native SWAP leans on this identity constantly when routing quantum circuits onto fixed connectivity.

From bit trick to hardware tax

The trace above uses definite bit labels, but nothing in it depended on the values being definite. The circuit is unitary and linear, so it swaps every superposition by acting on each basis term at once, sending α|01⟩ + β|10⟩ to α|10⟩ + β|01⟩. If one of the qubits is entangled with a third party, the entanglement travels with the state to its new wire, so the swap moves quantum information around without ever reading or copying it.

One SWAP costs three CNOTs, and on chips where only neighbouring qubits can interact, bringing two distant qubits together can cost a whole chain of these swaps in each direction. That price is why compilers sweat qubit placement so hard, and why the depth of a circuit on paper often balloons once a router has inserted the swaps a real layout demands. Routing like this dominates the cost of running large quantum circuits on fixed-connectivity hardware.

SWAP from three CNOTs, a classic quantum circuits identity shown as two equivalent circuit panels
Three alternating CNOTs implement exactly the same operation as a single SWAP gate.

Qiskit reports this circuit at two qubits and a depth of three. The gate count comes to three controlled-NOTs.

Build it in Qiskit
from qiskit import QuantumCircuit

# right-hand panel; the left panel is just qc.swap(0, 1)
qc = QuantumCircuit(2)
qc.cx(0, 1)
qc.cx(1, 0)
qc.cx(0, 1)
qc.draw("mpl")
See it run

The input is prepared as 01, with only the lower qubit set to 1. After the three alternating CNOTs, all 4,096 shots read 10: the excitation has moved to the other wire with probability one, and no other outcome ever appears. Three CNOTs reproduce the SWAP gate exactly, which is why compilers on devices without a native SWAP fall back on this identity.

SWAP from three CNOTs in quantum circuits: input 01 comes out 10 on all 4,096 shotsThe three-CNOT identity in action: state 01 goes in, state 10 comes out with probability one.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

qc = QuantumCircuit(2, 2)
qc.x(0)            # prepare input |q1 q0> = |01>
qc.cx(0, 1)
qc.cx(1, 0)
qc.cx(0, 1)        # three alternating CNOTs = one SWAP
qc.measure([0, 1], [0, 1])

counts = StatevectorSampler(seed=7).run([qc], shots=4096).result()[0].data.c.get_counts()
print(dict(counts))  # every shot reads 10

The Controlled-U Gate

The controlled-U gate is the generic conditional operation from which almost every two-qubit interaction in quantum circuits is built. A filled dot on the control wire applies the boxed unitary U to the target only when the control reads one, turning any single-qubit gate into an entangler. Phase estimation, controlled rotations, and oracle constructions all rest on this single primitive. The gate leaves the target alone when the control reads zero and applies U when it reads one.

The cleanest way to understand any controlled gate is to write it as a sum of two branches, and the outer products |0⟩⟨0| and |1⟩⟨1| are projectors, machines that ask a question. Read |0⟩⟨0| right to left: the bra ⟨0| measures how much of the control sits in |0⟩, and the ket |0⟩ puts exactly that component back, so the projector passes the |0⟩ part of a state through and deletes the rest.

Show the math
\text{C-U} = |0\rangle\langle 0|\otimes I + |1\rangle\langle 1|\otimes U
\text{C-U}\cdot(\alpha|0\rangle + \beta|1\rangle)\otimes|\psi\rangle = \alpha|0\rangle\otimes|\psi\rangle + \beta|1\rangle\otimes U|\psi\rangle

Each term reads as condition then consequence. The |0⟩⟨0| ⊗ I term says that on the branch where the control is zero the target is left alone, while |1⟩⟨1| ⊗ U says that on the branch where the control is one the target receives U. A classical if statement runs one branch; because this is a single linear operator, the plus sign runs both branches at once, weighted by the control’s amplitudes α and β.

That one formula explains two things at the heart of quantum circuits. When U changes |ψ⟩, the two branches now differ on the target, the state no longer factors, and the controlled gate has created entanglement. When |ψ⟩ is instead an eigenstate of U, U|ψ⟩ equals e^(iφ)|ψ⟩, the target factors back out, and the phase slides onto the control, which is exactly the phase kickback mechanism derived earlier on this page.

Controlled-U gate in quantum circuits: a control dot applies the unitary U only when the control qubit is 1
A filled dot on the control wire applies the boxed unitary U to the target only when the control qubit is 1.

Qiskit reports this circuit at two qubits and a depth of one. The gate count comes to one controlled-unitary.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Gate

u = Gate("u_box", 1, [], label="U")
defn = QuantumCircuit(1)
defn.u(0.5, 0.3, 0.2, 0)  # placeholder definition so .control() unrolls
u.definition = defn
qc = QuantumCircuit(2)
qc.append(u.control(1), [0, 1])
qc.draw("mpl")
See it run

The same controlled gate runs twice, here with U chosen as the bit-flip X so the effect is visible in the counts. With the control at 0 all 4,096 shots read 00, the target untouched; with the control set to 1 all 4,096 shots read 11, so U fired on every single run. One qubit’s value decides whether an operation happens at all, and that conditional logic is the branching primitive inside larger quantum circuits.

Controlled-U in quantum circuits: the target flips only when the control qubit is set to 1Two runs of the same controlled gate: control at 0 leaves the target alone, control at 1 applies U every time.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

def run(control_on):
    qc = QuantumCircuit(2, 2)
    if control_on:
        qc.x(0)        # set the control qubit to 1
    qc.cx(0, 1)        # controlled-U with U = X
    qc.measure([0, 1], [0, 1])
    return qc

sampler = StatevectorSampler(seed=7)
for on in (False, True):
    counts = sampler.run([run(on)], shots=4096).result()[0].data.c.get_counts()
    print("control 1" if on else "control 0", dict(counts))

Communication and measurement circuits

These circuits move quantum information around and read it out cleverly. They turn shared entanglement into a communication resource and show how measurement can be woven into the middle of a computation rather than saved for the very end.

Quantum Teleportation

Teleportation answers a genuine difficulty in quantum information. An unknown quantum state cannot be copied, because the no-cloning theorem forbids duplicating an arbitrary state, and it cannot simply be read out, since any measurement that recovered it would destroy the superposition you wanted to keep. Real systems still need to move a state between machines or across a network, and teleportation does precisely that, transferring the state intact using a shared entangled Bell pair together with two ordinary classical bits.

The circuit splits into three phases marked by the barriers in the diagram. First, qubits q1 and q2 are prepared as a shared Bell pair with a Hadamard followed by a CNOT, and q2 is handed to the distant receiver ahead of time. Second, the sender entangles the mystery qubit, drawn as the |ψ⟩ wire, with her half of the pair using a CNOT then a Hadamard and measures both, a Bell measurement that yields two classical bits m0 and m1.

Third, those two bits travel over an ordinary channel and choose the receiver’s correction, an X when m1 reads one and a Z when m0 reads one, with both or neither applied in the other cases, so that after the correction q2 holds exactly the state |ψ⟩ that the top wire began with. The reason those specific corrections work becomes clear once you regroup the same three qubits in the Bell basis of the first two.

Show the math
|\psi\rangle \otimes |\Phi^{+}\rangle,\quad \text{with}\ |\psi\rangle = \alpha|0\rangle + \beta|1\rangle,\ \ |\Phi^{+}\rangle = \tfrac{1}{\sqrt{2}}(|00\rangle + |11\rangle)
= \tfrac{1}{2}\big[\,|\Phi^{+}\rangle\otimes(\alpha|0\rangle + \beta|1\rangle) + |\Phi^{-}\rangle\otimes(\alpha|0\rangle - \beta|1\rangle) + |\Psi^{+}\rangle\otimes(\alpha|1\rangle + \beta|0\rangle) + |\Psi^{-}\rangle\otimes(\alpha|1\rangle - \beta|0\rangle)\,\big]
= \tfrac{1}{2}\big[\,|\Phi^{+}\rangle\otimes|\psi\rangle + |\Phi^{-}\rangle\otimes Z|\psi\rangle + |\Psi^{+}\rangle\otimes X|\psi\rangle + |\Psi^{-}\rangle\otimes XZ|\psi\rangle\,\big]

Nothing has happened yet, because this is the same state written in a new basis. The Bell measurement simply selects one line, and each line names the exact Pauli correction that returns Bob’s qubit to |ψ⟩.

It helps to be precise about what teleportation does not do. Nothing travels faster than light, because the two classical bits are essential to the protocol and they move no quicker than any other signal, so no information outruns lightspeed. The original state is destroyed the moment the sender measures, which means no second copy ever exists and the no-cloning theorem stays intact. No physical qubit is sent anywhere either, since only the description of the state is transferred while the atoms or electrons stay where they are.

This pattern earns its place far beyond a textbook demonstration. It is the backbone of quantum networking and quantum repeaters, which chain teleportation through entanglement swapping, a trick covered later on this page, to extend entanglement across distances no single link could reach. The same mechanics return inside fault-tolerant quantum circuits, where gate teleportation and magic state injection move hard-to-build operations onto the data with a measurement and a classical correction. Learning teleportation once therefore pays off across both communication and computation.

Quantum circuits diagram of teleportation: Bell pair, Bell measurement, and classically controlled X and Z fix-ups.
Quantum teleportation: a Bell measurement plus two classical bits move state |ψ⟩ onto a distant qubit.

Qiskit reports this circuit at three qubits, two classical bits and a depth of seven. The gate count comes to two Hadamards, two controlled-NOTs, two classically conditioned blocks and two measurements.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

q = QuantumRegister(3, "q")
m0 = ClassicalRegister(1, "m0")
m1 = ClassicalRegister(1, "m1")
qc = QuantumCircuit(q, m0, m1)
qc.h(1)
qc.cx(1, 2)
qc.barrier()
qc.cx(0, 1)
qc.h(0)
qc.measure(1, m1[0])
qc.measure(0, m0[0])
qc.barrier()
with qc.if_test((m1, 1)):
    qc.x(2)
with qc.if_test((m0, 1)):
    qc.z(2)
qc.draw("mpl")
See it run

The input qubit is prepared with RY(1.2), giving Bloch components 0.9320, 0.0000 and 0.3624. After the full protocol, a Bell pair plus Alice’s two measured bits steering Bob’s X and Z fix-ups, Bob’s reduced state shows exactly the same three components and a state fidelity of 1.0000. The per-branch check confirms it works on every measurement branch: all four outcomes deliver fidelity 1.0000, so nothing is left to luck.

Teleportation in quantum circuits: input and output Bloch components match, fidelity 1.0000Teleporting RY(1.2)|0>: Bob’s Bloch components (0.9320, 0.0000, 0.3624) match the input exactly, fidelity 1.0000.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, partial_trace, state_fidelity

prep = QuantumCircuit(1)
prep.ry(1.2, 0)
psi = Statevector.from_instruction(prep)

qc = QuantumCircuit(3)
qc.ry(1.2, 0)              # the state to send, on q0
qc.h(1); qc.cx(1, 2)       # shared Bell pair, q1 and q2
qc.cx(0, 1); qc.h(0)       # Alice rotates into the Bell basis
qc.cx(1, 2); qc.cz(0, 2)   # Bob's X and Z corrections, deferred
rho_bob = partial_trace(Statevector.from_instruction(qc), [0, 1])
print("fidelity with the input state:", state_fidelity(rho_bob, psi))

Superdense Coding

Superdense coding is teleportation read in reverse, with one qubit carrying two classical bits. Starting from a shared Bell pair, the sender picks one of four gates, I, X, Z, or XZ, and sends their single qubit, which a Bell measurement decodes into two bits. It is the cleanest demonstration that shared entanglement doubles the classical capacity of a quantum channel. One local Pauli on the sender’s half moves the pair among the four Bell states like this.

Show the math
\begin{aligned}(I \otimes I)\,|\Phi^{+}\rangle &= \tfrac{1}{\sqrt{2}}(|00\rangle + |11\rangle)\\(X \otimes I)\,|\Phi^{+}\rangle &= \tfrac{1}{\sqrt{2}}(|10\rangle + |01\rangle)\\(Z \otimes I)\,|\Phi^{+}\rangle &= \tfrac{1}{\sqrt{2}}(|00\rangle - |11\rangle)\\(XZ \otimes I)\,|\Phi^{+}\rangle &= \tfrac{1}{\sqrt{2}}(|10\rangle - |01\rangle)\end{aligned}

One local Pauli on a single half reaches all four orthogonal Bell states. A Bell measurement then recovers two full classical bits.

Why one qubit really carries two bits

Four different output states are not yet enough on their own. The receiver has to tell them apart with certainty, and quantum mechanics permits perfect discrimination only when the states are mutually orthogonal. Two short inner products settle whether that condition holds here.

Show the math
\langle\Phi^{+}|\Phi^{-}\rangle = \tfrac{1}{2}\big(\langle 00| + \langle 11|\big)\big(|00\rangle - |11\rangle\big) = \tfrac{1}{2}(1 - 1) = 0
\langle\Phi^{\pm}|\Psi^{\pm}\rangle = 0 \qquad \Phi:\{|00\rangle,|11\rangle\},\ \ \Psi:\{|01\rangle,|10\rangle\}
\Rightarrow\ \text{all four encoded states are mutually orthogonal}

Mutually orthogonal states can be separated perfectly by the right measurement, and the Bell measurement is exactly that measurement here. The CNOT then Hadamard mapping in the Bell measurement pattern sends the four Bell states to the four computational outcomes, so the receiver reads both bits with certainty, which is what the run’s 4,096 error-free shots confirm.

Holevo’s theorem caps the classical information extractable from a single qubit at one bit, no matter how cleverly it is encoded, so a lone qubit can never carry the two bits this circuit delivers. The pre-shared Bell pair pays for the difference, one ebit consumed per two bits sent, and the protocol is teleportation’s mirror image in resources. Teleportation spends one ebit plus two classical bits to move one qubit, while superdense coding spends one ebit plus one transmitted qubit to move two classical bits.

Superdense coding shown as one of the key quantum circuits: one sent qubit delivers two classical bits.
Superdense coding: choosing I, X, Z, or XZ on one half of a Bell pair packs two classical bits into a single travelling qubit.

Qiskit reports this circuit at two qubits, two classical bits and a depth of seven. The gate count comes to two Hadamards, one X gate, one Z gate, two controlled-NOTs and two measurements.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

q = QuantumRegister(2, "q")
a = ClassicalRegister(1, "a")
b = ClassicalRegister(1, "b")
qc = QuantumCircuit(q, a, b)
qc.h(0)
qc.cx(0, 1)
qc.barrier(label="share")
qc.x(0)
qc.z(0)
qc.barrier(label="send")
qc.cx(0, 1)
qc.h(0)
qc.measure(0, a[0])
qc.measure(1, b[0])
qc.draw("mpl")
See it run

Alice takes her half of a shared Bell pair and applies nothing, X, Z, or both to encode 00, 01, 10 or 11. Bob undoes the entangling step and measures, and across 1,024 shots per message he reads back exactly the two bits Alice chose, with zero errors in 4,096 total shots. One travelling qubit really did carry two classical bits, which is the whole point of these quantum circuits.

Superdense coding in quantum circuits: all four two-bit messages decode exactly over 1,024 shots eachSuperdense coding, all four messages: each decodes to the bits that were sent, 1,024 of 1,024 shots every time.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

sampler = StatevectorSampler(seed=7)
for msg in ("00", "01", "10", "11"):
    qc = QuantumCircuit(2, 2)
    qc.h(0); qc.cx(0, 1)           # shared Bell pair
    if msg[1] == "1": qc.x(0)      # Alice encodes two bits
    if msg[0] == "1": qc.z(0)      # on her single qubit
    qc.cx(0, 1); qc.h(0)           # Bob decodes
    qc.measure([0, 1], [0, 1])
    counts = sampler.run([qc], shots=1024).result()[0].data.c.get_counts()
    decoded = {k[::-1]: v for k, v in counts.items()}
    print("sent", msg, "->", decoded)

Entanglement Swapping

Entanglement swapping links two qubits that have never interacted. Beginning with two independent Bell pairs, a Bell measurement on the inner qubits projects the outer qubits into an entangled state of their own. Quantum repeaters chain this trick along a fibre to build entanglement across distances no single link could span. Two independent Bell pairs meet at a joint measurement that stitches their far ends together.

Show the math
\displaystyle |\Phi^{+}\rangle_{12} \otimes |\Phi^{+}\rangle_{34} = \tfrac{1}{2}\sum_{B} |B\rangle_{23} \otimes (\sigma_{B}|\Phi^{+}\rangle)_{14} \quad (\text{sum over the four Bell states } B)

Qubits 1 and 4 never interacted, yet measuring 2 and 3 in the Bell basis leaves 1 and 4 in a Bell state named by the outcome. This is how quantum repeaters extend entanglement across links that were never directly connected.

Entanglement swapping in quantum circuits notation: a Bell measurement on the middle pair links the outer qubits.
Entanglement swapping: a Bell measurement on the two middle qubits entangles the outer qubits, which never interacted.

Qiskit reports this circuit at four qubits, two classical bits and a depth of five. The gate count comes to three Hadamards, three controlled-NOTs and two measurements.

Build it in Qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(4, 2)
qc.h(0)
qc.cx(0, 1)
qc.h(2)
qc.cx(2, 3)
qc.barrier()
qc.cx(1, 2)
qc.h(1)
qc.measure(1, 0)
qc.measure(2, 1)
qc.draw("mpl")
See it run

Two independent Bell pairs are prepared, q0 with q1 and q2 with q3, so the outer qubits q0 and q3 share no history at all. A Bell measurement on the middle pair, with its two correction bits applied to q3, then leaves the outer pair entangled: over 4,096 shots they read 00 on 2,066 shots and 11 on 2,030, and the mismatched outcomes never appear. Perfect correlation between qubits that never interacted is the signature these quantum circuits exist to produce.

Entanglement swapping in quantum circuits: outer qubits read 00 or 11 on all 4,096 shotsEntanglement swapping, sampled: the outer qubits q0 and q3 agree on all 4,096 shots, splitting 2,066 to 2,030 between 00 and 11.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

qc = QuantumCircuit(4, 4)
qc.h(0); qc.cx(0, 1)         # Bell pair q0-q1
qc.h(2); qc.cx(2, 3)         # Bell pair q2-q3
qc.cx(1, 2); qc.h(1)         # Bell measurement on the middle pair
qc.cx(2, 3); qc.cz(1, 3)     # corrections on q3, deferred
qc.measure(range(4), range(4))
res = StatevectorSampler(seed=7).run([qc], shots=4096).result()[0]
outer = {}
for key, n in res.data.c.get_counts().items():
    k = key[::-1]                          # k[i] is qubit i
    outer[k[0] + k[3]] = outer.get(k[0] + k[3], 0) + n
print("outer pair q0,q3:", outer)          # only 00 and 11

Bell Measurement

A Bell measurement reads out which of the four Bell states two qubits are in. Running Bell-state preparation backwards, a CNOT then a Hadamard, rotates the entangled basis back to the computational one so two ordinary measurements finish the job. It is the shared decoding step inside teleportation, superdense coding, and entanglement swapping. A CNOT followed by a Hadamard maps each of the four Bell states onto a distinct pair of classical bits.

Show the math
\text{CNOT then H maps:}
|\Phi^{+}\rangle \to |00\rangle,\qquad |\Phi^{-}\rangle \to |10\rangle
|\Psi^{+}\rangle \to |01\rangle,\qquad |\Psi^{-}\rangle \to |11\rangle
Bell measurement, a staple of quantum circuits: CNOT and Hadamard before two standard measurements.
Bell measurement: running Bell-state preparation in reverse turns two measurements into a readout of which Bell state arrived.

Qiskit reports this circuit at two qubits, two classical bits and a depth of three. The gate count comes to one Hadamard, one controlled-NOT and two measurements.

Build it in Qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(2, 2)
qc.cx(0, 1)
qc.h(0)
qc.measure(0, 0)
qc.measure(1, 1)
qc.draw("mpl")
See it run

Each of the four Bell states is prepared and fed through the CNOT plus Hadamard readout. Every input returns one and only one bit pair across 1,024 shots: the phase bit flags the minus sign and the parity bit flags the flipped pair, so Phi plus reads 00, Phi minus reads 10, Psi plus reads 01 and Psi minus reads 11. Two classical bits name one of four entangled states deterministically, which is exactly the decoder teleportation and superdense coding rely on.

Bell measurement in quantum circuits: four Bell states map to four distinct bit pairs, 1,024 shots eachBell measurement as a state reader: each of the four Bell states returns its own phase and parity bits on all 1,024 shots.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

sampler = StatevectorSampler(seed=7)
for (z, x), name in {(0, 0): "Phi+", (1, 0): "Phi-",
                     (0, 1): "Psi+", (1, 1): "Psi-"}.items():
    qc = QuantumCircuit(2, 2)
    qc.h(0); qc.cx(0, 1)          # make Phi+
    if x: qc.x(1)                 # turn it into the chosen Bell state
    if z: qc.z(0)
    qc.cx(0, 1); qc.h(0)          # Bell measurement
    qc.measure([0, 1], [0, 1])
    counts = sampler.run([qc], shots=1024).result()[0].data.c.get_counts()
    bits = list(counts)[0][::-1]
    print(name, "-> phase", bits[0], "parity", bits[1], counts)

Mid-Circuit Feedforward

Dynamic circuits measure some qubits partway through and use the result to steer later gates. Here a mid-circuit measurement conditions an X gate on another qubit while the rest of the computation carries on. This feedforward is what separates today’s dynamic circuits from the old picture where every measurement waited until the very end. A measurement partway through the run feeds its outcome into a gate applied later.

Show the math
\text{final state} = X^{m}\,|\text{rest}\rangle \quad (m = \text{the measured bit})

The exponent m is classical data read off the meter, which is what makes this feedforward rather than a coherently controlled gate. Many quantum circuits for error correction depend on exactly this loop between measurement and later action.

Dynamic quantum circuits: a mid-circuit measurement result conditions an X gate on another qubit.
Mid-circuit feedforward: a measurement partway through the circuit steers a conditional X gate while the computation continues.

Qiskit reports this circuit at two qubits, two classical bits and a depth of five. The gate count comes to two Hadamards, one classically conditioned block and two measurements.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

q = QuantumRegister(2, "q")
m = ClassicalRegister(1, "m")
out = ClassicalRegister(1, "out")
qc = QuantumCircuit(q, m, out)
qc.h(0)
qc.measure(0, m[0])
qc.barrier()
with qc.if_test((m, 1)):
    qc.x(1)
qc.h(1)
qc.measure(1, out[0])
qc.draw("mpl")
See it run

A Bell pair is created and the first qubit is measured mid-circuit, landing 0 or 1 with probability 0.5000 each. With feedforward on, an X applied only when the result is 1 leaves the target reading 0 with probability 1.0000, while switching the correction off leaves a fair coin at 0.5000 per outcome. The exact branch arithmetic shows a classical bit steering a live gate is what lets quantum circuits turn randomness into a deterministic answer.

Mid-circuit feedforward in quantum circuits: correction on gives certainty, off gives a coin flipFeedforward on versus off: with the conditional X the target reads 0 with probability 1.0000, without it the readout is 0.5000 each way.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

bell = QuantumCircuit(2)
bell.h(0); bell.cx(0, 1)
amps = np.asarray(Statevector.from_instruction(bell)).reshape(2, 2)
X = np.array([[0, 1], [1, 0]])
p_on, p_off = np.zeros(2), np.zeros(2)
for m in (0, 1):                       # the two q0 measurement branches
    v = amps[:, m]
    pm = float(np.vdot(v, v).real)     # branch probability
    v = v / pm ** 0.5
    p_off += pm * np.abs(v) ** 2                   # no correction
    p_on += pm * np.abs(X @ v if m else v) ** 2    # X iff m == 1
print("correction ON :", p_on)
print("correction OFF:", p_off)

Qubit Reset and Reuse

Qubits are scarce, so reusing them stretches a small processor further. After measuring a qubit, a reset returns it to the zero state mid-circuit, freeing the same physical wire for a fresh task. The pattern shows up in iterative phase estimation and in any long circuit that would otherwise run out of qubits. A measurement collapses the qubit and a conditional flip returns it to a clean zero for a second job.

Show the math
\text{reset:}\ \ \rho \to |0\rangle\langle 0| \quad \text{for every input}\ \rho

Reset is not a unitary, it discards the qubit’s history, which is exactly why the second computation starts clean. Reusing wires this way lets narrow hardware run quantum circuits that would otherwise demand far more qubits.

Reset and reuse in quantum circuits: a qubit is measured, reset to |0⟩, then put back to work.
Reset and reuse: after measurement the qubit is wiped back to |0⟩ and immediately starts a second job on the same wire.

Qiskit reports this circuit at two qubits, one classical bit and a depth of five. The gate count comes to two Hadamards, one controlled-NOT, one reset and one measurement.

Build it in Qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(2, 1)
qc.h(0)
qc.measure(0, 0)
qc.reset(0)
qc.h(0)
qc.cx(0, 1)
qc.draw("mpl")
See it run

The qubit’s first computation is deliberately biased, an RY(1.2) that reads 0 with probability 0.6812 and 1 with probability 0.3188. After measure and reset, the same qubit runs a Hadamard test and returns exactly 0.5000 per outcome, and the density-matrix simulation puts its distance from a genuinely fresh qubit at zero. Reset really does wipe the slate, which is why quantum circuits can reuse one physical qubit instead of burning a new one per step.

Reset and reuse in quantum circuits: a reused qubit matches a fresh one, 0.5000 per outcomeReset and reuse: after a biased first use, the recycled qubit’s second computation gives 0.5000 per outcome, identical to a fresh qubit.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.quantum_info import DensityMatrix, Statevector

first = QuantumCircuit(1)
first.ry(1.2, 0)                      # biased first computation
print("first readout:", Statevector.from_instruction(first).probabilities())

reused = QuantumCircuit(1)
reused.ry(1.2, 0)
reused.reset(0)                       # measure and discard, as a channel
reused.h(0)                           # second computation on the same qubit
p_reused = DensityMatrix.from_instruction(reused).probabilities()

fresh = QuantumCircuit(1)
fresh.h(0)                            # same computation on a new qubit
p_fresh = Statevector.from_instruction(fresh).probabilities()
print("reused:", p_reused, " fresh:", p_fresh)
print("max difference:", abs(p_reused - p_fresh).max())

Deferred Measurement

The deferred measurement principle says you can always push measurements to the end. A mid-circuit measurement feeding a classically controlled gate is mathematically identical to a coherent controlled gate with the measurement postponed, and the output statistics match exactly. It lets theorists reason about purely unitary circuits even when the real device measures early. Any measurement can be slid to the very end once its classical control is replaced by a coherent one.

Show the math
X^{m} \circ (\text{measure}) = (\text{measure}) \circ \mathrm{CNOT}

Classical control after measuring equals quantum control before it, so the measured statistics can never differ between the two orderings. This equivalence lets theorists analyze quantum circuits as if every measurement happened last.

Two equivalent quantum circuits: classically controlled X after measurement versus CNOT with measurement at the end.
Deferred measurement: a classically controlled gate after a measurement equals a quantum-controlled gate with the measurement moved to the end.

Qiskit reports this circuit at two qubits, one classical bit and a depth of two. The gate count comes to one controlled-NOT and one measurement.

Build it in Qiskit
from qiskit import QuantumCircuit

# Deferred variant: control first, measure last.
# The equivalent early-measure variant measures q0 first, then
# applies X on q1 inside `with qc.if_test((c, 1)):`.
qc = QuantumCircuit(2, 1)
qc.cx(0, 1)
qc.measure(0, 0)
qc.draw("mpl")
See it run

The early variant measures the control qubit first and feeds the result forward into an X on the target, while the deferred variant replaces that whole sequence with a CNOT and measures at the very end. Both produce exactly the same distribution, 0.5000 on 00 and 0.5000 on 11 with a maximum difference of zero, and a 4,096-shot sampled run of the deferred circuit lands 2,066 and 2,030 on those same outcomes. That equality is the deferred measurement principle doing real work: any mid-circuit measurement can be pushed to the end without changing what you observe.

Deferred measurement in quantum circuits: early and late measurement give identical statisticsDeferred measurement check: measuring early with feedforward and measuring at the end both give 0.5000 on 00 and 0.5000 on 11, exactly.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

h = QuantumCircuit(1)
h.h(0)
a = np.asarray(Statevector.from_instruction(h))
# early variant: measure q0, then X on q1 iff the result was 1,
# so branch m contributes probability |a[m]|^2 to outcome (m, m)
early = {"00": abs(a[0]) ** 2, "11": abs(a[1]) ** 2}

late_qc = QuantumCircuit(2)
late_qc.h(0); late_qc.cx(0, 1)        # control first, measure at the end
p = Statevector.from_instruction(late_qc).probabilities()
late = {"00": p[0], "11": p[3]}
print("early:", early)
print("late :", late)
print("max difference:", max(abs(early[k] - late[k]) for k in early))

Algorithmic primitive circuits

The algorithmic primitives are the reusable subroutines that give quantum computing its famous speedups. Each one, from the Fourier transform to Grover’s oracle, appears again and again inside larger quantum circuits as a trusted building block.

Quantum Fourier Transform

The quantum Fourier transform is the quantum version of the discrete Fourier transform, a change of basis that re-expresses a state’s amplitudes in terms of phase frequencies rather than raw bit values. On n qubits it acts on all two-to-the-n amplitudes at once while spending only about n-squared gates, whereas the classical fast Fourier transform still needs work proportional to the number of data points themselves. That contrast is real but easy to overstate, because the transformed amplitudes cannot simply be read out by measurement. The speedup only pays off inside algorithms whose answer is a phase or a period, so this is a subroutine rather than a drop-in replacement for the classical FFT.

Reading the figure from left to right, the Hadamard on the top qubit splits it according to the most significant bit, and each controlled-phase rotation then twists in progressively finer phase detail, first through an angle of π/2 and next through π/4, conditioned on the lower qubits. The same shape repeats down the register with one fewer rotation on every row, which is why the work thins out as you move to the lower wires. The final swap is present because the transform naturally emerges with its qubits in reversed order, so the swap restores the ordering that the rest of the program expects.

The intuition worth holding onto is that the quantum Fourier transform encodes a number into rotation speeds. Each input basis state ends up as a pattern of phases winding around every qubit at its own frequency, fast on one wire and slower on the next. Different inputs therefore turn into distinguishable interference patterns rather than distinguishable bit strings, which is precisely the shape that later interference steps know how to exploit. In symbols the transform sends each basis state |x⟩ to a full comb of phases.

Show the math
\displaystyle \mathrm{QFT}\,|x\rangle = \tfrac{1}{\sqrt{N}}\sum_{k=0}^{N-1} e^{\,2\pi i\,xk/N}\,|k\rangle \quad (N = 2^{n})

How the gates build the transform

Track a single number |x⟩ with bits q2, q1, q0, so x = 4·q2 + 2·q1 + q0, and watch what each gate leaves on the wires. By the end no wire stores a bit any more; each stores a rotation rate, three dials of increasing coarseness.

The workhorse here is the controlled-phase gate CP(θ), which does nothing except attach a phase, and only when both of its qubits read one. It is symmetric between the two wires, which is why the diagram draws it as two dots joined by a line rather than a dot and a target. In the transform below, the lower wire’s bit plays b and θ is the fraction of a turn that bit contributes to the upper wire’s dial, the projector form being the same quantum if statement described in the controlled-U pattern.

Show the math
CP(\theta)\,|a\rangle|b\rangle = e^{\,i\theta\,ab}\,|a\rangle|b\rangle \quad (a,b \in \{0,1\})
CP(\theta) = |0\rangle\langle 0| \otimes I + |1\rangle\langle 1| \otimes P(\theta), \quad P(\theta)|b\rangle = e^{\,i\theta b}|b\rangle
H on q0
\tfrac{1}{\sqrt{2}}\big(|0\rangle + e^{\,2\pi i\, q_0/2}|1\rangle\big)
after CP(π/2) from q1 and CP(π/4) from q2
\tfrac{1}{\sqrt{2}}\big(|0\rangle + e^{\,2\pi i\,(q_0/2 + q_1/4 + q_2/8)}|1\rangle\big)
after H on q1 then CP(π/2) from q2
\tfrac{1}{\sqrt{2}}\big(|0\rangle + e^{\,2\pi i\,(q_1/2 + q_2/4)}|1\rangle\big)
after H on q2
\tfrac{1}{\sqrt{2}}\big(|0\rangle + e^{\,2\pi i\, q_2/2}|1\rangle\big)

The first wire winds through eighths of a turn using all three bits, the second through quarters using two, the third through halves using one, and together the three dials encode x purely in phases. The binary fractions emerge in bit-reversed order, which is the only job of the final swap, and multiplying the three wires out reproduces the definition above. For a concrete number, x = 6 has bits q2 = 1, q1 = 1, q0 = 0, so the three dials land at 3/8, 3/4 and 1/2 of a turn.

The transform as a product of qubits

Show the math
\mathrm{QFT}\,|x\rangle = \tfrac{1}{\sqrt{2}}\big(|0\rangle + e^{\,2\pi i\,x/2}|1\rangle\big) \otimes \tfrac{1}{\sqrt{2}}\big(|0\rangle + e^{\,2\pi i\,x/4}|1\rangle\big) \otimes \tfrac{1}{\sqrt{2}}\big(|0\rangle + e^{\,2\pi i\,x/8}|1\rangle\big)

Multiplying the three single-qubit states together gives the product form the final swap leaves behind, with the eighths dial sitting on the wire that reads as the ones bit under the q2, q1, q0 labelling. Expanding the three brackets reproduces exactly the 2³ = 8 terms of the definition’s sum, one term for every output state k, each carrying the phase that sum assigns to it.

The worked example below feeds in a sum of four numbers rather than one, and by linearity the transform processes all four at once. Their four phase patterns interfere and cancel at every output except 0 and 4, which is how the comb becomes two clean spikes in the See it run figures.

This pattern earns its keep as the engine inside quantum phase estimation, and through phase estimation it drives Shor’s factoring algorithm, where the inverse transform converts an encoded period into readable measurement outcomes. In practice the inverse quantum Fourier transform at the close of phase estimation is where you will most often meet this building block inside real quantum circuits.

Three-qubit quantum Fourier transform, a cornerstone of quantum circuits: Hadamards, controlled phases, final swap.
Quantum Fourier transform on three qubits: Hadamards interleaved with ever-finer controlled phase gates, then a swap to restore qubit order.

Qiskit reports this circuit at three qubits and a depth of six. The gate count comes to three Hadamards, three controlled-phase rotations and one swap.

Build it in Qiskit
import math
from qiskit import QuantumCircuit

qc = QuantumCircuit(3)
qc.h(0)
qc.cp(math.pi / 2, 1, 0)
qc.cp(math.pi / 4, 2, 0)
qc.h(1)
qc.cp(math.pi / 2, 2, 1)
qc.h(2)
qc.swap(0, 2)
qc.draw("mpl")
See it run

This input is a pattern we chose deliberately for the demonstration, because it is cheap to prepare and its repetition is obvious by eye, so the transform’s answer can be checked against what we already know. Line up the eight possible readouts like boxes in a row, numbered 0 through 7. The input fills every second box: each even box holds a quarter of the probability and every odd box holds none.

box: 0 1 2 3 4 5 6 7
weight: 1/4 0 1/4 0 1/4 0 1/4 0
Show the math
|\text{in}\rangle = \tfrac{1}{2}(|0\rangle + |2\rangle + |4\rangle + |6\rangle) = \tfrac{1}{2}(|000\rangle + |010\rangle + |100\rangle + |110\rangle)
|\text{in}\rangle = |+\rangle \otimes |+\rangle \otimes |0\rangle \quad (\text{wires}\ q_2, q_1, q_0\ \text{left to right})
x = 4q_2 + 2q_1 + q_0 \ \Rightarrow\ 0{=}000,\ 2{=}010,\ 4{=}100,\ 6{=}110 \quad (\text{odd}\ x\ \text{need}\ q_0{=}1)

Each basis state is a three-bit number, so the four terms are the even values with amplitude one half each, which squares to the 0.25 bars in the left panel. The factored form doubles as the recipe, a Hadamard on wires q2 and q1 with wire q0 left in |0⟩, and that untouched q0 bit is the reason only even numbers can appear, exactly what the runnable snippet below does with two gates.

The eight labels on the chart are therefore not eight separate inputs but the eight possible readouts of the three wires together. The input is one state holding four of them at once, and a readout of 4 after the transform means the wires came out as q2 = 1, q1 = 0, q0 = 0.

Full, empty, full, empty: the register holds an on-off rhythm that completes one cycle every two boxes, so across all eight boxes the rhythm plays 8/2 = 4 times. The transform counts exactly that. Its output boxes no longer mean numbers; output box k lights up only if the input rhythm plays k times across the register.

That is why exactly two output bars appear and no others. The bar at 4 says the on-off rhythm played four times, and the bar at 0 reports the steady part of the pattern, the constant background any all-positive pattern carries, much like the average level of a signal. Every other box stays dark because the input contains no rhythm that plays one, two, three, five, six or seven times, and the interference arithmetic below shows those cancellations happening term by term.

Show the math
\mathrm{QFT}\,|\text{in}\rangle = \tfrac{1}{\sqrt{2}}\big(|0\rangle + |4\rangle\big)

Running the transform on that comb lands the whole state on a clean two-term superposition. This is the state the right panel’s two 0.5 bars are showing, one half of the probability on 0 and one half on 4.

Show the math
\text{amplitude at}\ k\ \propto\ \sum_{x\,\in\,\{0,2,4,6\}} e^{\,2\pi i\,xk/8}
k{=}2:\ 1 + e^{i\pi} + e^{2\pi i} + e^{3\pi i} = 1 - 1 + 1 - 1 = 0
k{=}4:\ 1 + e^{2\pi i} + e^{4\pi i} + e^{6\pi i} = 1 + 1 + 1 + 1 = 4

At every k that is not a multiple of four the four phase arrows point in cancelling directions and the amplitude dies, while at 0 and 4 they line up and reinforce. That cancellation pattern is the transform doing its real work, and the same mechanism operates unchanged at any register size.

Compare what a measurement is worth before and after: beforehand you draw a random even number that tells you almost nothing, afterwards you draw 0 or 4, and the 4 hands you the period directly as 8/4 = 2. Shor’s algorithm is this exact move at scale, with one difference that matters: there nobody chooses the pattern. The modular arithmetic of the factoring problem manufactures a comb whose period is exactly the unknown being sought, and this transform is the instrument that reads that period out, turning an invisible repetition into a number a single measurement can return.

Quantum circuits worked example: the QFT maps a period 2 comb over states 0 to 7 into probability spikes at 0 and 4Simulated with Qiskit’s Statevector, the QFT converts a state with period 2 across eight basis states into spikes at frequencies 0 and 4.
Run this example yourself
from math import pi
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

qc = QuantumCircuit(3)
qc.h(1)
qc.h(2)  # equal superposition of 0, 2, 4, 6: a comb with period 2
print("input :", Statevector(qc).probabilities_dict(decimals=3))

qc.h(2)  # 3-qubit QFT, built gate by gate
qc.cp(pi / 2, 1, 2)
qc.cp(pi / 4, 0, 2)
qc.h(1)
qc.cp(pi / 2, 0, 1)
qc.h(0)
qc.swap(0, 2)
print("output:", Statevector(qc).probabilities_dict(decimals=3))

The same transform on a different pattern

One worked example could be a fluke, so change the input and let the machine rather than the example do the work. A single Hadamard on the fours wire q2 prepares a sparser input, two spikes in boxes 0 and 4 with half the probability in each, a pattern that repeats every four boxes.

Show the math
|\text{in}\rangle = \tfrac{1}{\sqrt{2}}\big(|0\rangle + |4\rangle\big) = |+\rangle \otimes |0\rangle \otimes |0\rangle \quad (\text{wires}\ q_2, q_1, q_0\ \text{left to right})
\mathrm{QFT}\,|\text{in}\rangle = \tfrac{1}{2}\big(|0\rangle + |2\rangle + |4\rangle + |6\rangle\big)
Quantum circuits worked example: the QFT maps two spikes at 0 and 4 into a probability comb at 0, 2, 4 and 6Simulated with Qiskit’s Statevector, the QFT sends two spikes at 0 and 4 to equal probabilities on 0, 2, 4 and 6, exactly the comb the first example started from.

The counting rule reads this pattern just as cleanly as the first. Half as many input spikes produce twice as many output spikes, because a pattern repeating every four boxes plays only 8/4 = 2 times across the register, so the lit output boxes sit every two slots. Where the first input was dense in position and sparse in frequency, this one is the reverse.

Look closer and the reversal is exact. The simulated output amplitudes land at precisely one half on each of 0, 2, 4 and 6 with no stray phases, which makes this output amplitude for amplitude the state the first example fed in. The two patterns form a Fourier pair, and the transform swaps between them: run it on either one and it returns the other.

Run this example yourself
from math import pi
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

qc = QuantumCircuit(3)
qc.h(2)  # equal superposition of 0 and 4: two spikes with period 4
print("input :", Statevector(qc).probabilities_dict(decimals=3))

qc.h(2)  # 3-qubit QFT, built gate by gate
qc.cp(pi / 2, 1, 2)
qc.cp(pi / 4, 0, 2)
qc.h(1)
qc.cp(pi / 2, 0, 1)
qc.h(0)
qc.swap(0, 2)
print("output:", Statevector(qc).probabilities_dict(decimals=3))

Quantum Phase Estimation

Phase estimation reads the eigenphase of a unitary onto a register of counting qubits. Each counting qubit controls a different power of U, one, two, four, and so on, and an inverse quantum Fourier transform turns the accumulated phases into a binary readout. It is the measurement primitive behind Shor’s algorithm, quantum chemistry energy estimates, and amplitude estimation. After the controlled powers imprint their phases, and just before the inverse quantum Fourier transform runs, the counting register holds this state.

Show the math
\displaystyle \tfrac{1}{\sqrt{2^{n}}}\sum_{k=0}^{2^{n}-1} e^{\,2\pi i\,\varphi k}\,|k\rangle

This is exactly a quantum Fourier transform of a phase-φ signal. The inverse transform therefore turns it into the binary digits of φ on the counting wires.

Quantum phase estimation, one of the core quantum circuits: controlled powers of U, inverse QFT, then measurement
Quantum phase estimation: three counting qubits in superposition control U once, twice, and four times, and an inverse QFT converts the accumulated phase into measurable bits.

Qiskit reports this circuit at four qubits, three classical bits and a depth of six. The gate count comes to three Hadamards, three controlled powers of U, one inverse quantum Fourier transform and three measurements.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit import Gate, ControlledGate

def cpow(name, label):
    base = Gate(name, 1, [], label=label)
    return ControlledGate("c-" + name, 2, [], num_ctrl_qubits=1, base_gate=base)

qc = QuantumCircuit(QuantumRegister(3, "count"), QuantumRegister(1, "psi"),
                    ClassicalRegister(3, "c"))
qc.h([0, 1, 2])
qc.append(cpow("u1", "$U^1$"), [2, 3])
qc.append(cpow("u2", "$U^2$"), [1, 3])
qc.append(cpow("u4", "$U^4$"), [0, 3])
qc.append(Gate("qft_dg", 3, [], label="QFT†"), [0, 1, 2])
qc.measure([0, 1, 2], [0, 1, 2])
qc.draw("mpl")
See it run

The counting register lands on 001 in every one of 4096 shots, and 001 is binary for one. Dividing by eight possible readings gives a phase of exactly 1/8, which is precisely the phase the T gate imprints on its excited eigenstate. Because 1/8 fits in three bits with nothing left over, the readout is deterministic rather than statistical, which is how these quantum circuits pin down an exact phase.

Histogram from running quantum circuits for phase estimation: all 4096 shots read 001, a phase of one eighthPhase estimation of the T gate with three counting qubits: every one of 4096 simulated shots returns 001, which is binary for one, so the estimated phase is exactly 1/8.
Run this example yourself
from math import pi
from qiskit import QuantumCircuit
from qiskit.circuit.library import QFTGate
from qiskit.primitives import StatevectorSampler

qc = QuantumCircuit(4, 3)
qc.x(3)                       # eigenstate |1> of T
qc.h([0, 1, 2])
for j in range(3):
    for _ in range(2 ** j):
        qc.cp(pi / 4, j, 3)   # controlled-T, applied 2^j times
qc.append(QFTGate(3).inverse(), [0, 1, 2])
qc.measure([0, 1, 2], [0, 1, 2])

sampler = StatevectorSampler(seed=7)
counts = sampler.run([qc], shots=4096).result()[0].data.c.get_counts()
print(counts)                 # {'001': 4096} so the phase is 1/8

Grover Phase Oracle

A Grover oracle marks the answer to a search problem with a phase rather than a flag you can read. The boxed operation maps the marked basis state to minus itself while leaving every other amplitude alone, hiding the answer in a sign that later interference will expose. Building this oracle is the problem-specific part of any Grover search. The oracle flips the sign of the marked answer and leaves every other basis state untouched.

Show the math
O_f\,|x\rangle = (-1)^{f(x)}\,|x\rangle
Grover phase oracle in quantum circuits notation, a boxed O_f applying a sign flip to the marked state
The Grover oracle O_f maps |x⟩ to (−1)^f(x)|x⟩, flipping the sign of the marked basis state while leaving every amplitude magnitude untouched.

Qiskit reports this circuit at three qubits and a depth of one. The gate count comes to one oracle.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Gate

qc = QuantumCircuit(3)
qc.append(Gate("of", 3, [], label="$O_f$"), [0, 1, 2])
qc.draw("mpl")
See it run

Before the oracle every amplitude sits at +0.354, and afterward the amplitude of 101 reads −0.354 while the other seven are untouched. Squaring either set gives the same 0.125 probability for all eight states, so no measurement can tell the two situations apart. The mark is stored purely in the sign, which is exactly what the diffusion step later converts into a measurable bias inside Grover’s quantum circuits.

Signed amplitudes from quantum circuits before and after a Grover oracle: state 101 flips to minus 0.354A Grover oracle flips the sign of the marked state 101, from +0.354 to −0.354, while all eight measured probabilities remain 0.125; probabilities alone cannot see the mark.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

prep = QuantumCircuit(3)
prep.h([0, 1, 2])
before = Statevector.from_instruction(prep).data.real

oracle = QuantumCircuit(3)
oracle.x(1)
oracle.ccz(0, 1, 2)           # phase flip on |101>
oracle.x(1)
after = Statevector.from_instruction(prep.compose(oracle)).data.real

print("before:", np.round(before, 4))
print("after :", np.round(after, 4))
print("probabilities equal:", np.allclose(before**2, after**2))

Grover Diffusion Operator

The diffusion operator turns the oracle’s hidden sign into a measurable boost. Sandwiching a multi-controlled Z between layers of Hadamard and X gates reflects every amplitude about their mean, so the marked state grows while the rest shrink. Oracle then diffusion is one Grover step, the repeated engine inside search-based quantum circuits. The operator and its effect on the amplitudes read as follows.

Show the math
\displaystyle D = 2|s\rangle\langle s| - I,\quad |s\rangle = \tfrac{1}{\sqrt{N}}\sum_{x}|x\rangle
a_x \to 2\bar{a} - a_x \quad (\bar{a} = \text{mean of all amplitudes})

Every amplitude is reflected through the average of them all. The one negative marked amplitude therefore lands far above the rest.

Grover diffusion operator, one of the workhorse quantum circuits: H and X layers around a multi-controlled Z
The diffusion operator sandwiches a multi-controlled Z between layers of Hadamard and X gates, reflecting every amplitude about the mean.

Qiskit reports this circuit at three qubits and a depth of five. The gate count comes to six Hadamards, six X gates and one multi-controlled Z gate.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Gate, ControlledGate

qc = QuantumCircuit(3)
qc.h([0, 1, 2])
qc.x([0, 1, 2])
mcz = ControlledGate("mcz", 3, [], num_ctrl_qubits=2,
                     base_gate=Gate("z", 1, [], label="Z"))
qc.append(mcz, [0, 1, 2])
qc.x([0, 1, 2])
qc.h([0, 1, 2])
qc.draw("mpl")
See it run

Starting from the uniform superposition, a single oracle plus diffusion round lifts the marked state from 12.5 percent to 78.125 percent. The other seven states drop to 3.125 percent each, so one round of these quantum circuits already makes the answer the overwhelmingly likely readout on three qubits.

Probabilities from quantum circuits before and after one Grover round: marked state 101 rises to 78.1 percentOne oracle plus diffusion round lifts the marked state 101 from 12.5 percent to 78.125 percent, with the other seven states falling to 3.125 percent each.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

qc = QuantumCircuit(3)
qc.h([0, 1, 2])                       # uniform start, all P = 0.125
qc.x(1); qc.ccz(0, 1, 2); qc.x(1)     # oracle: flip sign of |101>
qc.h([0, 1, 2]); qc.x([0, 1, 2])
qc.ccz(0, 1, 2)                       # diffusion: invert about the mean
qc.x([0, 1, 2]); qc.h([0, 1, 2])

probs = Statevector.from_instruction(qc).probabilities()
for k, p in enumerate(probs):
    print(f"{k:03b}: {p:.5f}")        # 101 reaches 0.78125

Amplitude Amplification

Amplitude amplification is Grover search generalised to any state-preparation routine. Each round applies the oracle then the diffusion reflection, and repeating the bracketed pair about the square root of N times rotates the register toward the marked subspace. The quadratic speedup it delivers is the workhorse behind many quantum circuits beyond plain search. Each Grover round rotates the state a fixed angle toward the marked answer, and the amplitude follows a sine.

Show the math
\text{amplitude after}\ k\ \text{rounds} = \sin\big((2k+1)\theta\big),\quad \sin\theta = \tfrac{1}{\sqrt{N}}
k_{\text{best}} \approx \tfrac{\pi}{4}\sqrt{N}

The sine keeps rotating past the peak once you pass the ideal count, which is the overshoot the run below shows at rounds three and four. Stopping at the right round is the whole art, since more iterations can make quantum circuits less likely to succeed, not more.

Amplitude amplification quantum circuits pattern: oracle and diffusion blocks repeated inside a bracket about √N times
One oracle call followed by one diffusion step forms a Grover round; repeating the bracketed pair about √N times drives the register toward the marked state.

Qiskit reports this circuit at three qubits, three classical bits and a depth of four. The gate count comes to three Hadamards, one oracle, one diffusion operator and three measurements.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Gate

qc = QuantumCircuit(3, 3)
qc.h([0, 1, 2])
qc.barrier()
qc.append(Gate("of", 3, [], label="$O_f$"), [0, 1, 2])
qc.append(Gate("d", 3, [], label="D"), [0, 1, 2])
qc.barrier()
qc.measure([0, 1, 2], [0, 1, 2])
qc.draw("mpl")
See it run

The marked state probability climbs from 12.5 percent to 78.1 percent after one round and peaks at 94.5 percent after two. A third round overshoots and drags it down to 33 percent, and a fourth all but erases it at 1.2 percent. Grover iteration is a rotation, not a ratchet, so the stopping count matters as much as the quantum circuits themselves.

Marked state probability versus Grover rounds in simulated quantum circuits, peaking at 94.5 percent at two roundsProbability of the marked state over zero to six Grover rounds: it peaks at 94.5 percent after two rounds, then overshoots and collapses to 1.2 percent by round four.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

def grover(k):
    qc = QuantumCircuit(3)
    qc.h([0, 1, 2])
    for _ in range(k):
        qc.x(1); qc.ccz(0, 1, 2); qc.x(1)      # oracle marks |101>
        qc.h([0, 1, 2]); qc.x([0, 1, 2])
        qc.ccz(0, 1, 2)
        qc.x([0, 1, 2]); qc.h([0, 1, 2])       # diffusion
    return Statevector.from_instruction(qc).probabilities()[5]

for k in range(7):
    print(f"rounds={k}: P(101) = {grover(k):.5f}")

The Hadamard Test

The Hadamard test estimates the expectation value of a unitary using a single ancilla. The ancilla is put into superposition, controls U on the main register, and is interfered back with a Hadamard, so the bias in its outcomes equals the real part of the expectation. It is a building block of variational algorithms and of quantum-enhanced linear algebra. The two outcome probabilities encode the overlap directly.

Show the math
P(0) = \tfrac{1}{2}\big(1 + \operatorname{Re}\langle\psi|U|\psi\rangle\big)
P(0) - P(1) = \operatorname{Re}\langle\psi|U|\psi\rangle
Hadamard test, a staple of variational quantum circuits: ancilla H, controlled-U, H, then measurement
The Hadamard test interferes an ancilla with |ψ⟩ through a controlled-U; the bias in the ancilla’s outcomes equals Re ⟨ψ|U|ψ⟩.

Qiskit reports this circuit at two qubits, one classical bit and a depth of four. The gate count comes to two Hadamards, one controlled-U gate and one measurement.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Gate, ControlledGate

qc = QuantumCircuit(2, 1)
qc.h(0)
cu = ControlledGate("c-u", 2, [], num_ctrl_qubits=1,
                    base_gate=Gate("u_box", 1, [], label="$U$"))
qc.append(cu, [0, 1])
qc.h(0)
qc.measure(0, 0)
qc.draw("mpl")
See it run

The exact real overlap of T on the plus state is one half of one plus cos(pi/4), which is 0.8536 to four places. The sampled estimate moves from 0.9062 at 64 shots to 0.8579 at 4096 shots, shrinking the error from roughly 0.05 to roughly 0.004. Statistical noise falls as one over the square root of the shot count, so each factor of four in shots halves the error bar.

Hadamard test quantum circuits sampled at rising shot counts converge on the exact overlap 0.8536Hadamard test estimates of the real overlap of T on the plus state at 64 to 4096 shots, converging on the exact value 0.8536.
Run this example yourself
from math import pi, cos
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

qc = QuantumCircuit(2, 1)
qc.h(1)                    # |psi> = |+>
qc.h(0)
qc.cp(pi / 4, 0, 1)        # controlled-T
qc.h(0)
qc.measure(0, 0)

exact = (1 + cos(pi / 4)) / 2
for shots in (64, 256, 1024, 4096):
    r = StatevectorSampler(seed=7).run([qc], shots=shots).result()
    c = r[0].data.c.get_counts()
    est = (c.get("0", 0) - c.get("1", 0)) / shots
    print(f"shots={shots}: estimate {est:.4f}  exact {exact:.4f}")

The Swap Test

The swap test measures how similar two quantum states are without reading either one directly. An ancilla controls a SWAP between the two registers, and a Hadamard plus measurement on the ancilla reports the squared overlap through its probability of reading zero. It appears in quantum machine learning kernels and in state-fingerprinting protocols. The probability of reading zero on the ancilla encodes the squared overlap.

Show the math
P(0) = \tfrac{1}{2} + \tfrac{1}{2}\,|\langle\psi|\varphi\rangle|^{2}

Identical states give P(0) equal to 1, and orthogonal states give exactly 1/2. Every value in between reports the squared overlap of the two inputs.

Swap test quantum circuits diagram: an ancilla-controlled SWAP of two states with an H and measure on the ancilla
In the swap test an ancilla controls a SWAP of |ψ⟩ and |φ⟩; the probability of reading 0 encodes the squared overlap of the two states.

Qiskit reports this circuit at three qubits, one classical bit and a depth of four. The gate count comes to two Hadamards, one controlled-swap and one measurement.

Build it in Qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(3, 1)
qc.h(0)
qc.cswap(0, 1, 2)
qc.h(0)
qc.measure(0, 0)
qc.draw("mpl")
See it run

With identical inputs the ancilla reads zero in all 4096 shots, and with orthogonal inputs it reads zero 50.4 percent of the time against an exact 50 percent. The partially overlapping pair, prepared with a rotation giving a squared overlap of 0.75, lands at 87.3 percent against the exact 87.5. One ancilla measurement therefore lets quantum circuits estimate how similar two quantum states are without ever revealing the states themselves.

Swap test quantum circuits compare three state pairs; ancilla statistics match the exact overlapsSwap test ancilla statistics at 4096 shots for identical, orthogonal, and partially overlapping state pairs, against the exact predictions 1.0, 0.5, and 0.875.
Run this example yourself
from math import pi, cos
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

def swap_test(prep):
    qc = QuantumCircuit(3, 1)
    prep(qc)                          # psi on q1, phi on q2
    qc.h(0); qc.cswap(0, 1, 2); qc.h(0)
    qc.measure(0, 0)
    r = StatevectorSampler(seed=7).run([qc], shots=4096).result()
    return round(r[0].data.c.get_counts().get("0", 0) / 4096, 4)

print("identical :", swap_test(lambda qc: None), " exact 1.0")
print("orthogonal:", swap_test(lambda qc: qc.x(2)), " exact 0.5")
print("partial   :", swap_test(lambda qc: qc.ry(pi / 3, 2)),
      " exact", (1 + cos(pi / 6) ** 2) / 2)

The Uncompute Trick

Uncomputation is the discipline of cleaning up after yourself. A subroutine V computes an intermediate result, a CNOT copies the useful answer to an output qubit, and V-dagger runs the subroutine backwards to return the scratch qubits to zero. Skipping this step leaves garbage entangled with your answer and quietly destroys the interference an algorithm depends on. A helper register computes an intermediate value, hands its result to the main wire, then runs backward to erase itself.

Show the math
|x\rangle|0\rangle|0\rangle \xrightarrow{\,V\,} |x\rangle|g(x)\rangle|f(x)\rangle \xrightarrow{\ \text{copy},\ V^{\dagger}\ } |x\rangle|0\rangle|f(x)\rangle

The garbage g(x) must return to |0⟩, or it stays entangled with the answer and wrecks later interference. Clean uncomputation is what keeps large quantum circuits reversible and free of stray correlations.

Uncompute pattern in quantum circuits: compute V, copy the answer with a CNOT, then V dagger cleans the scratch qubit
Bennett’s uncompute trick: V computes f(x) into a scratch qubit, a CNOT copies the answer to the output, and V† returns the scratch qubit to |0⟩.

Qiskit reports this circuit at three qubits and a depth of three. The gate count comes to one controlled-NOT, one subroutine block and one inverse subroutine block.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Gate

qc = QuantumCircuit(3)
qc.append(Gate("v", 2, [], label="$V$"), [0, 1])
qc.cx(1, 2)
qc.append(Gate("vdg", 2, [], label="$V^\\dagger$"), [0, 1])
qc.draw("mpl")
See it run

With the uncompute step the work qubit returns to zero with probability one and purity one, so it is exactly the fresh qubit it started as. Leave the step out and the same qubit shows a 50/50 mixture with purity one half, meaning it stays entangled with the answer register. That stray entanglement would wreck any later interference, which is why well-behaved quantum circuits clean up after themselves.

Uncompute demonstration in quantum circuits: work qubit returns exactly to zero, versus an entangled 50/50 mixThe work qubit after compute, copy, uncompute is exactly zero with purity one; skipping the uncompute leaves it in an entangled 50/50 mixture with purity one half.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, partial_trace

def work_qubit(uncompute):
    qc = QuantumCircuit(3)
    qc.h(0)          # input superposition
    qc.cx(0, 1)      # compute into the work qubit
    qc.cx(1, 2)      # copy the answer out
    if uncompute:
        qc.cx(0, 1)  # undo the work
    rho = partial_trace(Statevector.from_instruction(qc), [0, 2])
    probs = np.round(np.real(np.diag(rho.data)), 5)
    purity = round(float(np.real(np.trace(rho.data @ rho.data))), 3)
    return probs, purity

print("with uncompute   :", work_qubit(True))   # ([1. 0.], 1.0)
print("without uncompute:", work_qubit(False))  # ([0.5 0.5], 0.5)

Decomposing the Toffoli Gate

The Toffoli, or controlled-controlled-NOT, is the reversible AND gate, but hardware cannot run it directly. The standard decomposition compiles one Toffoli into six CNOTs, seven T and T-dagger rotations, and two Hadamards, the form a real device actually executes. Those seven T gates dominate its cost on fault-tolerant machines, which is why compilers work hard to minimise them. The three-qubit gate flips its target only when both controls are one, and hardware builds it from smaller pieces.

Show the math
\mathrm{CCX}\,|a, b, c\rangle = |a,\ b,\ c \oplus (a\cdot b)\rangle
Toffoli decomposition, showing how quantum circuits compile a three-qubit gate into H, CNOT, and T gates
The standard decomposition compiles one Toffoli into six CNOTs, seven T or T† rotations, and two Hadamards, the form real hardware actually executes.

Qiskit reports this circuit at three qubits and a depth of 11. The gate count comes to two Hadamards, four T gates, three T-dagger gates and six controlled-NOTs.

Build it in Qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(3)
qc.h(2); qc.cx(1, 2); qc.tdg(2); qc.cx(0, 2); qc.t(2)
qc.cx(1, 2); qc.tdg(2); qc.cx(0, 2)
qc.t(1); qc.t(2); qc.h(2)
qc.cx(0, 1); qc.t(0); qc.tdg(1); qc.cx(0, 1)
qc.draw("mpl")
See it run

All eight basis inputs produce identical outputs from the native Toffoli and from its 15 gate decomposition, with only the 011 and 111 inputs flipping the target. The simulation also confirms the two unitaries are equivalent as full matrices, so the match holds for superposition inputs too. Six CNOTs, four T gates, three inverse T gates, and two Hadamards are the standard recipe when quantum circuits run on hardware without native three-qubit gates.

Truth table from simulated quantum circuits: the 15 gate Toffoli decomposition matches the native gate on all inputsSimulated over all eight basis inputs, the 15 gate CNOT plus T decomposition reproduces the native Toffoli truth table eight out of eight, and the full unitaries are equivalent.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, Operator

tof = QuantumCircuit(3); tof.ccx(0, 1, 2)
dec = QuantumCircuit(3)
dec.h(2); dec.cx(1, 2); dec.tdg(2); dec.cx(0, 2); dec.t(2); dec.cx(1, 2)
dec.tdg(2); dec.cx(0, 2); dec.t(1); dec.t(2); dec.h(2); dec.cx(0, 1)
dec.t(0); dec.tdg(1); dec.cx(0, 1)             # 15 gates total

for x in range(8):
    init = QuantumCircuit(3)
    [init.x(q) for q in range(3) if (x >> q) & 1]
    kt = np.argmax(Statevector.from_instruction(init.compose(tof)).probabilities())
    kd = np.argmax(Statevector.from_instruction(init.compose(dec)).probabilities())
    print(f"{x:03b}: toffoli {kt:03b}  decomposition {kd:03b}  match {kt == kd}")
print("unitaries equivalent:", Operator(dec).equiv(Operator(tof)))

A Quantum Random Bit

A quantum random number generator is the simplest useful circuit there is. One Hadamard creates an equal superposition and one measurement collapses it, producing a bit that is random by the laws of physics rather than by a deterministic formula. Certified quantum randomness of exactly this kind now backs commercial security products. A single Hadamard on a fresh qubit splits it into an even superposition before the measurement lands.

Show the math
P(0) = |\langle 0|H|0\rangle|^{2} = \tfrac{1}{2},\qquad P(1) = |\langle 1|H|0\rangle|^{2} = \tfrac{1}{2}
One of the simplest quantum circuits: a Hadamard then a measurement produces a truly random bit.
A Hadamard and a measurement, the simplest useful quantum circuit.

Qiskit reports this circuit at one qubit, one classical bit and a depth of two. The gate count comes to one Hadamard and one measurement.

Build it in Qiskit
from qiskit import QuantumCircuit

qc = QuantumCircuit(1, 1)
qc.h(0)
qc.measure(0, 0)
qc.draw("mpl")
See it run

Across 4,096 shots the circuit returned 2066 zeros and 2030 ones, a deviation of just 18 counts from a perfect split and well inside the expected statistical noise of about 32. Unlike the pseudorandom generators in ordinary software, each bit comes from a genuine quantum measurement, so in these quantum circuits the randomness is physical rather than algorithmic.

Quantum circuits as coin flips: 4096 shots of H plus measure give 2066 zeros and 2030 ones.Sampled counts from a single Hadamard and measurement: 2066 zeros and 2030 ones out of 4096 shots.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

qc = QuantumCircuit(1, 1)
qc.h(0)
qc.measure(0, 0)
job = StatevectorSampler(seed=7).run([qc], shots=4096)
print(job.result()[0].data.c.get_counts())  # {'1': 2030, '0': 2066}

Arithmetic and simulation circuits

To compute with numbers or imitate physics, quantum circuits need reversible arithmetic and controlled time evolution. These patterns show how addition, modular multiplication, and Hamiltonian simulation are expressed as concrete gates.

Quantum Half Adder

Arithmetic on a quantum computer must be reversible, and the half adder shows how. A Toffoli writes the carry bit as the AND of the two inputs, then a CNOT writes the sum as their XOR, with no information discarded. Chaining these units builds the ripple-carry adders inside Shor’s algorithm and other arithmetic-heavy quantum circuits. A CNOT writes the sum bit and a Toffoli writes the carry, both from the same two inputs.

Show the math
|a, b, 0\rangle \to |a,\ a\oplus b,\ a\cdot b\rangle \quad (\text{sum} = a\oplus b,\ \text{carry} = a\cdot b)
Quantum circuits can add: a Toffoli and a CNOT compute the sum and carry of two bits.
A Toffoli computes the carry, then a CNOT computes the sum.

Qiskit reports this circuit at three qubits and a depth of two. The gate count comes to one Toffoli gate and one controlled-NOT.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister

a = QuantumRegister(1, "a")
b = QuantumRegister(1, "b")
carry = QuantumRegister(1, "carry")
qc = QuantumCircuit(a, b, carry)
qc.ccx(a[0], b[0], carry[0])
qc.cx(a[0], b[0])
qc.draw("mpl")
See it run

All four input pairs were prepared and sampled 256 times each, and every shot returned the correct answer, 1,024 correct outcomes out of 1,024. The Toffoli writes the AND of the inputs to the carry wire while the CNOT writes their XOR to the sum wire, so the arithmetic these quantum circuits perform is exact rather than probabilistic.

Quantum circuits doing arithmetic: the half adder returns the correct sum and carry on all 1024 shots.Every input pair, sampled 256 times each, returns the correct sum and carry on every single shot.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

for a in (0, 1):
    for b in (0, 1):
        qc = QuantumCircuit(3, 2)
        if a: qc.x(0)
        if b: qc.x(1)
        qc.ccx(0, 1, 2)   # carry = a AND b
        qc.cx(0, 1)       # sum  = a XOR b
        qc.measure([1, 2], [0, 1])
        job = StatevectorSampler(seed=11).run([qc], shots=256)
        (bits, n), = job.result()[0].data.c.get_counts().items()
        print(f"a={a} b={b} -> sum={bits[1]} carry={bits[0]} ({n}/256 shots)")

Modular Exponentiation

Modular exponentiation is the expensive core of Shor’s factoring algorithm. Each qubit of a superposed exponent register controls a modular multiplier, multiplying the work register by a, a squared, a to the fourth, and so on. Feeding this block a superposition computes a-to-the-x mod N for every x at once, the most demanding part of the quantum circuits that threaten RSA. The circuit raises a base to a superposition of exponents, and the result marches through a repeating cycle.

Show the math
f(x) = a^{x} \bmod N;\qquad 7^{x} \bmod 15 = 1, 7, 4, 13, 1, 7, \dots \ (\text{period}\ r = 4)
\gcd(7^{\,r/2} - 1,\ 15) = 3 \qquad \gcd(7^{\,r/2} + 1,\ 15) = 5
Shor-style modular exponentiation, one of the key quantum circuits in factoring, built from controlled multipliers.
Each control qubit selects which power of a multiplies the work register.

Qiskit reports this circuit at five qubits and a depth of four. The gate count comes to three Hadamards and three controlled modular multipliers.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister
from qiskit.circuit import Gate, ControlledGate

x = QuantumRegister(3, "x")
w = QuantumRegister(2, "w")
qc = QuantumCircuit(x, w)
qc.h(x)
for i, lab in enumerate(["×a mod N", "×a² mod N", "×a⁴ mod N"]):
    g = ControlledGate(f"m{i}", 3, [], label=None, num_ctrl_qubits=1,
                       base_gate=Gate(f"m{i}", 2, [], label=lab))
    qc.append(g, [x[i], w[0], w[1]])
qc.draw("mpl")
See it run

Computing seven to the power x modulo 15 for x from zero to seven gives 1, 7, 4, 13 and then the same four values again, so the period is four. Shor’s algorithm evaluates this function on a superposition of every exponent at once, and the quantum Fourier transform reads the period out of the resulting interference pattern. That single number unlocks the factors, since gcd of seven squared plus or minus one with 15 returns three and five.

The period of 7^x mod 15 repeats every four steps, the pattern Shor's quantum circuits extract with the QFT.The values of 7^x mod 15 for x = 0 to 7: the sequence 1, 7, 4, 13 repeats with period four.
Run this example yourself
from math import gcd

vals = [pow(7, x, 15) for x in range(8)]
print("7^x mod 15 for x = 0..7:", vals)
r = next(r for r in range(1, 8) if pow(7, r, 15) == 1)
print("period r =", r)
print("factors:", gcd(7 ** (r // 2) - 1, 15), gcd(7 ** (r // 2) + 1, 15))

Trotterized Time Evolution

Simulating how a quantum system evolves means approximating the exponential of its Hamiltonian. A Trotter step slices that evolution into thin alternating layers, here a ZZ coupling layer and an X field layer, repeated to build up the full time. More slices give a better approximation, so the pattern trades circuit depth for simulation accuracy. The splitting and its accuracy cost can be written compactly.

Show the math
e^{(A+B)\,t} \approx \big(e^{A\,t/n}\,e^{B\,t/n}\big)^{n}
\text{error per total evolution} = O(t^{2}/n)

First-order Trotter error over the whole evolution scales as t²/n, so doubling n roughly halves it. The run’s measured infidelity falls even faster, tracking 1/n², because fidelity is quadratic in the state error.

Trotter steps let quantum circuits approximate e^(-iHt) with alternating ZZ and X layers repeated n times.
Alternating ZZ and X layers, repeated n times, approximate continuous time evolution.

Qiskit reports this circuit at three qubits and a depth of three. The gate count comes to three RX rotations and two RZZ couplings.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter

zz = Parameter("2Jδt")
hx = Parameter("2hδt")
qc = QuantumCircuit(3)
qc.rzz(zz, 0, 1)
qc.rzz(zz, 1, 2)
qc.rx(hx, 0)
qc.rx(hx, 1)
qc.rx(hx, 2)
qc.draw("mpl")
See it run

A single Trotter step approximates the exact evolution with an infidelity of 0.255, while eight steps bring it down to 0.0024, roughly 107 times closer. The error shrinks along the expected one over n squared trend, which is why deeper Trotter quantum circuits buy accuracy at a predictable price.

Trotterized quantum circuits close in on exact evolution: infidelity falls from 0.255 to 0.0024 by eight steps.Infidelity of the Trotter state against exact evolution for one, two, four, and eight steps.
Run this example yourself
import numpy as np
from scipy.linalg import expm
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

Z, X, I = np.diag([1, -1]), np.array([[0, 1], [1, 0]]), np.eye(2)
H = np.kron(Z, Z) + np.kron(X, I) + np.kron(I, X)
t = 0.8
exact = expm(-1j * H * t) @ np.array([1, 0, 0, 0], dtype=complex)
for n in (1, 2, 4, 8):
    qc = QuantumCircuit(2)
    for _ in range(n):
        qc.rzz(2 * t / n, 0, 1)
        qc.rx(2 * t / n, 0)
        qc.rx(2 * t / n, 1)
    F = abs(np.vdot(exact, Statevector.from_instruction(qc).data)) ** 2
    print(f"{n} steps: infidelity {1 - F:.4f}")

Quantum State Preparation

Many algorithms assume the register already holds a specific state, and state preparation is how you get there. A cascade of plain and controlled RY rotations sculpts arbitrary real amplitudes across the qubits, one branch at a time. Preparing a general n-qubit state can cost exponentially many gates, which makes efficient special-case loaders a research topic of their own. A cascade of controlled rotations carves an arbitrary amplitude profile out of the all-zero start.

Show the math
\displaystyle |\psi\rangle = \sum_{x} \sqrt{p_x}\,|x\rangle
\cos(\theta_1/2) = \sqrt{p_0} \quad (\text{first angle; each later angle splits the remainder})
State preparation with quantum circuits: a cascade of RY rotations builds any target amplitudes.
Plain and controlled RY rotations sculpt arbitrary amplitudes across three qubits.

Qiskit reports this circuit at three qubits and a depth of three. The gate count comes to two controlled-RY rotations and one RY rotation.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter

qc = QuantumCircuit(3)
qc.ry(Parameter("θ[0]"), 0)
qc.cry(Parameter("θ[1]"), 0, 1)
qc.cry(Parameter("θ[2]"), 1, 2)
qc.draw("mpl")
See it run

The two rotation angles, 1.571 and 1.369 radians, come straight from arccos of the branch probabilities rather than from any tuning. A 4,096-shot run then reproduced the 0.5, 0.3, 0.2 target with a worst-case deviation of 0.009, exactly the level of agreement shot noise allows, which is all these quantum circuits are asked to guarantee.

Quantum circuits shaping a distribution: two RY angles hit a 0.5/0.3/0.2 target within 0.009.Target probabilities beside the 4096-shot estimates for the two-angle RY cascade.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.primitives import StatevectorSampler

t1 = 2 * np.arccos(np.sqrt(0.5))   # split 1.0 into 0.5 and 0.5
t2 = 2 * np.arccos(np.sqrt(0.6))   # split 0.5 into 0.3 and 0.2
qc = QuantumCircuit(2)
qc.ry(t1, 1)
qc.cry(t2, 1, 0)
qc.measure_all()
job = StatevectorSampler(seed=5).run([qc], shots=4096)
counts = job.result()[0].data.meas.get_counts()
print({k: round(v / 4096, 3) for k, v in sorted(counts.items())})

Angle Encoding

Angle encoding is the most common way to feed classical data into a quantum model. Each feature value becomes the angle of an RY rotation, so a data point maps directly onto the Bloch sphere of its qubit. It is cheap and hardware-friendly, which is why most near-term quantum machine learning starts here. A single RY rotation places one feature on the Bloch sphere and fixes the measurement statistics.

Show the math
R_Y(x)\,|0\rangle = \cos(x/2)\,|0\rangle + \sin(x/2)\,|1\rangle
P(1) = \sin^{2}(x/2)
Angle encoding in quantum circuits: classical features x0, x1, x2 become RY rotation angles.
Classical data enters the circuit directly as RY rotation angles.

Qiskit reports this circuit at three qubits and a depth of one. The gate count comes to three RY rotations.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter

qc = QuantumCircuit(3)
for i in range(3):
    qc.ry(Parameter(f"x[{i}]"), i)
qc.draw("mpl")
See it run

Encoding the vector (0.4, 1.1, 2.3) concentrates 58 percent of the probability on the state 100, while (2.0, 0.2, 1.4) spreads its weight over a completely different set of outcomes. Running the first vector a second time reproduces its distribution exactly, bar for bar, which is what makes these quantum circuits a deterministic feature map rather than a sampling trick.

Angle encoding in quantum circuits: two data vectors give different outputs, one vector twice gives identical bars.Output distributions for two feature vectors, then the first vector encoded a second time.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

def encode(x):
    qc = QuantumCircuit(3)
    for i, v in enumerate(x):
        qc.ry(v, i)
    return Statevector.from_instruction(qc).probabilities()

pA = encode([0.4, 1.1, 2.3])
pB = encode([2.0, 0.2, 1.4])
print("A:", np.round(pA, 3))
print("B:", np.round(pB, 3))
print("re-encode of A is identical:", np.array_equal(pA, encode([0.4, 1.1, 2.3])))
Bloch sphere showing angle encoding in quantum circuits, an RY rotation tilting the vector to encode data in its latitudeA 45 degree RY rotation tilts the vector partway from the pole toward the equator, encoding a continuous value in its latitude. Push the angle further and the same wire stores a different number, which is how a classical feature is written into a qubit. Explore this live on our interactive Bloch sphere.

Variational patterns for NISQ hardware

The variational patterns are tuned for the noisy processors available today. They combine trainable circuit templates with gradient rules and error-mitigation tricks so that shallow quantum circuits can still return useful answers.

Hardware-Efficient Ansatz

A hardware-efficient ansatz is a trainable circuit shaped to fit a real device rather than a clean mathematical form. Each layer applies RY and RZ rotations to every qubit and then a ladder of CZ gates matched to the chip’s connectivity, and the layer repeats L times. Its native-gate structure keeps noise manageable, which is why these shallow quantum circuits dominate near-term experiments, though very deep versions can suffer from barren plateaus. Layers of single-qubit rotations and native entanglers repeat L times to cover a rich slice of states.

Show the math
|\psi(\theta)\rangle = \big[\,\text{entangler}\cdot R_Z(\theta)\,R_Y(\theta)\ \text{layers}\,\big]^{L}\,|0\dots0\rangle
Hardware-efficient ansatz: layered quantum circuits of RY and RZ rotations plus a CZ entangling ladder.
One trainable layer of RY and RZ rotations followed by a CZ ladder, repeated L times.

Qiskit reports this circuit at three qubits and a depth of four. The gate count comes to three RY rotations, three RZ rotations and two controlled-Z gates.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter

qc = QuantumCircuit(3)
for i in range(3):
    qc.ry(Parameter(f"θ[{i}]"), i)
for i in range(3):
    qc.rz(Parameter(f"θ[{i + 3}]"), i)
qc.cz(0, 1)
qc.cz(1, 2)
qc.draw("mpl")
See it run

Two random six-angle parameter sets produced clearly different output distributions from the same one-layer ansatz. The least pure qubit scored 0.540 in the first run and 0.648 in the second, and since any unentangled state would score exactly one, both figures certify that these quantum circuits genuinely entangle the register.

Hardware-efficient quantum circuits: two random parameter sets give entangled states with qubit purity 0.54 and 0.65.Output distributions for two random parameter sets, with the minimum single-qubit purity of each run.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, partial_trace

def ansatz(th):
    qc = QuantumCircuit(3)
    for i in range(3):
        qc.ry(th[i], i)
        qc.rz(th[i + 3], i)
    qc.cz(0, 1)
    qc.cz(1, 2)
    return Statevector.from_instruction(qc)

rng = np.random.default_rng(3)
for name in ("A", "B"):
    sv = ansatz(rng.uniform(0, 2 * np.pi, 6))
    pur = min(partial_trace(sv, [j for j in range(3) if j != k]).purity().real
              for k in range(3))
    print(name, np.round(sv.probabilities(), 3), f"min purity {pur:.3f}")

One QAOA Round

The quantum approximate optimisation algorithm tackles combinatorial problems by alternating two unitaries. A cost layer applies ZZ phase rotations with angle γ to encode the problem, then a mixer layer rotates every qubit with angle β, and the pair repeats for p rounds. Tuning the angles steers amplitude toward good solutions, making it one of the most studied variational quantum circuits for optimisation. One round alternates a cost phase and a mixing phase, each set by its own tunable angle.

Show the math
|\gamma, \beta\rangle = e^{-i\beta B}\,e^{-i\gamma C}\,|{+}\dots{+}\rangle
\text{classical optimizer maximizes}\ \ \langle\gamma, \beta|\,C\,|\gamma, \beta\rangle
One QAOA round: quantum circuits alternate an RZZ cost layer and an RX mixer layer for p rounds.
The cost unitary applies phase twists with angle γ, then the mixer rotates every qubit with angle β.

Qiskit reports this circuit at three qubits and a depth of four. The gate count comes to three Hadamards, three RX rotations and two RZZ couplings.

Build it in Qiskit
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter

g = Parameter("γ")
b = Parameter("β")
qc = QuantumCircuit(3)
qc.h([0, 1, 2])
qc.barrier()
qc.rzz(g, 0, 1)
qc.rzz(g, 1, 2)
qc.rx(b, 0)
qc.rx(b, 1)
qc.rx(b, 2)
qc.draw("mpl")
See it run

Sweeping the cost angle gamma and the mixer angle beta over a 33 by 17 grid produced a smooth cost landscape whose peak sits at exactly 1.000, reached at gamma equal to pi over two and beta equal to three pi over eight. That value is the true MaxCut of the one-edge graph, so a single round of these quantum circuits already solves this smallest instance outright.

One QAOA round in quantum circuits reaches the exact MaxCut value 1.000 at gamma pi/2 and beta 3pi/8.Cut expectation across the gamma and beta grid, with the optimum marked in amber.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, SparsePauliOp

def cut(g, b):
    qc = QuantumCircuit(2)
    qc.h([0, 1])
    qc.rzz(g, 0, 1)
    qc.rx(2 * b, 0)
    qc.rx(2 * b, 1)
    zz = Statevector.from_instruction(qc).expectation_value(SparsePauliOp("ZZ"))
    return 0.5 * (1 - zz.real)

gs, bs = np.linspace(0, np.pi, 33), np.linspace(0, np.pi / 2, 17)
C = np.array([[cut(g, b) for g in gs] for b in bs])
i, j = np.unravel_index(C.argmax(), C.shape)
print(f"max cut expectation {C[i, j]:.3f} at gamma={gs[j]:.4f}, beta={bs[i]:.4f}")

The Parameter Shift Rule

Training a variational circuit needs gradients, and the parameter shift rule gets them exactly. Running the same circuit at a parameter shifted by plus and minus a quarter turn and subtracting the two expectation values yields the true derivative, not a finite-difference estimate. Because each evaluation is just another circuit, the gradients come straight from the same quantum hardware. The gradient of the expectation value comes from two shifted circuit runs.

Show the math
\displaystyle \frac{d\langle E\rangle}{d\theta} = \tfrac{1}{2}\Big(\big\langle E(\theta + \tfrac{\pi}{2})\big\rangle - \big\langle E(\theta - \tfrac{\pi}{2})\big\rangle\Big)

For rotation gates this identity is exact at a finite shift, not a finite-difference approximation. That is why the run’s points sit on the true derivative to machine precision.

Parameter shift rule shown as two quantum circuits run at shifted angles, subtracted to give the gradient
The parameter shift rule: run the circuit at θ plus and minus pi/2 and subtract the results.

Qiskit reports this circuit at one qubit, one classical bit and a depth of two. The gate count comes to one RY rotation and one measurement.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit import Parameter

qc = QuantumCircuit(QuantumRegister(1, "q"), ClassicalRegister(1, "m"))
qc.ry(Parameter("θ+π/2"), 0)  # the paired run uses RY(θ−π/2)
qc.measure(0, 0)
qc.draw("mpl")
See it run

Each blue point is built from two real circuit runs, one with the angle nudged up by pi over two and one nudged down. The five estimates land on the exact derivative curve with a worst case deviation of 1.1e-16, which is floating point noise rather than approximation error. This is why variational quantum circuits trust the rule: it is exact, not a finite difference.

Parameter shift rule gradients from quantum circuits landing exactly on the negative sine curveShift rule gradient estimates at five angles against the exact derivative of cos theta.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, Pauli

def f(theta):
    qc = QuantumCircuit(1)
    qc.ry(theta, 0)
    return np.real(Statevector(qc).expectation_value(Pauli("Z")))

for t in [0.4, 0.9, 1.4, 1.9, 2.4]:
    grad = (f(t + np.pi / 2) - f(t - np.pi / 2)) / 2
    print(f"theta={t:.1f}  shift rule={grad:+.6f}  exact={-np.sin(t):+.6f}")

Zero Noise Extrapolation

Zero noise extrapolation squeezes better answers out of noisy hardware without any extra qubits. Folding appends a gate and its inverse so the logic is unchanged but the effective noise is scaled up in a controlled way, and running at several noise levels lets you extrapolate back to the zero-noise limit. It is one of the cheapest and most widely used error-mitigation techniques. The same job is rerun at deliberately amplified noise, then a fit extrapolates back to zero.

Show the math
E(\lambda) \approx E_0 + c_1\lambda + c_2\lambda^{2} \quad (\text{measure at}\ \lambda = 1, 3, 5,\ \text{read off}\ E_0)

E₀ is the zero-noise value you never actually ran but can still infer from the trend. This is one of the cheapest ways to sharpen results from noisy quantum circuits without adding any qubits.

Zero noise extrapolation folding in quantum circuits, with G dagger G appended to amplify noise threefold
Circuit folding appends G dagger G, an identity that triples the noise so results can be extrapolated back to zero.

Qiskit reports this circuit at two qubits, two classical bits and a depth of four. The gate count comes to three unitary blocks and two measurements.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit import Gate

qc = QuantumCircuit(QuantumRegister(2, "q"), ClassicalRegister(2, "m"))
qc.append(Gate("unitary", 2, [], label="G"), [0, 1])
qc.barrier()
qc.append(Gate("unitary", 2, [], label="G†"), [0, 1])
qc.barrier()
qc.append(Gate("unitary", 2, [], label="G"), [0, 1])
qc.measure([0, 1], [0, 1])
qc.draw("mpl")
See it run

Every gate call in this run over rotates by 0.06 radians, and folding the gate as G, G dagger, G repeats the damage three and five times over. A quadratic fit through the three noisy points lands at 0.6221 against an exact answer of 0.6216, while the raw unmitigated value sits at 0.5735. The extrapolation cuts the error by roughly a factor of one hundred without knowing anything about the noise beyond how to amplify it.

Zero noise extrapolation in quantum circuits, folded runs fitted back to a zero noise estimate of 0.6221Expectation values at fold factors one, three and five, extrapolated back to zero noise.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, Pauli

theta, eps = 0.9, 0.06          # each gate call over rotates by eps

def measure(fold):
    qc = QuantumCircuit(1)
    qc.ry(theta + eps, 0)
    for _ in range((fold - 1) // 2):
        qc.ry(-theta + eps, 0)
        qc.ry(theta + eps, 0)
    return np.real(Statevector(qc).expectation_value(Pauli("Z")))

folds = [1, 3, 5]
vals = [measure(k) for k in folds]
zne = np.polyval(np.polyfit(folds, vals, 2), 0)
print("folded values:", [round(v, 4) for v in vals])
print(f"ZNE {zne:.4f}  raw {vals[0]:.4f}  exact {np.cos(theta):.4f}")

Dynamical Decoupling

Idle qubits are not truly idle, because they slowly dephase while they wait. Dynamical decoupling fills that idle time with an evenly spaced train of X pulses that repeatedly flips the qubit and cancels slow environmental noise, much like a spin echo. Adding these pulses to gaps in a schedule is a nearly free way to extend coherence. A pair of X pulses brackets the idle stretch so the drift picked up in the first half cancels in the second.

Show the math
X\,e^{-i\delta Z}\,X = e^{+i\delta Z}
\Rightarrow\ X\,e^{-i\delta Z}\,X\,e^{-i\delta Z} = I

The echo flips the sign of the accumulated phase so the second half of the drift unwinds the first. Idle qubits in real quantum circuits use this trick to hold their state while other wires stay busy.

Dynamical decoupling in quantum circuits: a bare idle wire above a wire protected by an echo train of X pulses
A bare idle qubit slowly dephases while an evenly spaced train of X pulses refocuses the noise below it.

Qiskit reports this circuit at two qubits, two classical bits and a depth of five. The gate count comes to four X gates and two measurements.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

idle = QuantumRegister(1, "idle")
echo = QuantumRegister(1, "echo")
m = ClassicalRegister(2, "m")
qc = QuantumCircuit(idle, echo, m)
qc.barrier()
for _ in range(4):
    qc.x(echo[0])
    qc.barrier()
qc.measure(idle[0], m[0])
qc.measure(echo[0], m[1])
qc.draw("mpl")
See it run

Eight idle slices each drift the phase by 0.2 radians, and left alone they drag the fidelity with the intended state down to 0.485. Inserting an X pulse halfway and another at the end makes the second half of the drift undo the first, and the run ends back at fidelity 1.000. The noise is not removed, it is refocused, which is why the echoed curve dips before it recovers.

Dynamical decoupling in quantum circuits, echoes refocusing dephasing from fidelity 0.485 to 1.000Fidelity across an idle period with and without X echo pulses, computed slice by slice.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, state_fidelity

plus = Statevector.from_label("+")

def idle(echo_after):
    sv = plus
    for n in range(1, 9):
        step = QuantumCircuit(1)
        step.rz(0.2, 0)              # slow dephasing drift
        if n in echo_after:
            step.x(0)                # decoupling pulse
        sv = sv.evolve(step)
    return state_fidelity(sv, plus)

print(f"bare idle fidelity  {idle(set()):.3f}")
print(f"with two X echoes   {idle({4, 8}):.3f}")

Error correction circuits

Error correction is what will carry quantum computing from fragile prototypes to dependable machines. These circuits encode information redundantly and measure parities so that faults can be caught and fixed without disturbing the protected state.

The Repetition Code

The repetition code is the gentlest introduction to the quantum circuits behind error correction. Two CNOTs fan a single logical qubit out across three physical qubits, so a later majority vote can outvote any single bit flip. It only protects against one type of error, but it captures the core idea of spreading information so no single fault is fatal. Two CNOTs spread a single logical bit across three physical qubits so a later vote can catch a flip.

Show the math
\alpha|0\rangle + \beta|1\rangle \to \alpha|000\rangle + \beta|111\rangle

This is not three copies of the state, since no-cloning forbids |ψ⟩⊗|ψ⟩⊗|ψ⟩ outright. Only the basis labels are spread across the wires, and that restraint is exactly why the encoding is legal.

Repetition code encoding in quantum circuits: two CNOTs fan one qubit state out across three wires
Two CNOTs fan a single qubit out across three physical wires to form one bit-flip protected logical qubit.

Qiskit reports this circuit at three qubits and a depth of two. The gate count comes to two controlled-NOTs.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister

psi = QuantumRegister(1, "|ψ⟩")
code = QuantumRegister(2, "|0⟩")
qc = QuantumCircuit(psi, code)
qc.cx(psi[0], code[0])
qc.cx(psi[0], code[1])
qc.draw("mpl")
See it run

The encoded state, RY at angle 0.9 applied to zero, survives a single bit flip untouched, with the decoder returning fidelity 1.000. Flip two of the three qubits and the majority vote sides with the errors, dropping fidelity to 0.614. That gap is code distance in action: a distance three code built from these quantum circuits corrects one error and no more.

Repetition code in quantum circuits recovering a state perfectly after one bit flip but failing after twoMajority decoding after one injected bit flip versus two, on the three qubit repetition code.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, partial_trace, state_fidelity

one = QuantumCircuit(1)
one.ry(0.9, 0)
ideal = Statevector(one)

def recovered(flips):
    qc = QuantumCircuit(3)
    qc.ry(0.9, 0)
    qc.cx(0, 1); qc.cx(0, 2)                    # encode
    for q in flips:
        qc.x(q)                                 # injected bit flips
    qc.cx(0, 1); qc.cx(0, 2); qc.ccx(1, 2, 0)   # majority decode
    return state_fidelity(partial_trace(Statevector(qc), [1, 2]), ideal)

print(f"one flip  -> fidelity {recovered([1]):.3f}")
print(f"two flips -> fidelity {recovered([1, 2]):.3f}")

Syndrome Extraction

Syndrome extraction is the measurement that makes error correction possible without collapsing the data. A fresh ancilla collects the joint parity of several data qubits through a fan of CNOTs, and measuring only the ancilla reveals where an error struck while the encoded state stays intact. Every stabiliser code, including the surface code, repeats this check thousands of times per second. An ancilla reaches across two data qubits and reports whether they still agree.

Show the math
\text{ancilla measures}\ ZZ\ \text{parity:}\ \ +1 \Rightarrow \text{the pair agrees},\ \ -1 \Rightarrow \text{one flipped}

The pattern of parities localizes the error without ever measuring a data qubit directly. Keeping the payload untouched is what lets quantum circuits correct faults without collapsing the information they protect.

Syndrome extraction in quantum circuits: four CNOTs write data-qubit parity onto an ancilla that is then measured
A Z-type parity check: four CNOTs accumulate the parity of the data qubits on a fresh ancilla, which is then measured.

Qiskit reports this circuit at five qubits, one classical bit and a depth of five. The gate count comes to four controlled-NOTs and one measurement.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

d = QuantumRegister(4, "d")
a = QuantumRegister(1, "a")
syn = ClassicalRegister(1, "syn")
qc = QuantumCircuit(d, a, syn)
for i in range(4):
    qc.cx(d[i], a[0])
qc.measure(a[0], syn[0])
qc.draw("mpl")
See it run

Each row is a separate run with an X error injected on one data qubit, or on none. The three parity checks fire in a different pattern every time, so reading the three bits tells the decoder exactly which qubit to fix. No run ever measures the data itself; only the ancillas are read out.

Syndrome extraction in quantum circuits, three parity checks localizing a bit flip on four data qubitsThe measured syndrome for each possible bit flip location, run one case at a time.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

def syndrome(err):
    qc = QuantumCircuit(7)              # d0..d3 data, q4..q6 ancillas
    if err is not None:
        qc.x(err)
    qc.cx(0, 4); qc.cx(1, 4)            # s0 checks Z0Z1
    qc.cx(1, 5); qc.cx(2, 5)            # s1 checks Z1Z2
    qc.cx(2, 6); qc.cx(3, 6)            # s2 checks Z2Z3
    probs = Statevector(qc).probabilities_dict(qargs=[4, 5, 6])
    return max(probs, key=probs.get)[::-1]   # bits s0 s1 s2

print("no error -> syndrome", syndrome(None))
for d in range(4):
    print(f"X on d{d}  -> syndrome", syndrome(d))

The X Stabilizer Check

An X-type stabiliser check catches phase-flip errors, the partner of the bit-flip checks. Wrapping the ancilla in Hadamards before and after its CNOTs moves the parity measurement into the X basis, so it detects the errors a Z-check would miss. Real codes interleave X and Z stabilisers to catch both error types at once. A four-way parity check reads the combined X value of a plaquette in one shot.

Show the math
\text{the check measures}\ X\otimes X\otimes X\otimes X;\quad XZ = -ZX \Rightarrow \text{Z errors flip it}

Anticommutation is the whole detection mechanism, since a Z error fails to commute with the check and flips its outcome. The same check is blind to X errors, which commute straight through, so surface-code quantum circuits pair it with a matching Z check.

X stabilizer measurement in quantum circuits, with Hadamards around an ancilla that controls four CNOTs
An X-type check: Hadamards sandwich the ancilla, which now acts as the control of four CNOTs onto the data qubits.

Qiskit reports this circuit at five qubits, one classical bit and a depth of seven. The gate count comes to two Hadamards, four controlled-NOTs and one measurement.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

d = QuantumRegister(4, "d")
a = QuantumRegister(1, "a")
syn = ClassicalRegister(1, "syn")
qc = QuantumCircuit(d, a, syn)
qc.h(a[0])
for i in range(4):
    qc.cx(a[0], d[i])
qc.h(a[0])
qc.measure(a[0], syn[0])
qc.draw("mpl")
See it run

A Z error on any data qubit flips the ancilla to one, so the phase flip is caught on the first pass. The same check reads zero when an X error is injected, because a bit flip commutes with the X parity being measured. That blind spot is the whole argument for running both check types side by side, exactly as the surface code does.

X stabilizer check in quantum circuits catching phase flips while a bit flip passes undetectedThe X check ancilla outcome for phase flips and a bit flip, run case by case.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

def x_check(err=None):
    qc = QuantumCircuit(5)              # d0..d3 data, q4 ancilla
    for q in range(4):
        qc.h(q)                         # data in the plus state
    if err:
        getattr(qc, err)(2)             # inject error on d2
    qc.h(4)
    for q in range(4):
        qc.cx(4, q)
    qc.h(4)
    return int(np.argmax(Statevector(qc).probabilities([4])))

print("no error -> ancilla", x_check())
print("Z on d2  -> ancilla", x_check("z"))
print("X on d2  -> ancilla", x_check("x"))

Magic State Injection

Fault-tolerant machines apply Clifford gates cheaply but need a special trick for the T gate that completes a universal set. Magic state injection consumes a carefully prepared T state with a CNOT, a measurement, and a classically conditioned S correction, teleporting a T gate onto the data. Distilling clean magic states is expected to dominate the qubit budget of early fault-tolerant computers. A pre-cooked |T⟩ resource is teleported into the data wire to apply a gate the code cannot do directly.

Show the math
|T\rangle = T|+\rangle = \tfrac{1}{\sqrt{2}}\big(|0\rangle + e^{\,i\pi/4}|1\rangle\big)
\mathrm{CNOT} + \text{measure} \Rightarrow T|\psi\rangle \quad (\text{S correction on the 1 branch})
Magic state injection in quantum circuits: a prepared T state, a CNOT, a measurement and a conditional S fix-up
Gate teleportation: a CNOT and measurement consume a prepared magic state, with an S correction applied when the meter reads 1.

Qiskit reports this circuit at two qubits, one classical bit and a depth of three. The gate count comes to one controlled-NOT, one classically conditioned block and one measurement.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

psi = QuantumRegister(1, "|ψ⟩")
t = QuantumRegister(1, "|T⟩")
m = ClassicalRegister(1, "m")
qc = QuantumCircuit(psi, t, m)
qc.cx(psi[0], t[0])
qc.measure(t[0], m[0])
with qc.if_test((m, 1)):
    qc.s(psi[0])
qc.draw("mpl")
See it run

When the meter reads zero the data qubit already holds the T gate output, fidelity 1.000 with no correction at all. When it reads one the raw state only overlaps the target at 0.500, and a single S gate lifts it to exactly 1.000. Each branch fires half the time, so the injection succeeds on every shot once the fix up is wired in.

Magic state injection in quantum circuits, both measurement branches reaching the ideal T gate outputOutput fidelity on both meter outcomes, before and after the conditional S fix up.
Run this example yourself
import numpy as np
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector, state_fidelity

qc = QuantumCircuit(2)
qc.h(0)                     # data: the plus state
qc.h(1); qc.t(1)            # magic T state on q1
qc.cx(0, 1)
amps = Statevector(qc).data

tq = QuantumCircuit(1); tq.h(0); tq.t(0)
ideal = Statevector(tq)     # the target: T applied to the data

for m in (0, 1):            # both meter outcomes, p = 0.5 each
    branch = Statevector(amps[2 * m: 2 * m + 2] / np.sqrt(0.5))
    if m == 1:
        fix = QuantumCircuit(1); fix.s(0)
        branch = branch.evolve(fix)     # the S fix up
    print(f"meter {m} -> fidelity {state_fidelity(branch, ideal):.3f}")

Mirror Circuit Benchmarking

Mirror circuits are a practical way to measure how good a processor really is. A random circuit runs forward and then its exact inverse runs it backward, so a perfect machine returns every qubit to zero, and any one in the readout counts a hardware error. Because the ideal answer is known in advance, mirror benchmarking scales to large qubit counts where full simulation is impossible. A circuit is run forward and then exactly reversed, so a perfect device must return every qubit to zero.

Show the math
P(\text{all zeros}) = \big|\langle 0\dots0|\,C^{\dagger} E\,C\,|0\dots0\rangle\big|^{2}
E = I \Rightarrow P = 1

Any shortfall below one is a direct fingerprint of the error E the hardware slipped in between the two halves. This makes mirror runs a fast, scalable way to benchmark quantum circuits without simulating them.

Mirror circuit benchmarking of quantum circuits: a random circuit C followed by its inverse, measured to all zeros
A benchmarking mirror: circuit C runs forward, its inverse runs it backward, and a perfect machine measures all zeros.

Qiskit reports this circuit at three qubits, three classical bits and a depth of three. The gate count comes to two unitary blocks and three measurements.

Build it in Qiskit
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
from qiskit.circuit import Gate

qc = QuantumCircuit(QuantumRegister(3, "q"), ClassicalRegister(3, "m"))
qc.append(Gate("unitary", 3, [], label="C"), [0, 1, 2])
qc.barrier()
qc.append(Gate("unitary", 3, [], label="C†"), [0, 1, 2])
qc.measure([0, 1, 2], [0, 1, 2])
qc.draw("mpl")
See it run

Running C forward and then its inverse returns every one of 4096 shots to all zeros, exactly as the algebra promises. Slip one 0.6 radian rotation between the halves and the return probability falls to 0.913, with 3743 of 4096 sampled shots surviving. Hardware teams use exactly this gap as a scorecard, since any deviation from a perfect echo is machine error, not algorithm.

Mirror circuit benchmark from quantum circuits, return probability falling from 1.000 to 0.913 with one errorAll zeros return probability for a clean mirror versus one with a hidden error rotation.
Run this example yourself
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector

C = QuantumCircuit(3)
C.h(0); C.cx(0, 1); C.cx(1, 2); C.ry(0.7, 2); C.t(0)

def survival(with_error):
    qc = C.copy()
    if with_error:
        qc.ry(0.6, 1)                    # one stray rotation
    qc.compose(C.inverse(), inplace=True)
    return Statevector(qc).probabilities()[0]

print(f"clean mirror     P(000) = {survival(False):.3f}")
print(f"one error inside P(000) = {survival(True):.3f}")

Frequently asked questions about quantum circuits

What is a quantum circuit?

A quantum circuit is a sequence of quantum gates applied to a set of qubits, usually ending in measurement. It is the standard model for describing a quantum computation, in the same way a flowchart describes a classical program.

How do you read a quantum circuit diagram?

Each horizontal line is a qubit and time flows from left to right, with gates drawn as boxes and symbols in the order they run. Control dots, target circles, meter symbols, and double classical wires make up most of the notation you will meet.

Which quantum circuits should you learn first?

The Bell state, a layer of Hadamards for uniform superposition, and the controlled-NOT cover most of what beginners need. From those three quantum circuits you can already understand entanglement, superposition, and conditional logic.

Are these quantum circuits the same in Qiskit and Cirq?

Yes, the patterns are framework-independent, so the same Bell state or Fourier transform looks alike whether you write it in Qiskit, Cirq, or PennyLane. Only the surrounding code differs, while the gate sequence and the diagram stay the same.

What is the difference between a static and a dynamic circuit?

A static circuit fixes every gate in advance and measures only at the end. A dynamic circuit measures partway through and feeds those results forward to choose later gates, which enables reset-and-reuse and real-time error correction.

Why do so many circuits start with a Hadamard?

A Hadamard creates an equal superposition, giving an algorithm access to many inputs at once. Loading that superposition is the natural first step before interference is arranged to concentrate probability on the right answer.

What makes a quantum circuit hard to run on current hardware?

Depth and two-qubit gate count are the main enemies, because every extra gate adds noise on near-term devices. Limited qubit connectivity also forces extra SWAP operations that lengthen the circuit further.

How does error correction change these circuits?

Error correction wraps the logical computation in repeated syndrome-extraction and stabiliser circuits that detect faults without reading the data. This adds many physical qubits and measurement rounds, which is why fault tolerance is so resource-intensive.

Where can you practise building quantum circuits?

Open-source frameworks such as Qiskit and Cirq let you build and simulate every pattern in this guide on a laptop. Many also connect to real cloud quantum processors once you are ready to run on hardware.

Stay current. See today’s quantum computing news on Quantum Zeitgeist for the latest breakthroughs in qubits, hardware, algorithms, and industry deals.
Dr. Donovan, Quantum Technology Futurist

Latest Posts by Dr. Donovan: