Skip to main content
Grover’s algorithm finds a marked item in an unstructured database of N entries in O(√N) queries, compared to O(N) for a classical linear scan. In b01t, the algorithm is split into two reusable @coherent components — a phase oracle that marks your target state with a −1 phase, and a diffusion operator that amplifies its amplitude. Both are structurally safe: ancilla qubits are allocated and fully uncomputed through the compute/phase/uncompute discipline.

Imports

  • make_phase_oracle — factory function that returns a @coherent oracle for any target bit pattern
  • phase_oracle — pre-built oracle for the 2-qubit |11⟩ state (equivalent to make_phase_oracle([1, 1]))
  • diffusion_operator@coherent Grover diffusion operator (works on any register width)

Phase oracle

The phase oracle flips the sign of the marked basis state. You describe the target as a sequence of bits, one per qubit — 1 for qubits that must be |1⟩ and 0 for qubits that must be |0⟩.
Arguments:
  • marked_bits — a sequence of 0s and 1s, one element per qubit. Must have at least one element. All entries must be 0 or 1.
Returns: a @coherent function oracle(sys: QReg) that applies the phase flip to |marked_bits⟩. Implementation details:
  • For a 1-qubit register: applies Z directly (wrapping with X/X if marked_bits[0] == 0).
  • For 2+ qubits: copies system bits into a 1-qubit ancilla via MCX (inside a compute block), applies Z via phase kickback, then uncomputes. The ancilla is always returned to |0⟩.

Diffusion operator

The diffusion operator implements the inversion-about-average step: 2|s⟩⟨s| − I where |s⟩ is the uniform superposition. It works on any register width.
Signature: @coherent function, takes a single QReg of any width. Implementation:
  • Applies H then X on every qubit.
  • Applies a multi-controlled-Z (using CZ for 2 qubits, or MCX+CZ+uncompute for 3+, all ancilla-clean).
  • Applies X then H on every qubit.

Complete example: Grover search on 2 qubits

This example mirrors the demos/grover_search/search.py demo. It searches for |11⟩ in a 2-qubit space with 2 Grover iterations, which is the optimal number for N=4.
1

Write the Grover step

Combine the oracle and diffusion into a single step using @parametric (required for use inside @adaptive).
2

Write the full search circuit

Use @adaptive to create a circuit that prepares a uniform superposition, runs 2 Grover iterations, and measures.
3

Build and run on Qiskit

Compile to a Qiskit QuantumCircuit and run.

Using zoo components directly

If you prefer to use the zoo’s make_phase_oracle and diffusion_operator directly rather than inlining gate sequences, you can call them inside a @coherent host:
The @coherent decorator cannot be used directly inside @adaptive. Wrap your @coherent Grover step in a @parametric function, or inline the gate sequences as shown in the full example above.

Scaling to more qubits

make_phase_oracle and diffusion_operator both scale to any number of qubits. For n qubits you typically want ⌊π/4 · √(2^n)⌋ iterations:
For multi-qubit oracles, b01t allocates exactly one ancilla qubit via compute/phase/uncompute — the circuit width grows by only 1 qubit regardless of n.