Grover's algorithm

Grover's algorithm finds with high probability the unique input to a black box function that produces a particular output value, using just evaluations of the function, where is the size of the function's domain. As a comparison, the analogous problem in classical computation cannot be solved in fewer than evaluations. Although Grover's algorithm provides only a quadratic speedup, it is considerable when is large, and Grover's algorithm can be applied to speed up broad classes of algorithms.

As input for Grover's algorithm, suppose we have a function . In the "unstructured database" analogy, the domain represents indices to a database, and if and only if the data that points to satisfies the search criterion. We additionally assume that only one index satisfies , and we call this index . Our goal is to identify .

We can access with an oracle in the form of a unitary operator that acts as i.e., This uses the -dimensional state space , which is supplied by a register with qubits.

The steps of Grover's algorithm are

  1. Initialize the system to uniform superposition over all states

  2. Perform the following "Grover iteration" times:

    1. Apply oracle ;

    2. Apply the Grover diffusion operator

  3. Measure the resulting quantum state in the computational basis.

The circuit is shown as the following:

We write an example using isQ to demonstrate Grover's algorithm. In this example, , corresponding to the Hilbert space of 3 qubits. With this size, we can calculate that 2 Grover iterations are needed. We select , i.e., only . This oracle is defined using a truth table. Next, we define using a unitary matrix. The full program is shown below.

import std;

oracle U_omega(3,1) = [0,1,0,0,0,0,0,0];

defgate U0 = [
    1, 0, 0, 0, 0, 0, 0, 0;
    0, -1, 0, 0, 0, 0, 0, 0;
    0, 0, -1, 0, 0, 0, 0, 0;
    0, 0, 0, -1, 0, 0, 0, 0;
    0, 0, 0, 0, -1, 0, 0, 0;
    0, 0, 0, 0, 0, -1, 0, 0;
    0, 0, 0, 0, 0, 0, -1, 0;
    0, 0, 0, 0, 0, 0, 0, -1
];

qbit q[3];
qbit anc;

int grover_search() {
    // Initialize
    H(q);
    X(anc);
    H(anc);

    // Grover iterations
    for i in 0:2 {
        U_omega(q[2], q[1], q[0], anc);
        H(q);
        U0(q[2], q[1], q[0]);
        H(q);
    }

    // Finilize
    H(anc);
    X(anc);
    return M(q);
}

procedure main(){
    print grover_search();
}

We executed the program 100 times using isQ compiler's command bin/isqc run --shots 100 examples/grover.isq. The execution result is

{"010": 1, "110": 1, "011": 1, "001": 97}

Most of the results (97 out of 100) are 1, equal to . It shows that Grover's algorithm finds the desired answer with a high probability.