# Grover's Algorithm

This notebook demonstrates how to use the construct_grover_model function, which constructs a Grover search model. For more comprehensive explanation on the algorithm see 3SAT Grover notebook.

## 1. Defining a Specific Example

Start with specifying a specific search problem: the arithmetic variables and the arithmetic predicate.

def classical_predicate(a, b, c):
return (a + b + (c & 6)) % 4 | 4 & c == 4


with a, b, c unsinged integers of size 3.

## 2. Constructing and Synthesizing a Grover Model

We now call the grover_search for the specific case. We pass the number of grover operator repetitions in the model (which is based on the frequency of solutions in the search space).

from classiq import *

NUM_VARIABLES = 3

class PredicateVars(QStruct):
a: QNum[2, False, 0]
b: QNum[2, False, 0]
c: QNum[3, False, 0]

@qfunc
def quantum_predicate(vars: PredicateVars, res: QBit):
res ^= classical_predicate(vars.a, vars.b, vars.c)

@qfunc
def main(vars: Output[PredicateVars]):
allocate(vars.size, vars)

grover_search(
reps=1,
oracle=lambda vars: phase_oracle(quantum_predicate, vars),
packed_vars=vars,
)

qmod = create_model(main)

write_qmod(qmod, "grover")


We synthesize and visualize the circuit

qprog = synthesize(qmod)

show(qprog)

Opening: http://localhost:4200/circuit/57eaa16b-6943-458c-a973-4267bc411a17?version=0.0.0


## 3. Executing to Find the Result

Lastly, we execute the resulting quantum program

res = execute(qprog).result()[0].value


We can take the three-most probable results (the parsed_counts variable of the results is ordered according to the probability of the corresponding state)

res.parsed_counts[0].state["vars"]

{'a': 1, 'b': 3, 'c': 5}

NUM_SOLUTIONS = 3

for k in range(NUM_SOLUTIONS):
parsed_res = res.parsed_counts[k].state["vars"]
a, b, c = int(parsed_res["a"]), int(parsed_res["b"]), int(parsed_res["c"])
print("a =", a, ", b =", b, ", c =", c, ":", classical_predicate(a, b, c))

a = 1 , b = 3 , c = 5 : True
a = 1 , b = 1 , c = 6 : True
a = 2 , b = 2 , c = 5 : True