Struct quantr::Circuit

source ·
pub struct Circuit<'a> { /* private fields */ }
Expand description

A quantum circuit where gates can be appended and then simulated to measure resulting superpositions.

Implementations§

source§

impl<'a> Circuit<'a>

source

pub const fn new(num_qubits: usize) -> Result<Circuit<'a>, QuantrErrorConst>

👎Deprecated: In the next major update, const will be removed from this function. Therefore, please do not use this function in constant settings.

Initialises a new circuit.

The lifetime is due to the slices of control qubits for Gate::Custom. That is, the slice argument must outlive the circuit.

§Example
use quantr::Circuit;

// Initialises a 3 qubit circuit.
let quantum_circuit: Circuit = Circuit::new(3).unwrap();
Examples found in repository?
examples/qft.rs (line 24)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(3)?;

    // Apply qft
    qc.add_repeating_gate(Gate::X, &[1, 2])?
        .add_gate(Gate::Custom(qft, &[0, 1], "QFT".to_string()), 2)?; // QFT on bits 0, 1 and 2

    let mut printer = Printer::new(&qc);
    printer.print_diagram();

    qc.toggle_simulation_progress();

    qc.simulate();

    if let Ok(Measurement::NonObservable(final_sup)) = qc.get_superposition() {
        println!("\nThe final superposition is:");
        for (state, amplitude) in final_sup.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}

// A QFT implementation that can be used for other circuits. Note, the output is reveresed compared
// to usual conventions; swap gates are needed.
fn qft(input_state: ProductState) -> Option<SuperPosition> {
    let qubit_num = input_state.num_qubits();
    let mut mini_circuit: Circuit = Circuit::new(qubit_num).unwrap();

    for pos in 0..qubit_num {
        mini_circuit.add_gate(Gate::H, pos).unwrap();
        for k in 2..=(qubit_num - pos) {
            mini_circuit
                .add_gate(Gate::CRk(k as i32, pos + k - 1), pos)
                .unwrap();
        }
    }

    mini_circuit
        .change_register(SuperPosition::from(input_state))
        .unwrap()
        .simulate();

    if let Ok(Measurement::NonObservable(super_pos)) = mini_circuit.get_superposition() {
        Some(super_pos.clone())
    } else {
        panic!("No superposition was simualted!");
    }
}
More examples
Hide additional examples
examples/generalised_control_not_gate.rs (line 24)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;

    // Multi-controlled gate used here.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2, 3, 4, 5])?
        .add_gate(
            Gate::Custom(multicnot::<CIRCUIT_SIZE>, &[0, 1, 2, 3, 4], "X".to_string()),
            5,
        )?;

    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress();
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
examples/custom_gate.rs (line 21)
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(4)?;

    // Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
    // the target on 3.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::Custom(cccnot, &[0, 1, 2], "X".to_string()), 3)?;

    // Prints the circuit, viewing the custom gate, and then simulating it.
    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress(); // prints the simulation toggle_simulation_progress
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
examples/grovers.rs (line 22)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
fn main() -> Result<(), Box<dyn Error>>{
    let mut circuit = Circuit::new(3)?;

    // Kick state into superposition of equal weights
    circuit.add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Oracle
    circuit.add_gate(Gate::CZ(1), 0)?;

    // Amplitude amplification
    circuit
        .add_repeating_gate(Gate::H, &[0, 1, 2])?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::H, 2)?
        .add_gate(Gate::Toffoli(0, 1), 2)?
        .add_gate(Gate::H, 2)?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Prints the circuit in UTF-8
    let mut printer = Printer::new(&circuit);
    printer.print_diagram();

    // Un-commenting the line below will print the progress of the simulation
    circuit.toggle_simulation_progress();

    // Simulates the circuit
    circuit.simulate();
    println!("");

    // Displays bin count of the resulting 500 repeat measurements of
    // superpositions. bin_count is a HashMap<ProductState, usize>.
    if let Ok(Measurement::Observable(bin_count)) = circuit.repeat_measurement(500) {
        println!("[Observable] Bin count of observed states.");
        for (state, count) in bin_count {
            println!("|{}> observed {} times", state, count);
        }
    } 

    // Returns the superpsoition that cannot be directly observed.
    if let Ok(Measurement::NonObservable(output_super_position)) = circuit.get_superposition()
    {
        println!("\n[Non-Observable] The amplitudes of each state in the final superposition.");
        for (state, amplitude) in output_super_position.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}
