Grover's Algorithm
Overview
This notebook provides an introduction to Grover's algorithm, a landmark quantum algorithm that has the potential to enable efficient search of unsorted databases. There are several expositions of Grover's algorithm online including this video by 3Blue1Brown, section 5.8 of Girvin's class notes, and section 7.6 of Thomas Wong's book. By learning Grover's algorithm, you will recognize patterns and structure that are also used in other quantum algorithms, such as:
Deutsch-Jozsa algorithm (distinguishing constant from balanced functions)
Simon’s algorithm (finding hidden periodicity)
Shor’s algorithm (factoring via quantum Fourier transform).
By the end of this notebook you will be able to
understand the theoretical foundations of Grover's algorithm
apply the algorithm to solve specific search problems
design and implement your own simulations of Grover's algorithm using CUDA-Q
Before we get started, we will need to import a few libraries:
Problem
We consider the problem of locating one or more marked items in an unstructured database, where no prior information about the structure of the data is available. We can make this explicit by considering a database made up of binary strings of length . Let denote the set of binary strings of length and be a Boolean function that encodes the marked elements, i.e. if and only if is a marked string. Our goal is to find all strings such that .
Classically, if we have no prior knowledge about (i.e., it is given as a black-box oracle), the best strategy requires evaluations, where is the total number of binary strings. However, there exists a quantum algorithm due to L. Grover that finds a solution using only oracle queries (Grover, 1996).
We will use computational basis states on qubits to represent the elements in the database . Our goal is to create a quantum kernel that separates the marked states from the non-marked states. That is, sampling from the kernel yields a marked state with high probability and a non-marked state with low probability.
An alternative approach to this problem involves discrete time quantum walks. For an introduction to discrete time quantum walks refer to the CUDA-Q Academic notebook and for details of using discrete time quantum walks for the search problem, consult Thomas Wong's exposition.
Step-by-Step Example: Understanding Grover's Algorithm
In this notebook, we use a concrete example to illustrate the key steps and concepts behind Grover’s algorithm. Each section begins with an explanation of the theoretical foundations of a specific stage of the algorithm, followed by a step-by-step walkthrough applying these ideas to our example.
Let and mark the states 1001
and 1111
. The code block below defines the Boolean function, which we'll call marking_function
that encodes the marked elements.
Structure of Grover's Algorithm
Grover's Algorithm can be broken down into the following steps:
Preparation: Initialize qubits in an equal superposition state.
Oracle Application: Apply the oracle operator to flip the phase of the marked states (i.e., multiply them by ).
Amplitude Amplification: Use the diffusion operator to amplify the amplitudes of the marked states.
Iteration: Repeat Steps 2 and 3 a specified number of times, which depends on the number of marked elements and .
Measurement: Measure the qubits. With high probability, the result will be one of the marked states.
These steps are implicit in the circuit diagram below, which we'll describe in more detail in the following sections.
Between the sections describing Step 1 and Step 2, we will introduce two quantum states (the good and the bad state) and their geometric interpretation that will help motivate Steps 3 and 4.
Step 1: Preparation
The first step of Grover's algorithm requires initializing qubits in a state of equal superposition:
where each binary string is identified with the integer it represents (e.g., ).
The kernel in the code block below places the qubits in an equal superposition state.
To test that the equal_superposition
function acts as required, let's create a quantum kernel and sample it. We will also use the get_state
command to get the probability amplitudes of the state, which should all be . The sampling block below uses shots_count
parameter equal to , so we expect each of the basis states to appear approximately times in the histogram. We'll also define helper functions to visualize the sampling results and to print out the statevector.
The histogram illustrates the distribution from sampling the state , showing that each bitstring has roughly equal probability of being measured. In this notebook, our objective is to implement Grover's Algorithm by developing a kernel that transforms the equal superposition state into one where the probability amplitudes of the marked states are amplified, making them more likely to be sampled than the other states.
Good and Bad States: Explanation
We can simplify our analysis of Grover's Algorithm by focusing on two useful quantum states, which we'll refer to as the "good" and "bad" states. The "good" state captures the marked bitstrings and the "bad" state is orthogonal to the "good" state.
Suppose there are marked states, i.e., there are elements with . Letting , we introduce the following quantum states:
These are the uniform superpositions of marked and unmarked states, referred to as the "good" and "bad" states, respectively.
Rewriting the uniform superposition state in terms of and , we obtain:
Good and Bad States: Step-by-step Example
Let's see what this look likes for our example of and marked states 1001
and 1111
. Here since there are 4 qubits and 16 computational basis states with . The good state is an equal superposition of the states and :
The bad state is an equal superposition of the remaining states:
Notice that the states and are orthogonal (with respect to the standard Hermitian inner product on the Hilbert space ). We will verify this in the code block below by computing the 'overlap' between and , which is equal to , the absolute value of the inner product of and .
Geometry of the Good and Bad States
In the standard basis, the vectors and have components consisting only of zeros and ones in complementary positions. Specifically, we can write:
where and . As we saw in the previous example, this structure ensures that and are orthogonal with respect to the standard Hermitian inner product:
Next, let's introduce the angle between the equal superposition state and the bad state . We can compute this angle using the dot product formula. To compute the dot product of with , notice that the coefficients for are all while the coefficients for are all except for the bad states that have coefficients . Furthermore, the states both have magnitude 1. Therefore
With this notation, we can rewrite as:
Furthermore note that a similar calculation using the dot product of and can be conducted to derive that . This would imply that can also be written as
We'll use this fact later.
Geometry of the Good and Bad States: a Step-by-step Example
In the code block below, we verify that the equality, , holds for our particular example. Recall that in our example, we have 2 marked states and 4 qubits, in other words and . In this case, . To verify that , we will compute the inner product (using the overlap function) of and , which we expect to be close to 1.
Let us now examine the geometric picture behind our current discussion. We'll consider the ambient Hilbert space to be spanned by the standard basis vectors , where the full dimension is . Since the uniform superposition state can be expressed as a linear combination of the states and with real coefficients, all three states and reside in a two-dimensional real subspace of the ambient Hilbert space, which we can visualize as a 2D plane as in the image below. Since, and are orthogonal, we can imagine them graphed as unit vectors in the positive and positive directions, respectively. From our previous expression, we see that the state forms an angle with .
Given that the number of marked states is typically small compared to , it follows that is a small angle. This assumption is reasonable, as otherwise, a sufficient number of independent queries to the oracle would likely yield a solution through classical search methods.
Step 2: Oracle application
Step 2: Explanation
After we have created a state of equal superposition, the good state is marked by flipping its phase. This is done with a phase oracle. A phase oracle is a unitary operation that has the property that for a computational basis state
Step 2: Step-by-step example
Let's consider our example of the two marked states and . We'll first write a unitary matrix that flips the computational basis state but keeps all other computational basis states fixed. We work through this marked state first because we have a built-in gate that carries out the required action, and we'll see how we can adapt it to mark other marked states. In particular, the multi-controlled Z gate applies a phase flip (-1) when all control qubits are in state |1⟩, and does nothing otherwise. Let's see this in action:
Notice that the only state with a negative phase is the 1111
state.
Your exercise is to adapt the oracle and create a new phase oracle which will flip the phase of the auxiliary qubit when the first four qubits are in the computational basis state and doing nothing to the auxiliary qubit otherwise. Hint: consider creating a kernel that when applied to the state would carry out the sequence of transformations .
When you finish the exercise above, check that the only computational basis state after an application of U9
with a negative phase is 1001
. If so, how would you combine U15
and U9
to create an oracle that only flips the phase of 1111
and 1001
leaving all other computational basis states fixed?
Step 3: Amplitude amplification
Step 3: Explanation
The main idea behind Grover's algorithm is to construct an operator (Grover iteration) that performs a clockwise rotation by in the two-dimensional plane spanned by the state vectors and . This is carried out through a composition of two rotations. First is reflected over (by a rotation operation ) and then this state is reflected over by a rotation operation , as depicted in the animation below.
After applying this operator times, the state vector becomes very close to . Consequently, performing a measurement in the standard basis yields one of the solutions with high probability.
The following section describes the derivation of the rotation gates and in general. If you are not concerned with understanding the mathematics, you can skip this optional section and continue down to the section titled "Reflecting over the State: Step-by-step example" to see how this operation is defined for our particular -qubit example.
(optional) Realizing Grover's Diffusion Operator: Reflection as Composition of Rotations
In this section we will derive the gate sequences needed to carry out the rotations followed by . We'll start by examining rotations in general.
Let be a vector, and let denote the reflection with respect to . By reflection with respect to a vector, we mean the linear map that leaves unchanged and maps any vector orthogonal to to its negative:
where denotes the dot product on .
If and are two vectors, then the composition of reflections with respect to them results in a rotation by twice the angle between them in the two-dimensional plane they span:
where is the angle between and .
In the case where and are unit vectors, i.e., , this formula simplifies to .
In order to realize Grover's iteration operator, which performs a rotation by in the direction from to , we will construct the reflections with respect to the state vectors and . We will denote this operator by
First, we focus on the reflection with respect to . The oracle for our Boolean function is the unitary operator , which acts on the given qubits and an auxiliary one, usually called an ancilla, as follows
where denotes addition modulo .
It follows that
This holds because , and the function value affects both terms in the same way, leaving the superposition unchanged. Similarly, we can check that
From this, it immediately follows that
This confirms that realizes the desired reflection in the two-dimensional plane spanned by and with respect to .
Remark. For the purposes of constructing the iteration operator, it suffices that implements the necessary reflection in the -dimensional subspace under consideration. However, it is interesting to note that is NOT a reflection with respect to in the full -dimensional Hilbert space. While it leaves unchanged, it does not map every vector orthogonal to to its negative. (Think this through as an exercise!)
The next step is to realize the operator that performs reflection with respect to . First, let's recall the general formula for an operator of reflection with respect to a vector.
Let be a real vector space with inner product (for our purposes, the standard dot product suffices). For a vector , the reflection with respect to is given by:
where denotes the identity operator. This formula simplifies to:
when is a unit vector, i.e., , which is always the case for state vectors in quantum mechanics.
To verify that this formula indeed defines a reflection across , we compute:
which confirms that is left unchanged. Similarly, for any vector orthogonal to , i.e., , we obtain:
This confirms that acts as the required reflection.
In Dirac notation, the formula for reflection with respect to a state vector takes the form:
Thus, the operator we need to realize is:
Recalling that is given by applying the Hadamard transform to the all-zero state:
we can rewrite the reflection as:
Here, we have used the property , which implies:
Notice that the operator:
is simply the reflection across the state vector . This reflection acts as the identity on and multiplies all other computational basis states by . This is typically implemented using a combination of multi-controlled NOT gates (Toffoli gates) and a single-qubit -gate. Let's refer to as to indicate that it is a reflection about .
Thus, the reflection about can be realized by first applying to move into the computational basis, applying the reflection about , and then applying again to return to the original basis:
Reflecting over the |0000> State: Step-by-step example
Before defining reflection over the state, we'll first define a gate sequence that will reflect a state with respect to the all zero state.
For ( n = 4 ), the reflection operator acts as the identity on and multiplies all other computational basis states by . Because we cannot distinguish states that differ by a global phase, this reflection operator is equivalent to which flips the phase of , while acting as the identity on all the other computational basis states.
To implement this reflection, we'll
Apply X gates to all qubits: This maps to and vice versa. Every other basis state is mapped to some other basis state.
Apply a multi-controlled Z (phase flip) This flips the sign of only the |1...1> ((which was originally |0...0>)
Apply gates again to revert the transformation.
In the code block below, change the initial state to test out that the all_zero_reflection function fixes the phase of all computational states except the all-zero state.
Reflecting over the equal superposition state: Step-by-step example
Now let's adapt the all_zero_reflection
to instead reflect about the equal superposition state. To do this we'll wrap the all_zero_reflection
kernel with Hadamard gates which will transform the qubits from the equal superposition state to the all zero state and back.
Now that we've defined , we're only left with defining . But we've actually already done that! Notice that the controlled-phase oracle that we discussed earlier has the effect of reflecting the state over the state , which is exactly what we need for .
Completing Step 3: Explanation and step-by-step example
We are now able to realize the iterated operator in Grover's algorithm, which we will denote by .
The circuit diagram below puts together steps 1 through 3:
Running this circuit initializes and performs a rotation by (twice the angle between and ) in the direction from to .
Recall that in our example the state is approximately away from . Let's verify that the state resulting from one iteration of Grover's algorithm is away from . Moreover, notice that the amplitudes of 1001
and 1111
in the resulting state have been amplified compared to the equal superposition of states.
Steps 4 and 5: Iteration and measurement
Depending on and the number of marked states , one iteration of the gate sequence may not amplifiy the good states enough to distinguish them from the bad states. However, iterating this sequence one more time will result in a vector radians away from the state , further amplifying the good states. We can repeat this until we are close enough to the good state. But we have to be careful not to repeat this gate sequence too many times as we may overshoot the good state. In this section we'll derive a formula that will tell us how many times we'll need to iterate the rotation gate sequence in Grover's algorithm.
Steps 4 and 5: Explanation
Since the initial angle between and is , applying for times produces a vector
that forms an angle of with .
Since the desired final state is at an angle of from , we need:
Recalling that
and using the small-angle approximation for , we obtain:
Thus, after approximately
iterations, the state is very close to , ensuring that a measurement in the computational basis yields a solution with high probability.
Steps 4 and 5: Step-by-step example
Edit the num_iterations
variable in the code block below to compute the angle between the resulting state of num_iterations
iterations of the Grover diffusion operator and the state along with the histogram of the resulting sampling distribution. Edit the num_iterations
variable value in the code block below. Notice how increasing the number of iterations beyond a certain point produces states with lower probability amplitudes of the marked states than desired. Why might this happen? What number of iterations results in a better chance of sampling a marked state? How does this compare from the number of iterations that are prescribed by the formula:
Summary
The steps of the algorithm can be summarized as follows.
Step 1. Initialize the uniform superposition state: on the first qubits and initialize the auxilary qubit in the minus state.
Steps 2, 3, and 4. Apply the rotation gate sequence exactly times, where: Step 5. Sample the circuit with shots_count=1
, obtaining a basis state . Check whether is a solution by evaluating . If , return ; otherwise, restart the algorithm.
This procedure ensures that with high probability, the measurement yields a correct solution in approximately steps, providing a quadratic speedup over classical exhaustive search.
One of the applications of Grover's algorithm is solving satisfiability (SAT) problems, which is critical in software verification. SAT, in general, is NP complete. The exercise below is a toy example of a SAT problem that you can try to solve with Grover's algorithm to test your understanding.
EXERCISE. Suppose Lewis wants to throw a party and invites Alice, the cat, and the rabbit. However, due to recent events in Wonderland, the following conditions must be met:
Alice joins the party if and only if the cat also joins, and the rabbit does not.
The rabbit will only participate if the cat is also present.
The cat dislikes the rabbit’s company and will not come if the rabbit is there.
It is easy to verify that the only valid arrangements satisfying these conditions are:
- no one attends the party;
- Alice and the cat attend together.
Solution. We encode this problem using three bits: a bit value of indicates attendance, while indicates absence. Assigning the first bit to Alice, the second to the cat, and the third to the rabbit, we define a Boolean function that marks valid solutions:
Applying Grover's algorithm, we note that the total number of states is and the number of solutions is . The superposition of solutions is given by while the equal superposition of the remaining states is
As we have , the angle satisfies: We solve for : Thus, a single iteration of the Grover diffusion operator maps exactly to , ensuring that the subsequent measurement yields a valid solution with probability!
Try writing the code for this. In particular, you will need to create new code for the phase oracle.