# Grovers Algorithm

Given an unstructured set \(N = {a_1, a_2,\dots,a_n}\), find a given element \(a_i \in N\).

This implementation looks for a given number \(target\) in the set \({0,1,\dots, \text{regwidth}}\).

See https://cs.uwaterloo.ca/~watrous/LectureNotes.html

    extern crate qcgpu;
    extern crate rand;

    use qcgpu::State;
    use std::f32::consts::PI;

    fn main() {
        let mut state = State::new(8, 1);

        let target = 5;
        let reg_width = 3;

        let num_inversions = ((PI / 4.0) * ((1 << reg_width) as f32).sqrt()) as i32;

        state.x(reg_width);

        for i in 0..(reg_width + 1) {
            state.h(i);
        }

        for _ in 0..(num_inversions) {
            iteration(&mut state, target, reg_width);
        }

        state.h(reg_width);

        println!("Measured: {:?}", state.measure_first(reg_width, 1000));
    }

    fn oracle(state: &mut State, target: i32, reg_width: i32) {
        for i in 0..reg_width {
            if get_bit(target, i) == 0 {
                state.x(i);
            }
        }

        state.toffoli(0, 1, reg_width + 1);

        let mut i = 1;
        while i < reg_width {
            state.toffoli(i, reg_width + i, reg_width + i + 1);
            i += 1;
        }

        state.cx(reg_width + i, reg_width);

        i = reg_width - 1;
        while i > 0 {
            state.toffoli(i, reg_width + i, reg_width + i + 1);
            i -= 1;
        }

        state.toffoli(0, 1, reg_width + 1);

        for i in 0..reg_width {
            if get_bit(target, i) == 0 {
                state.x(i);
            }
        }
    }

    fn inversion(state: &mut State, reg_width: i32) {
        for i in 0..reg_width {
            state.x(i);
        }

        state.h(reg_width - 1);

        if reg_width == 3 {
            state.toffoli(0, 1, 2);
        } else {
            state.toffoli(0, 1, reg_width + 1);

            let mut i = 1;
            while i < reg_width {
                state.toffoli(i, reg_width + i, reg_width + i + 1);
                i += 1;
            }

            state.cx(reg_width + i, reg_width - 1);

            i = reg_width - 2;
            while i > 0 {
                state.toffoli(i, reg_width + i, reg_width + i + 1);
                i -= 1;
            }

            state.toffoli(0, 1, reg_width + 1);
        }

        state.h(reg_width - 1);

        for i in 0..reg_width {
            state.x(i);
        }
    }

    fn iteration(state: &mut State, target: i32, reg_width: i32) {
        oracle(state, target, reg_width);

        for i in 0..reg_width {
            state.h(i);
        }

        inversion(state, reg_width);

        for i in 0..reg_width {
            state.h(i);
        }
    }

    /// Get the value of a bit
    fn get_bit(number: i32, n: i32) -> i32 {
        if number & (1 << n) != 0 {
            return 1;
        }
        0
    }