grover#
Functionality#
Grover’s search [15] [16] algorithm aims to find a solution for unstructured search.
grover_operator.py#
Callee: GroverOperator
The Grover operator is the core transformation that amplifies the amplitudes of “good” states (solutions). This operator \(\mathcal{Q}\) consists of the phase oracle \(\mathcal{S}_f\), zero phase-shift or zero reflection \(\mathcal{S}_0\), and an input state preparation \(\mathcal{A}\):
In the standard Grover search we have
and then
The operation \(D = H^{\otimes n} \mathcal{S}_0 H^{\otimes n}\) is also referred to as diffusion operator. In this formulation we can see that Grover’s operator consists of two steps: first, the phase oracle multiplies the good states by -1 (with \(\mathcal{S}_f\)) and then the whole state is reflected around the mean (with \(D\)).
The action of the phase oracle \(\mathcal{S}_f\) is defined as
where \(f(x) = 1\) if \(x\) is a good state and 0 otherwise, which is determined by the input oracle. To highlight the fact that this oracle flips the phase of the good states and does not flip the state of a result qubit, we call \(\mathcal{S}_f\) a phase oracle.
The zero reflection \(\mathcal{S}_0\) flips the sign of the \(\ket{0}^{\otimes n}\) state, which is usually defined as
where \(\mathbb{I}_n\) is the identity on \(n\) qubits. By default, this class implements the negative version \(2\ket{0}^{\otimes n}\bra{0}^{\otimes n} -\mathbb{I}_n\), since this can simply be implemented with a multi-controlled Z sandwiched by X gates on the target qubit and the introduced global phase does not matter for Grover’s algorithm.
Test expectations:
Program specification can be constructed according to each subroutine of Grover operator, such that the unitary operation can be verified through testing.
grover_search.py#
Callee: GroverSearch
This program implements the complete Grover’s search algorithm through multiple applications of the above grover operator.
The quantum circuit is constructed as follows:
Grover search circuit (Source: https://en.wikipedia.org/wiki/Grover%27s_algorithm)
Initialization: Uniform Superposition Apply Hadamard gates to all \(n\) qubits:
\[ |0\rangle^{\otimes n} \xrightarrow{H^{\otimes n}} \ket{s}_n = \frac{1}{\sqrt{N}}\sum_{x=0}^{N-1}\ket{x}_{n}, \]where \(N = 2^n\) and the state is an equal superposition of all computational basis states.
Phase Oracle \(S_f\): The phase oracle flips the sign of the target states \(x \in T\), where \(T\) is the set of solutions:
\[\begin{split} S_f\ket{x}_n = \begin{cases} -\ket{x}_n, & x \in T \\ \ket{x}_n, & x \notin T \end{cases} \end{split}\]Applied to the uniform superposition:
\[ \ket{s}_n \xrightarrow{S_f} S_f\ket{s}_n = \frac{1}{\sqrt{N}}\Big(\sum_{x \notin T} \ket{x}_n - \sum_{x \in T} \ket{x}_n\Big) \]By this means, good states have their amplitudes negated and bad states remain unchanged.
Diffuser (Inversion About the Mean): The diffuser is defined as:
\[ D = 2\ket{s}_n\langle s|_n - \mathbb{I}_n \]Grover Iteration: The Grover operator is:
\[ \mathcal{Q} = D \cdot S_f \]After \(t\) iterations, the state evolves to:
\[ |\psi_t\rangle = \mathcal{Q}^t \ket{s}_n = \cos((2t+1)\theta) \ket{\beta}_n + \sin((2t+1)\theta) \ket{\alpha}_n \]Where:
\(\ket{\alpha}_n = \frac{1}{\sqrt{|T|}} \sum_{x \in T} \ket{x}_n\) (good subspace)
\(\ket{\beta}_n = \frac{1}{\sqrt{N-|T|}} \sum_{x \notin T} \ket{x}_n\) (bad subspace)
\(\theta = \arcsin(\sqrt{|T|/N})\)
Each iteration rotates the state vector in the 2-dimensional subspace spanned by \(\ket{\alpha}_n\) and \(\ket{\beta}_n\).
Choosing \(t \approx \frac{\pi}{4} \sqrt{N/|T|}\) maximizes the probability of measuring a target state.
Measurement (not included in our implementation) After the Grover iterations, measure all qubits:
\[ |\psi_t\rangle \approx \ket{\alpha}_n = \frac{1}{\sqrt{|T|}}\sum_{x \in T} \ket{x}_n \]Measurement collapses the state to one of the target states \(x \in T\) with high probability.
Test expectations:
When searching only one item among \(N\) items, the probability of measuring a target state will be maximized, close to 1 by choosing \(t \approx \frac{\pi}{4} \sqrt{N/|T|}\) iterations.
When there are multiple target states, we can check the exact state \(|\psi_t\rangle \) after \(t\) iterations.
Notes:
For
steps, we acceptsteps = Noneonly whenoracleis of typeStatevector, since in that case we can determine the number of target states directly from the statevector. Iforacleis aQuantumCircuit, the user must providestepsexplicitly.As we can see the formula, Grover’s algorithm can ensure the target solution with high probability. This means that the solution is not deterministic and exact.
Code Example#
The following code gives an example to prepare the argument oracle for testing the grover module:
Example 1: Quantum circuit from [17]:
>>> from qiskit.circuit import QuantumCircuit
>>> from qiskit.circuit.library import GroverOperator
>>> oracle = QuantumCircuit(2)
>>> oracle.z(0) # good state = first qubit is |1>. Remember this is a phase oracle.
>>> grover_op = GroverOperator(oracle, insert_barriers=True)
>>> grover_op.decompose().draw()
┌───┐ ░ ┌───┐ ░ ┌───┐ ┌───┐ ░ ┌───┐
state_0: ┤ Z ├─░─┤ H ├─░─┤ X ├───────■──┤ X ├──────░─┤ H ├
└───┘ ░ ├───┤ ░ ├───┤┌───┐┌─┴─┐├───┤┌───┐ ░ ├───┤
state_1: ──────░─┤ H ├─░─┤ X ├┤ H ├┤ X ├┤ H ├┤ X ├─░─┤ H ├
░ └───┘ ░ └───┘└───┘└───┘└───┘└───┘ ░ └───┘
Example 2: Statevector
>>> from qiskit.quantum_info import Statevector
>>> from qiskit.circuit.library import GroverOperator
>>> oracle_sv = Statevector([0, 0, 0, 1, 0, 0, 0, 0]) # good state = |3>
>>> grover_op = GroverOperator(oracle_sv, insert_barriers=True)
>>> grover_op.decompose().draw()
global phase: π
┌─────────────────────────────┐ ░ ┌───┐ ░ ┌───┐ ┌───┐ ░ ┌───┐
state_0: ┤0 ├─░─┤ H ├─░─┤ X ├───────■──┤ X ├──────░─┤ H ├
│ │ ░ ├───┤ ░ ├───┤ │ ├───┤ ░ ├───┤
state_1: ┤1 Diagonal(1,1,1,-1,1,1,1,1) ├─░─┤ H ├─░─┤ X ├───────■──┤ X ├──────░─┤ H ├
│ │ ░ ├───┤ ░ ├───┤┌───┐┌─┴─┐├───┤┌───┐ ░ ├───┤
state_2: ┤2 ├─░─┤ H ├─░─┤ X ├┤ H ├┤ X ├┤ H ├┤ X ├─░─┤ H ├
└─────────────────────────────┘ ░ └───┘ ░ └───┘└───┘└───┘└───┘└───┘ ░ └───┘
API#
qolumbina.programs.grover.grover_operator#
The Grover operator.
- class GroverOperator(oracle, state_preparation=None, zero_reflection=None, reflection_qubits=None, insert_barriers=False, name='Q')[source]#
Bases:
QuantumCircuitGrover operator circuit.
- Parameters:
oracle (QuantumCircuit | Statevector) – The phase oracle implementing a reflection about the bad state. Note that this is not a bitflip oracle, see the docstring for more information.
state_preparation (QuantumCircuit | None) – The operator preparing the good and bad state. For Grover’s algorithm, this is a n-qubit Hadamard gate and for amplitude amplification or estimation the operator \(\mathcal{A}\). If
None, a layer of Hadamard gates is used onreflection_qubits.zero_reflection (QuantumCircuit | DensityMatrix | Operator | None) – The reflection about the zero state, \(\mathcal{S}_0\). If
None, a default implementation is used.reflection_qubits (list[int] | None) – Qubits on which the zero reflection acts on. If None, all qubits of the oracle are used.
insert_barriers (bool) – Whether barriers should be inserted between the reflections and A.
name (str) – The name of the circuit.
qolumbina.programs.grover.grover_search#
- class GroverSearch(oracle, steps=None, barrier=False, name=None)[source]#
Bases:
QuantumCircuitGrover’s search algorithm circuit.
- Parameters:
oracle (QuantumCircuit | Statevector) – The phase oracle implementing a reflection about the bad state(s). Note that the number of qubits \(n\) is inferred from the oracle.
steps (int | None) – Number of Grover iterations to perform. If
None, it is calculated as \(\left\lfloor \frac{\pi}{4} \sqrt{N/|T|} \right\rfloor\), where \(N\) is the total number of states and \(|T|\) is the number of target states.barrier (bool) – Whether to insert barriers between steps for clarity.
name (str | None) – Optional name for the circuit.
- Raises:
TypeError – If
oracleis not aQuantumCircuitorStatevector.ValueError – If
oracleis aStatevectorand its entries are not close to either 0 or 1 (indicating an invalid phase oracle).ValueError – If
stepsisNoneand cannot be calculated from the oracle (e.g., if oracle is a QuantumCircuit and steps is not provided).