source

pub const fn get_num_qubits(&self) -> usize

👎Deprecated: In the next major update, const will be removed from this function. Therefore, please do not use this function in constant settings.

Returns the number of qubits in the circuit.

§Example
use quantr::{Circuit, Gate};

let quantum_circuit: Circuit = Circuit::new(3).unwrap();
assert_eq!(quantum_circuit.get_num_qubits(), 3usize);
source

pub fn get_toggle_progress(&self) -> bool

Returns if the circuit will print explicit simulatin output set by Circuit::toggle_simulation_progress.

§Example
use quantr::{Circuit};

let mut quantum_circuit = Circuit::new(2).unwrap();
assert_eq!(quantum_circuit.get_toggle_progress(), false);
quantum_circuit.toggle_simulation_progress();
assert_eq!(quantum_circuit.get_toggle_progress(), true);
source

pub fn get_gates(&self) -> &[Gate<'a>]

Returns the vector of gates that have been added to the circuit.

It is a flattened vector which is buffered with identity gates.

§Example
use quantr::{Circuit, Gate};

let mut quantum_circuit: Circuit = Circuit::new(3).unwrap();
quantum_circuit.add_gate(Gate::X, 2).unwrap();

assert_eq!(quantum_circuit.get_gates(), &[Gate::Id, Gate::Id, Gate::X]);
source

pub fn add_gate( &mut self, gate: Gate<'a>, position: usize ) -> Result<&mut Circuit<'a>, QuantrError>

Adds a single gate to the circuit.

If wanting to add multiple gates, or a single gate repeatedly across multiple wires, see Circuit::add_gates_with_positions and Circuit::add_repeating_gate respectively.

§Example
use quantr::{Circuit, Gate};

let mut quantum_circuit: Circuit = Circuit::new(3).unwrap();
quantum_circuit.add_gate(Gate::X, 0).unwrap();

// Produces the circuit:
// -- X --
// -------
// -------
Examples found in repository?
examples/qft.rs (line 28)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(3)?;

    // Apply qft
    qc.add_repeating_gate(Gate::X, &[1, 2])?
        .add_gate(Gate::Custom(qft, &[0, 1], "QFT".to_string()), 2)?; // QFT on bits 0, 1 and 2

    let mut printer = Printer::new(&qc);
    printer.print_diagram();

    qc.toggle_simulation_progress();

    qc.simulate();

    if let Ok(Measurement::NonObservable(final_sup)) = qc.get_superposition() {
        println!("\nThe final superposition is:");
        for (state, amplitude) in final_sup.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}

// A QFT implementation that can be used for other circuits. Note, the output is reveresed compared
// to usual conventions; swap gates are needed.
fn qft(input_state: ProductState) -> Option<SuperPosition> {
    let qubit_num = input_state.num_qubits();
    let mut mini_circuit: Circuit = Circuit::new(qubit_num).unwrap();

    for pos in 0..qubit_num {
        mini_circuit.add_gate(Gate::H, pos).unwrap();
        for k in 2..=(qubit_num - pos) {
            mini_circuit
                .add_gate(Gate::CRk(k as i32, pos + k - 1), pos)
                .unwrap();
        }
    }

    mini_circuit
        .change_register(SuperPosition::from(input_state))
        .unwrap()
        .simulate();

    if let Ok(Measurement::NonObservable(super_pos)) = mini_circuit.get_superposition() {
        Some(super_pos.clone())
    } else {
        panic!("No superposition was simualted!");
    }
}
More examples
Hide additional examples
examples/generalised_control_not_gate.rs (lines 28-31)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;

    // Multi-controlled gate used here.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2, 3, 4, 5])?
        .add_gate(
            Gate::Custom(multicnot::<CIRCUIT_SIZE>, &[0, 1, 2, 3, 4], "X".to_string()),
            5,
        )?;

    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress();
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
examples/custom_gate.rs (line 26)
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(4)?;

    // Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
    // the target on 3.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::Custom(cccnot, &[0, 1, 2], "X".to_string()), 3)?;

    // Prints the circuit, viewing the custom gate, and then simulating it.
    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress(); // prints the simulation toggle_simulation_progress
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
examples/grovers.rs (line 28)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
fn main() -> Result<(), Box<dyn Error>>{
    let mut circuit = Circuit::new(3)?;

    // Kick state into superposition of equal weights
    circuit.add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Oracle
    circuit.add_gate(Gate::CZ(1), 0)?;

    // Amplitude amplification
    circuit
        .add_repeating_gate(Gate::H, &[0, 1, 2])?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::H, 2)?
        .add_gate(Gate::Toffoli(0, 1), 2)?
        .add_gate(Gate::H, 2)?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Prints the circuit in UTF-8
    let mut printer = Printer::new(&circuit);
    printer.print_diagram();

    // Un-commenting the line below will print the progress of the simulation
    circuit.toggle_simulation_progress();

    // Simulates the circuit
    circuit.simulate();
    println!("");

    // Displays bin count of the resulting 500 repeat measurements of
    // superpositions. bin_count is a HashMap<ProductState, usize>.
    if let Ok(Measurement::Observable(bin_count)) = circuit.repeat_measurement(500) {
        println!("[Observable] Bin count of observed states.");
        for (state, count) in bin_count {
            println!("|{}> observed {} times", state, count);
        }
    } 

    // Returns the superpsoition that cannot be directly observed.
    if let Ok(Measurement::NonObservable(output_super_position)) = circuit.get_superposition()
    {
        println!("\n[Non-Observable] The amplitudes of each state in the final superposition.");
        for (state, amplitude) in output_super_position.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}
source

pub fn add_gates_with_positions( &mut self, gates_with_positions: HashMap<usize, Gate<'a>> ) -> Result<&mut Circuit<'a>, QuantrError>

Add a column of gates specifying the position for each gate.

A HashMap<usize, Gate> is used to place gates onto their desired position. This is similar to Circuit::add_gate, however not all wires have to be accounted for.

§Example
use quantr::{Circuit, Gate};
use std::collections::HashMap;

let mut quantum_circuit: Circuit = Circuit::new(3).unwrap();
// Adds gates on wires 0 and 2, implicitly leaving wire 1 bare.
quantum_circuit.add_gates_with_positions(
    HashMap::from(
        [(0, Gate::X), (2, Gate::H)]
    )
).unwrap();

// Produces the circuit:
// -- X --
// -------
// -- H --
source

pub fn add_gates( &mut self, gates: &[Gate<'a>] ) -> Result<&mut Circuit<'a>, QuantrError>

Add a column of gates.

Expects the input vector to specify the gate that is added to each wire. That is, the length of the vector should equal the number of wires. To only add gates based on their positions, see Circuit::add_gates_with_positions and Circuit::add_gate.

§Example
use quantr::{Circuit, Gate};

let mut quantum_circuit: Circuit = Circuit::new(3).unwrap();
let gates_to_add = [Gate::H, Gate::X, Gate::Y];

quantum_circuit.add_gates(&gates_to_add).unwrap();

// Produces the circuit:
// -- H --
// -- X --
// -- Y --
source

pub fn add_repeating_gate( &mut self, gate: Gate<'a>, positions: &[usize] ) -> Result<&mut Circuit<'a>, QuantrError>

Place a single gate repeatedly onto multiple wires.

For adding multiple different gates, refer to Circuit::add_gates and Circuit::add_gates_with_positions.

§Example
use quantr::{Circuit, Gate};

let mut quantum_circuit: Circuit = Circuit::new(3).unwrap();
quantum_circuit.add_repeating_gate(Gate::H, &[1, 2]).unwrap();

// Produces the circuit:
// -------
// -- H --
// -- H --
Examples found in repository?
examples/qft.rs (line 27)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(3)?;

    // Apply qft
    qc.add_repeating_gate(Gate::X, &[1, 2])?
        .add_gate(Gate::Custom(qft, &[0, 1], "QFT".to_string()), 2)?; // QFT on bits 0, 1 and 2

    let mut printer = Printer::new(&qc);
    printer.print_diagram();

    qc.toggle_simulation_progress();

    qc.simulate();

    if let Ok(Measurement::NonObservable(final_sup)) = qc.get_superposition() {
        println!("\nThe final superposition is:");
        for (state, amplitude) in final_sup.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}
More examples
Hide additional examples
examples/generalised_control_not_gate.rs (line 27)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;

    // Multi-controlled gate used here.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2, 3, 4, 5])?
        .add_gate(
            Gate::Custom(multicnot::<CIRCUIT_SIZE>, &[0, 1, 2, 3, 4], "X".to_string()),
            5,
        )?;

    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress();
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
examples/custom_gate.rs (line 25)
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(4)?;

    // Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
    // the target on 3.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::Custom(cccnot, &[0, 1, 2], "X".to_string()), 3)?;

    // Prints the circuit, viewing the custom gate, and then simulating it.
    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress(); // prints the simulation toggle_simulation_progress
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
examples/grovers.rs (line 25)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
fn main() -> Result<(), Box<dyn Error>>{
    let mut circuit = Circuit::new(3)?;

    // Kick state into superposition of equal weights
    circuit.add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Oracle
    circuit.add_gate(Gate::CZ(1), 0)?;

    // Amplitude amplification
    circuit
        .add_repeating_gate(Gate::H, &[0, 1, 2])?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::H, 2)?
        .add_gate(Gate::Toffoli(0, 1), 2)?
        .add_gate(Gate::H, 2)?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Prints the circuit in UTF-8
    let mut printer = Printer::new(&circuit);
    printer.print_diagram();

    // Un-commenting the line below will print the progress of the simulation
    circuit.toggle_simulation_progress();

    // Simulates the circuit
    circuit.simulate();
    println!("");

    // Displays bin count of the resulting 500 repeat measurements of
    // superpositions. bin_count is a HashMap<ProductState, usize>.
    if let Ok(Measurement::Observable(bin_count)) = circuit.repeat_measurement(500) {
        println!("[Observable] Bin count of observed states.");
        for (state, count) in bin_count {
            println!("|{}> observed {} times", state, count);
        }
    } 

    // Returns the superpsoition that cannot be directly observed.
    if let Ok(Measurement::NonObservable(output_super_position)) = circuit.get_superposition()
    {
        println!("\n[Non-Observable] The amplitudes of each state in the final superposition.");
        for (state, amplitude) in output_super_position.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}
source

pub fn simulate(&mut self)

Attaches the register, |0…0>, to the circuit resulting in a superposition that can be measured.

See Circuit::get_superposition and Circuit::repeat_measurement for details on obtaining observables from the resulting superposition.

§Example
use quantr::{Circuit, Gate};

let mut circuit = Circuit::new(3).unwrap();
circuit.add_gate(Gate::H, 2).unwrap();

circuit.simulate();

// Simulates the circuit:
// |0> -------
// |0> -------
// |0> -- H --
Examples found in repository?
examples/qft.rs (line 35)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(3)?;

    // Apply qft
    qc.add_repeating_gate(Gate::X, &[1, 2])?
        .add_gate(Gate::Custom(qft, &[0, 1], "QFT".to_string()), 2)?; // QFT on bits 0, 1 and 2

    let mut printer = Printer::new(&qc);
    printer.print_diagram();

    qc.toggle_simulation_progress();

    qc.simulate();

    if let Ok(Measurement::NonObservable(final_sup)) = qc.get_superposition() {
        println!("\nThe final superposition is:");
        for (state, amplitude) in final_sup.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}

// A QFT implementation that can be used for other circuits. Note, the output is reveresed compared
// to usual conventions; swap gates are needed.
fn qft(input_state: ProductState) -> Option<SuperPosition> {
    let qubit_num = input_state.num_qubits();
    let mut mini_circuit: Circuit = Circuit::new(qubit_num).unwrap();

    for pos in 0..qubit_num {
        mini_circuit.add_gate(Gate::H, pos).unwrap();
        for k in 2..=(qubit_num - pos) {
            mini_circuit
                .add_gate(Gate::CRk(k as i32, pos + k - 1), pos)
                .unwrap();
        }
    }

    mini_circuit
        .change_register(SuperPosition::from(input_state))
        .unwrap()
        .simulate();

    if let Ok(Measurement::NonObservable(super_pos)) = mini_circuit.get_superposition() {
        Some(super_pos.clone())
    } else {
        panic!("No superposition was simualted!");
    }
}
More examples
Hide additional examples
examples/generalised_control_not_gate.rs (line 37)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;

    // Multi-controlled gate used here.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2, 3, 4, 5])?
        .add_gate(
            Gate::Custom(multicnot::<CIRCUIT_SIZE>, &[0, 1, 2, 3, 4], "X".to_string()),
            5,
        )?;

    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress();
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
examples/custom_gate.rs (line 33)
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(4)?;

    // Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
    // the target on 3.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::Custom(cccnot, &[0, 1, 2], "X".to_string()), 3)?;

    // Prints the circuit, viewing the custom gate, and then simulating it.
    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress(); // prints the simulation toggle_simulation_progress
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
examples/grovers.rs (line 48)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
fn main() -> Result<(), Box<dyn Error>>{
    let mut circuit = Circuit::new(3)?;

    // Kick state into superposition of equal weights
    circuit.add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Oracle
    circuit.add_gate(Gate::CZ(1), 0)?;

    // Amplitude amplification
    circuit
        .add_repeating_gate(Gate::H, &[0, 1, 2])?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::H, 2)?
        .add_gate(Gate::Toffoli(0, 1), 2)?
        .add_gate(Gate::H, 2)?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Prints the circuit in UTF-8
    let mut printer = Printer::new(&circuit);
    printer.print_diagram();

    // Un-commenting the line below will print the progress of the simulation
    circuit.toggle_simulation_progress();

    // Simulates the circuit
    circuit.simulate();
    println!("");

    // Displays bin count of the resulting 500 repeat measurements of
    // superpositions. bin_count is a HashMap<ProductState, usize>.
    if let Ok(Measurement::Observable(bin_count)) = circuit.repeat_measurement(500) {
        println!("[Observable] Bin count of observed states.");
        for (state, count) in bin_count {
            println!("|{}> observed {} times", state, count);
        }
    } 

    // Returns the superpsoition that cannot be directly observed.
    if let Ok(Measurement::NonObservable(output_super_position)) = circuit.get_superposition()
    {
        println!("\n[Non-Observable] The amplitudes of each state in the final superposition.");
        for (state, amplitude) in output_super_position.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}
source

pub const fn get_superposition( &self ) -> Result<Measurement<&SuperPosition>, QuantrErrorConst>

👎Deprecated: In the next major update, const will be removed from this function. Therefore, please do not use this function in constant settings.

Returns the resulting superposition after the circuit has been simulated using Circuit::simulate.

This is a non-physical observable, as the superposition would reduce to a single state upon measurement.

§Example
use quantr::{states::SuperPosition, Circuit, Measurement::NonObservable, Gate};

let mut circuit = Circuit::new(3).unwrap();

circuit.add_gate(Gate::H, 2).unwrap();
circuit.add_gate(Gate::Y, 2).unwrap();
circuit.simulate();

println!("State | Amplitude of State");
if let Ok(NonObservable(super_pos)) = circuit.get_superposition() {
    for (state, amplitude) in super_pos.into_iter() {
        println!("|{}>   : {}", state.to_string(), amplitude);
    }
}

// State | Amplitude of State    
// |000> : 0 - 0.71...i     
// |001> : 0 + 0.71...i
Examples found in repository?
examples/qft.rs (line 37)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(3)?;

    // Apply qft
    qc.add_repeating_gate(Gate::X, &[1, 2])?
        .add_gate(Gate::Custom(qft, &[0, 1], "QFT".to_string()), 2)?; // QFT on bits 0, 1 and 2

    let mut printer = Printer::new(&qc);
    printer.print_diagram();

    qc.toggle_simulation_progress();

    qc.simulate();

    if let Ok(Measurement::NonObservable(final_sup)) = qc.get_superposition() {
        println!("\nThe final superposition is:");
        for (state, amplitude) in final_sup.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}

// A QFT implementation that can be used for other circuits. Note, the output is reveresed compared
// to usual conventions; swap gates are needed.
fn qft(input_state: ProductState) -> Option<SuperPosition> {
    let qubit_num = input_state.num_qubits();
    let mut mini_circuit: Circuit = Circuit::new(qubit_num).unwrap();

    for pos in 0..qubit_num {
        mini_circuit.add_gate(Gate::H, pos).unwrap();
        for k in 2..=(qubit_num - pos) {
            mini_circuit
                .add_gate(Gate::CRk(k as i32, pos + k - 1), pos)
                .unwrap();
        }
    }

    mini_circuit
        .change_register(SuperPosition::from(input_state))
        .unwrap()
        .simulate();

    if let Ok(Measurement::NonObservable(super_pos)) = mini_circuit.get_superposition() {
        Some(super_pos.clone())
    } else {
        panic!("No superposition was simualted!");
    }
}
More examples
Hide additional examples
examples/grovers.rs (line 61)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
fn main() -> Result<(), Box<dyn Error>>{
    let mut circuit = Circuit::new(3)?;

    // Kick state into superposition of equal weights
    circuit.add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Oracle
    circuit.add_gate(Gate::CZ(1), 0)?;

    // Amplitude amplification
    circuit
        .add_repeating_gate(Gate::H, &[0, 1, 2])?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::H, 2)?
        .add_gate(Gate::Toffoli(0, 1), 2)?
        .add_gate(Gate::H, 2)?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Prints the circuit in UTF-8
    let mut printer = Printer::new(&circuit);
    printer.print_diagram();

    // Un-commenting the line below will print the progress of the simulation
    circuit.toggle_simulation_progress();

    // Simulates the circuit
    circuit.simulate();
    println!("");

    // Displays bin count of the resulting 500 repeat measurements of
    // superpositions. bin_count is a HashMap<ProductState, usize>.
    if let Ok(Measurement::Observable(bin_count)) = circuit.repeat_measurement(500) {
        println!("[Observable] Bin count of observed states.");
        for (state, count) in bin_count {
            println!("|{}> observed {} times", state, count);
        }
    } 

    // Returns the superpsoition that cannot be directly observed.
    if let Ok(Measurement::NonObservable(output_super_position)) = circuit.get_superposition()
    {
        println!("\n[Non-Observable] The amplitudes of each state in the final superposition.");
        for (state, amplitude) in output_super_position.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}
source

pub fn repeat_measurement( &self, shots: usize ) -> Result<Measurement<HashMap<ProductState, usize>>, QuantrErrorConst>

Returns a HashMap that contains the number of times the corresponding state was observed over n measurements of the superpositions (shots).

Explicitly, this performs repeated measurements where a register is attached to the circuit, the resulting superposition measured in the computational basis, and then the reduced state recorded. If the HashMap does not include a product state, then it was not observed over the n measurements. This method requires that the circuit has already been simulated by calling Circuit::simulate.

§Example
use quantr::{states::SuperPosition, Circuit, Measurement::Observable, Gate};

let mut circuit = Circuit::new(3).unwrap();

circuit.add_gate(Gate::H, 2).unwrap();
circuit.simulate();

// Measures 500 superpositions.
println!("State | Number of Times Observed");
if let Ok(Observable(bin_count)) = circuit.repeat_measurement(500) {
    for (state, observed_count) in bin_count {
        println!("|{}>   : {}", state, observed_count);
    }
}

// State | Number of Times Observed
// |000> : 247
// |001> : 253
Examples found in repository?
examples/generalised_control_not_gate.rs (line 40)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;

    // Multi-controlled gate used here.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2, 3, 4, 5])?
        .add_gate(
            Gate::Custom(multicnot::<CIRCUIT_SIZE>, &[0, 1, 2, 3, 4], "X".to_string()),
            5,
        )?;

    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress();
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
More examples
Hide additional examples
examples/custom_gate.rs (line 36)
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(4)?;

    // Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
    // the target on 3.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::Custom(cccnot, &[0, 1, 2], "X".to_string()), 3)?;

    // Prints the circuit, viewing the custom gate, and then simulating it.
    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress(); // prints the simulation toggle_simulation_progress
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
examples/grovers.rs (line 53)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
fn main() -> Result<(), Box<dyn Error>>{
    let mut circuit = Circuit::new(3)?;

    // Kick state into superposition of equal weights
    circuit.add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Oracle
    circuit.add_gate(Gate::CZ(1), 0)?;

    // Amplitude amplification
    circuit
        .add_repeating_gate(Gate::H, &[0, 1, 2])?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::H, 2)?
        .add_gate(Gate::Toffoli(0, 1), 2)?
        .add_gate(Gate::H, 2)?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Prints the circuit in UTF-8
    let mut printer = Printer::new(&circuit);
    printer.print_diagram();

    // Un-commenting the line below will print the progress of the simulation
    circuit.toggle_simulation_progress();

    // Simulates the circuit
    circuit.simulate();
    println!("");

    // Displays bin count of the resulting 500 repeat measurements of
    // superpositions. bin_count is a HashMap<ProductState, usize>.
    if let Ok(Measurement::Observable(bin_count)) = circuit.repeat_measurement(500) {
        println!("[Observable] Bin count of observed states.");
        for (state, count) in bin_count {
            println!("|{}> observed {} times", state, count);
        }
    } 

    // Returns the superpsoition that cannot be directly observed.
    if let Ok(Measurement::NonObservable(output_super_position)) = circuit.get_superposition()
    {
        println!("\n[Non-Observable] The amplitudes of each state in the final superposition.");
        for (state, amplitude) in output_super_position.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}
source

pub fn change_register( &mut self, super_pos: SuperPosition ) -> Result<&mut Circuit<'a>, QuantrError>

Changes the register which is applied to the circuit when Circuit::simulate is called.

The default register is the |00..0> state. This method can be used before simulating the circuit to change the register. This is primarily helpful in defining custom functions, for example see examples/qft.rs.

§Example
use quantr::{Circuit, Gate};
use quantr::states::{Qubit, ProductState, SuperPosition};

let mut circuit = Circuit::new(2).unwrap();
circuit.add_gate(Gate::X, 1).unwrap();

let register: SuperPosition =
    ProductState::new(&[Qubit::One, Qubit::Zero])
        .unwrap()
        .into();

circuit.change_register(register).unwrap();
circuit.simulate();

// Simulates the circuit:
// |1> -------
// |0> -- X --
Examples found in repository?
examples/qft.rs (line 63)
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
fn qft(input_state: ProductState) -> Option<SuperPosition> {
    let qubit_num = input_state.num_qubits();
    let mut mini_circuit: Circuit = Circuit::new(qubit_num).unwrap();

    for pos in 0..qubit_num {
        mini_circuit.add_gate(Gate::H, pos).unwrap();
        for k in 2..=(qubit_num - pos) {
            mini_circuit
                .add_gate(Gate::CRk(k as i32, pos + k - 1), pos)
                .unwrap();
        }
    }

    mini_circuit
        .change_register(SuperPosition::from(input_state))
        .unwrap()
        .simulate();

    if let Ok(Measurement::NonObservable(super_pos)) = mini_circuit.get_superposition() {
        Some(super_pos.clone())
    } else {
        panic!("No superposition was simualted!");
    }
}
source

pub fn toggle_simulation_progress(&mut self)

Toggles if the circuit should print the progress of simulating each gate.

It will only show the application of non-identity gates. The toggle is set to false by default for a new quantum circuit.

§Example
use quantr::{Circuit, Gate};

let mut circuit = Circuit::new(3).unwrap();
circuit.add_gate(Gate::H, 2).unwrap();

circuit.toggle_simulation_progress();

circuit.simulate(); // Simulates and prints progress.
Examples found in repository?
examples/qft.rs (line 33)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(3)?;

    // Apply qft
    qc.add_repeating_gate(Gate::X, &[1, 2])?
        .add_gate(Gate::Custom(qft, &[0, 1], "QFT".to_string()), 2)?; // QFT on bits 0, 1 and 2

    let mut printer = Printer::new(&qc);
    printer.print_diagram();

    qc.toggle_simulation_progress();

    qc.simulate();

    if let Ok(Measurement::NonObservable(final_sup)) = qc.get_superposition() {
        println!("\nThe final superposition is:");
        for (state, amplitude) in final_sup.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}
More examples
Hide additional examples
examples/generalised_control_not_gate.rs (line 36)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;

    // Multi-controlled gate used here.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2, 3, 4, 5])?
        .add_gate(
            Gate::Custom(multicnot::<CIRCUIT_SIZE>, &[0, 1, 2, 3, 4], "X".to_string()),
            5,
        )?;

    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress();
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
examples/custom_gate.rs (line 32)
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
fn main() -> Result<(), Box<dyn Error>> {
    let mut qc: Circuit = Circuit::new(4)?;

    // Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
    // the target on 3.
    qc.add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::Custom(cccnot, &[0, 1, 2], "X".to_string()), 3)?;

    // Prints the circuit, viewing the custom gate, and then simulating it.
    let mut circuit_printer: Printer = Printer::new(&qc);
    circuit_printer.print_diagram();

    qc.toggle_simulation_progress(); // prints the simulation toggle_simulation_progress
    qc.simulate();

    // Prints the bin count of measured states.
    if let Ok(Measurement::Observable(bin_count)) = qc.repeat_measurement(50) {
        println!("\nStates observed over 50 measurements:");
        for (states, count) in bin_count.into_iter() {
            println!("|{}> : {}", states, count);
        }
    }

    Ok(())
}
examples/grovers.rs (line 45)
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
fn main() -> Result<(), Box<dyn Error>>{
    let mut circuit = Circuit::new(3)?;

    // Kick state into superposition of equal weights
    circuit.add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Oracle
    circuit.add_gate(Gate::CZ(1), 0)?;

    // Amplitude amplification
    circuit
        .add_repeating_gate(Gate::H, &[0, 1, 2])?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_gate(Gate::H, 2)?
        .add_gate(Gate::Toffoli(0, 1), 2)?
        .add_gate(Gate::H, 2)?
        .add_repeating_gate(Gate::X, &[0, 1, 2])?
        .add_repeating_gate(Gate::H, &[0, 1, 2])?;

    // Prints the circuit in UTF-8
    let mut printer = Printer::new(&circuit);
    printer.print_diagram();

    // Un-commenting the line below will print the progress of the simulation
    circuit.toggle_simulation_progress();

    // Simulates the circuit
    circuit.simulate();
    println!("");

    // Displays bin count of the resulting 500 repeat measurements of
    // superpositions. bin_count is a HashMap<ProductState, usize>.
    if let Ok(Measurement::Observable(bin_count)) = circuit.repeat_measurement(500) {
        println!("[Observable] Bin count of observed states.");
        for (state, count) in bin_count {
            println!("|{}> observed {} times", state, count);
        }
    } 

    // Returns the superpsoition that cannot be directly observed.
    if let Ok(Measurement::NonObservable(output_super_position)) = circuit.get_superposition()
    {
        println!("\n[Non-Observable] The amplitudes of each state in the final superposition.");
        for (state, amplitude) in output_super_position.into_iter() {
            println!("|{}> : {}", state, amplitude);
        }
    }

    Ok(())
}

Auto Trait Implementations§

§

impl<'a> Freeze for Circuit<'a>

§

impl<'a> RefUnwindSafe for Circuit<'a>

§

impl<'a> Send for Circuit<'a>

§

impl<'a> Sync for Circuit<'a>

§

impl<'a> Unpin for Circuit<'a>

§

impl<'a> UnwindSafe for Circuit<'a>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.