grovers/
grovers.rs

1/*
2* Copyright (c) 2024 Andrew Rowan Barlow. Licensed under the EUPL-1.2
3* or later. You may obtain a copy of the licence at
4* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12. A copy
5* of the EUPL-1.2 licence in English is given in LICENCE.txt which is
6* found in the root directory of this repository.
7*
8* Author: Andrew Rowan Barlow <a.barlow.dev@gmail.com>
9*/
10
11// A 3 qubit circuit that implements Grovers algorithm. The oracle target the states |110> and
12// |111>. This example will also print the circuit, and show the simulation in real time.
13//
14// This example will print a bin count of measured states from 500 repeated simulations, and the
15// superposition itself.
16
17use quantr::{Circuit, Gate, Measurement, Printer, QuantrError};
18
19#[rustfmt::skip]
20fn main() -> Result<(), QuantrError> {
21    let mut circuit = Circuit::new(3)?;
22
23    // Kick state into superposition of equal weights
24    circuit.add_repeating_gate(Gate::H, &[0, 1, 2])?;
25
26    // Oracle
27    circuit.add_gate(Gate::CZ(1), 0)?;
28
29    // Amplitude amplification
30    circuit
31        .add_repeating_gate(Gate::H, &[0, 1, 2])?
32        .add_repeating_gate(Gate::X, &[0, 1, 2])?
33        .add_gate(Gate::H, 2)?
34        .add_gate(Gate::Toffoli(0, 1), 2)?
35        .add_gate(Gate::H, 2)?
36        .add_repeating_gate(Gate::X, &[0, 1, 2])?
37        .add_repeating_gate(Gate::H, &[0, 1, 2])?;
38
39    // Prints the circuit in UTF-8
40    let mut printer = Printer::new(&circuit);
41    printer.print_diagram();
42
43    // Print the progress of the simulation
44    circuit.set_print_progress(true);
45
46    // Simulates the circuit
47    let simulated_circuit = circuit.simulate();
48    println!("");
49
50    // Displays bin count of the resulting 500 repeat measurements of
51    // superpositions. bin_count is a HashMap<ProductState, usize>.
52    if let Measurement::Observable(bin_count) = simulated_circuit.measure_all(500) {
53        println!("[Observable] Bin count of observed states.");
54        for (state, count) in bin_count {
55            println!("|{}> observed {} times", state, count);
56        }
57    } 
58
59    // Returns the superpsoition that cannot be directly observed.
60    if let Measurement::NonObservable(output_super_position) = simulated_circuit.get_state()
61    {
62        println!("\n[Non-Observable] The amplitudes of each state in the final superposition.");
63        for (state, amplitude) in output_super_position.into_iter() {
64            println!("|{}> : {}", state, amplitude);
65        }
66    }
67
68    Ok(())
69}