QUANTUM ALGORITHMS

Grover's Algorithm Explained with Python Code

A step-by-step walkthrough of Grover's quantum search algorithm with a complete Python implementation using Qiskit.

T

TQ Editors

Jan 28, 2026 · 11 min read

Grover's Algorithm Explained with Python Code

The Search Problem

Imagine you have an unsorted database of N items and you need to find a specific one. Classically, the best you can do is check items one by one — on average, you'll need N/2 checks, and in the worst case, N checks. Grover's algorithm, published by Lov Grover in 1996, solves this problem in roughly √N steps using quantum computing. For a database of one million items, that's 1,000 quantum steps instead of 500,000 classical checks.

This quadratic speedup might seem modest compared to the exponential speedups promised by Shor's algorithm for factoring. But Grover's algorithm is far more general. It applies to any problem that can be framed as searching for an input that satisfies a given condition — which includes optimization problems, constraint satisfaction, and NP-complete problems. A quadratic speedup on an NP-hard problem is nothing to dismiss.

How It Works

Grover's algorithm operates through two key operations applied repeatedly: the oracle and the diffusion operator.

The oracle is a black-box function that marks the target item by flipping its amplitude's sign. If you're searching for item |w⟩ in a superposition of all items, the oracle transforms the state such that the amplitude of |w⟩ becomes negative while all other amplitudes remain unchanged.

The diffusion operator (also called the Grover diffuser) performs an "inversion about the mean." It takes each amplitude, computes the average of all amplitudes, and reflects each amplitude about that average. The effect is that items with below-average amplitudes (the unmarked items, which just had their amplitudes slightly reduced because the mean decreased) get pushed lower, while the marked item (with its negative amplitude, well below the mean) gets pushed significantly higher.

After approximately π/4 × √N iterations of oracle + diffusion, the marked item's amplitude approaches 1, and measuring the system yields the target with high probability.

Implementation in Qiskit

Let's implement Grover's algorithm to search for the state |11⟩ among four possible states (|00⟩, |01⟩, |10⟩, |11⟩):

from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator

def grovers_algorithm():
    qc = QuantumCircuit(2, 2)

    # Step 1: Initialize superposition
    qc.h([0, 1])

    # Step 2: Oracle — mark |11⟩ by flipping its sign
    # CZ gate flips the phase of |11⟩
    qc.cz(0, 1)

    # Step 3: Diffusion operator
    qc.h([0, 1])          # Apply H gates
    qc.z([0, 1])          # Apply Z gates
    qc.cz(0, 1)           # Apply CZ gate
    qc.h([0, 1])          # Apply H gates

    # For N=4, only 1 iteration is needed

    # Measure
    qc.measure([0, 1], [0, 1])

    return qc

# Build and run
qc = grovers_algorithm()
print(qc.draw())

simulator = AerSimulator()
result = simulator.run(qc, shots=1024).result()
counts = result.get_counts()
print(f"Results: {counts}")
# Expected: {'11': 1024} — the target found with certainty

For N = 4, a single iteration suffices — and the algorithm finds |11⟩ with probability 1, not just high probability. This is a special case; for larger N, you need approximately √N iterations, and the success probability oscillates, requiring careful calibration of the iteration count.

Scaling Up

For practical problems, the oracle is the challenging part. In the textbook version, we assumed a black-box oracle, but in practice, you need to construct a quantum circuit that recognizes the target. For structured problems like SAT solving, the oracle implements the constraint-checking function reversibly using ancilla qubits.

Here's a more general implementation for 3 qubits, searching for a specific target:

def grovers_3qubit(target: str):
    n = 3
    qc = QuantumCircuit(n, n)

    # Initialize superposition
    qc.h(range(n))

    # Number of iterations: ~pi/4 * sqrt(N)
    import math
    iterations = round(math.pi / 4 * math.sqrt(2**n))

    for _ in range(iterations):
        # Oracle: flip phase of target state
        for i, bit in enumerate(reversed(target)):
            if bit == '0':
                qc.x(i)
        qc.h(n - 1)
        qc.mcx(list(range(n - 1)), n - 1)  # Multi-controlled X
        qc.h(n - 1)
        for i, bit in enumerate(reversed(target)):
            if bit == '0':
                qc.x(i)

        # Diffusion operator
        qc.h(range(n))
        qc.x(range(n))
        qc.h(n - 1)
        qc.mcx(list(range(n - 1)), n - 1)
        qc.h(n - 1)
        qc.x(range(n))
        qc.h(range(n))

    qc.measure(range(n), range(n))
    return qc

Practical Significance

Grover's algorithm is more than an academic exercise. It provides a provably optimal quantum speedup for unstructured search — no quantum algorithm can do better than O(√N) for this problem. This lower bound, proved by Bennett, Bernstein, Brassard, and Vazirani, tells us something fundamental about the power and limitations of quantum computing.

The algorithm also serves as a subroutine in more complex quantum algorithms. Amplitude amplification, a generalization of Grover's technique, is used in quantum counting, quantum minimum finding, and as a building block in quantum walks and quantum optimization algorithms. Understanding Grover's is essential groundwork for any serious study of quantum algorithms.

T

Written by

TQ Editors

The editorial team at Towards Quantum.