View on GitHub
Open this notebook in GitHub to run it yourself
Grover’s Search Algorithm, introduced by Lov Grover in 1996 [1], is one of the canonical quantum algorithms. It provides a quadratic speedup for searching an unstructured database and is often considered alongside Shor’s algorithm as a cornerstone of quantum computing. The search algorithm has applications in various fields, such as in cybersecurity.Grover’s Search algorithm starts with preparing the search space , and then repeats over a combination of two reflection operations: The number of times we need to repeat the combination of these two reflections (sometimes called a “Grover Operator”) depends on the number of solutions: for solutions in a search space of size , we shall perform iterations. In practice, however, the number of solutions is often unknown. In that case, one can perform a quantum counting algorithm prior to the search, or run the search algorithm repeatedly, with an increasing number of repetitions for . Both approaches do not affect the complexity of the search algorithm. In this notebook we take the second approach. For a given problem, Grover’s algorithm depends on two functions, one for preparing the search space and another for applying the oracle, as well as on the number of repetitions. Below we address two canonical search problems, a 3-SAT problem and a Max-Cut problem on a graph. In this notebook we work with theComplexity: The algorithm requires oracle queries to obtain the result, while the query complexity for classical search is .
- Input: A Boolean function (oracle) marking “solutions” among possible items.
- Promise: At least one marked element exists in the search space.
- Output: With high probability, the algorithm outputs a marked element (i.e., ).
Keywords: Search and optimization, Unstructured search, Quadratic speedup, Amplitude amplification, Graph problems, SAT problems, Oracle/Query complexity.
grover_operator function, and define a classical postprocess function for iterating over different values and obtianing the marked states.
Using the phase_oracle quantum function from the Classiq open-library together with the Qmod language for high-level problem definitions helps avoid low-level implementation details that are typically required on other platforms.

Classical postprocess function
Below we define a function that runs a quantum program of the Grover’s search algorithm, for an increasing number of repetitions, until a marked state is found.Example: 3-SAT problem
The 3-SAT problem [2] is a famous problem, a solution of which allows solving any problem in the complexity class . We treat two different 3-SAT problems, a small one and a larger one. For illustration, we define a function for printing the truth table of SAT problems.Small 3-SAT formula
We specify a 3-SAT formula in the so-called Conjunctive Normal Form (CNF), that requires a solution:Output:
phase_oracle that transforms ‘digital’ oracle; i.e., to a phase oracle .
The predicate that we pass to the phase oracle is simply given by the 3-CNF formula defined above.
Output:
Output:
Output:
| x | counts | probability | bitstring | f(x) | |
|---|---|---|---|---|---|
| 0 | [0, 1, 1] | 510 | 0.51 | 110 | 1 |
| 1 | [0, 1, 0] | 490 | 0.49 | 010 | 1 |
Large 3-SAT formula
We continue with a larger example:Output:
small_3sat_formula to large_3sat_formula.
Output:
| x | counts | probability | bitstring | f(x) | |
|---|---|---|---|---|---|
| 0 | [0, 0, 1, 1] | 475 | 0.475 | 1100 | 1 |
| 1 | [0, 0, 0, 1] | 471 | 0.471 | 1000 | 1 |
| 2 | [0, 1, 1, 0] | 6 | 0.006 | 0110 | 0 |
| 3 | [0, 1, 1, 1] | 6 | 0.006 | 1110 | 0 |
| 4 | [0, 1, 0, 0] | 5 | 0.005 | 0010 | 0 |
Example: Graph Cut Search Problem
The “Maximum Cut Problem” (MaxCut) [3] is an example of a combinatorial optimization problem. It refers to finding a partition of a graph into two sets, such that the number of edges between the two sets is the maximum. The MaxCut problem is defined as follows: Given a graph with nodes and edges, a cut is defined as a partition of the graph into two complementary subsets of nodes. The gaol is to find a cut where the number of edges between the two subsets is the maximum. We can represent a cut, and the number of its connecting edges as follows:- is a binary vector of size that represents a cut: assigning 0 and 1 to nodes in the first and second subsets, respectively.
- gives the number of connecting edges for a given cut.

Output:
Output:
| nodes | counts | probability | bitstring | f(x) | |
|---|---|---|---|---|---|
| 0 | [1, 0, 0, 1, 0] | 111 | 0.111 | 01001 | True |
| 1 | [0, 1, 1, 0, 0] | 108 | 0.108 | 00110 | True |
| 2 | [1, 0, 0, 0, 1] | 108 | 0.108 | 10001 | True |
| 3 | [1, 0, 1, 1, 0] | 103 | 0.103 | 01101 | True |
| 4 | [0, 1, 1, 1, 0] | 97 | 0.097 | 01110 | True |
| 5 | [0, 1, 0, 0, 1] | 94 | 0.094 | 10010 | True |
| 6 | [0, 1, 1, 0, 1] | 89 | 0.089 | 10110 | True |
| 7 | [0, 0, 1, 1, 0] | 87 | 0.087 | 01100 | True |
| 8 | [1, 1, 0, 0, 1] | 85 | 0.085 | 10011 | True |
| 9 | [1, 0, 0, 1, 1] | 79 | 0.079 | 11001 | True |
| 10 | [0, 0, 0, 0, 0] | 4 | 0.004 | 00000 | False |
| 11 | [0, 0, 1, 1, 1] | 4 | 0.004 | 11100 | False |
| 12 | [0, 1, 0, 1, 0] | 3 | 0.003 | 01010 | False |
| 13 | [0, 1, 0, 1, 1] | 3 | 0.003 | 11010 | False |
| 14 | [1, 0, 1, 1, 1] | 3 | 0.003 | 11101 | False |
| 15 | [1, 1, 1, 1, 1] | 3 | 0.003 | 11111 | False |
| 16 | [1, 0, 0, 0, 0] | 2 | 0.002 | 00001 | False |
| 17 | [1, 0, 1, 0, 0] | 2 | 0.002 | 00101 | False |
| 18 | [1, 1, 1, 0, 0] | 2 | 0.002 | 00111 | False |
| 19 | [0, 0, 1, 0, 1] | 2 | 0.002 | 10100 | False |
| 20 | [1, 1, 1, 0, 1] | 2 | 0.002 | 10111 | False |
| 21 | [0, 1, 0, 0, 0] | 1 | 0.001 | 00010 | False |
| 22 | [0, 0, 1, 0, 0] | 1 | 0.001 | 00100 | False |
| 23 | [1, 1, 0, 1, 0] | 1 | 0.001 | 01011 | False |
| 24 | [1, 1, 1, 1, 0] | 1 | 0.001 | 01111 | False |
| 25 | [0, 0, 0, 0, 1] | 1 | 0.001 | 10000 | False |
| 26 | [1, 0, 1, 0, 1] | 1 | 0.001 | 10101 | False |
| 27 | [0, 0, 0, 1, 1] | 1 | 0.001 | 11000 | False |
| 28 | [1, 1, 0, 1, 1] | 1 | 0.001 | 11011 | False |
| 29 | [0, 1, 1, 1, 1] | 1 | 0.001 | 11110 | False |
