Circuit

Struct Circuit 

Source
pub struct Circuit { /* private fields */ }
Expand description

A quantum circuit where gates can be appended and then simulated to produce a SimulatedCircuit struct.

Implementations§

Source§

impl Circuit

Source

pub fn new(num_qubits: usize) -> Result<Circuit, QuantrError>

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/post_select.rs (line 18)
17fn main() -> Result<(), QuantrError> {
18    let mut qc = Circuit::new(3)?;
19
20    qc.add_repeating_gate(Gate::H, &[0, 1, 2])?
21        .add_gate(Gate::Custom(post_select, vec![], "P".to_string()), 1)?;
22
23    let mut printer = Printer::new(&qc);
24    printer.print_diagram();
25
26    qc.set_print_progress(true);
27    let simulated_qc = qc.simulate();
28
29    if let Measurement::NonObservable(final_sup) = simulated_qc.get_state() {
30        println!("\nThe final superposition is:");
31        for (state, amplitude) in final_sup.into_iter() {
32            println!("|{}> : {}", state, amplitude);
33        }
34    }
35
36    Ok(())
37}
More examples
Hide additional examples
examples/qft.rs (line 22)
21fn main() -> Result<(), QuantrError> {
22    let mut qc: Circuit = Circuit::new(3)?;
23
24    // Apply qft
25    qc.add_repeating_gate(Gate::X, &[1, 2])?
26        .add_gate(Gate::Custom(qft, vec![0, 1], "QFT".to_string()), 2)?; // QFT on bits 0, 1 and 2
27
28    let mut printer = Printer::new(&qc);
29    printer.print_diagram();
30
31    qc.set_print_progress(true);
32
33    let simulated_circuit = qc.simulate();
34
35    if let Measurement::NonObservable(final_sup) = simulated_circuit.get_state() {
36        println!("\nThe final superposition is:");
37        for (state, amplitude) in final_sup.into_iter() {
38            println!("|{}> : {}", state, amplitude);
39        }
40    }
41
42    Ok(())
43}
44
45// A QFT implementation that can be used for other circuits. Note, the output is reveresed compared
46// to usual conventions; swap gates are needed.
47fn qft(input_state: ProductState) -> Option<SuperPosition> {
48    let qubit_num = input_state.num_qubits();
49    let mut mini_circuit: Circuit = Circuit::new(qubit_num).unwrap();
50
51    for pos in 0..qubit_num {
52        mini_circuit.add_gate(Gate::H, pos).unwrap();
53        for k in 2..=(qubit_num - pos) {
54            mini_circuit
55                .add_gate(Gate::CRk(k as i32, pos + k - 1), pos)
56                .unwrap();
57        }
58    }
59
60    mini_circuit
61        .change_register(SuperPosition::from(input_state))
62        .unwrap();
63
64    Some(mini_circuit.simulate().take_state().take())
65}
examples/generalised_control_not_gate.rs (line 22)
21fn main() -> Result<(), QuantrError> {
22    let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;
23
24    // Multi-controlled gate used here.
25    qc.add_repeating_gate(Gate::X, &[0, 1, 2, 3, 4, 5])?
26        .add_gate(
27            Gate::Custom(
28                multicnot::<CIRCUIT_SIZE>,
29                vec![0, 1, 2, 3, 4],
30                "X".to_string(),
31            ),
32            5,
33        )?;
34
35    let mut circuit_printer: Printer = Printer::new(&qc);
36    circuit_printer.print_diagram();
37
38    qc.set_print_progress(true);
39    let simulated = qc.simulate();
40
41    // Prints the bin count of measured states.
42    if let Measurement::Observable(bin_count) = simulated.measure_all(50) {
43        println!("\nStates observed over 50 measurements:");
44        for (states, count) in bin_count.into_iter() {
45            println!("|{}> : {}", states, count);
46        }
47    }
48
49    Ok(())
50}
examples/custom_gate.rs (line 19)
18fn main() -> Result<(), QuantrError> {
19    let mut qc: Circuit = Circuit::new(4)?;
20
21    // Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
22    // the target on 3.
23    qc.add_repeating_gate(Gate::X, &[0, 1, 2])?
24        .add_gate(Gate::Custom(cccnot, vec![0, 1, 2], "X".to_string()), 3)?;
25
26    // Prints the circuit, viewing the custom gate.
27    let mut circuit_printer: Printer = Printer::new(&qc);
28    circuit_printer.print_diagram();
29
30    // Prints the simulation process of each gate (excluding identity gates).
31    qc.set_print_progress(true);
32    let simulated = qc.simulate();
33
34    // Prints the bin count of measured states.
35    if let Measurement::Observable(bin_count) = simulated.measure_all(50) {
36        println!("\nStates observed over 50 measurements:");
37        for (states, count) in bin_count.into_iter() {
38            println!("|{}> : {}", states, count);
39        }
40    }
41
42    Ok(())
43}
examples/grovers.rs (line 21)
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}
Source

pub fn get_num_qubits(&self) -> usize

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 set_print_progress(&mut self, progress: bool)

Sets whether the simulation progress of the circuit shall be printed to the terminal.

§Example
use quantr::{Circuit};

let mut quantum_circuit = Circuit::new(2).unwrap();
quantum_circuit.set_print_progress(true);
Examples found in repository?
examples/post_select.rs (line 26)
17fn main() -> Result<(), QuantrError> {
18    let mut qc = Circuit::new(3)?;
19
20    qc.add_repeating_gate(Gate::H, &[0, 1, 2])?
21        .add_gate(Gate::Custom(post_select, vec![], "P".to_string()), 1)?;
22
23    let mut printer = Printer::new(&qc);
24    printer.print_diagram();
25
26    qc.set_print_progress(true);
27    let simulated_qc = qc.simulate();
28
29    if let Measurement::NonObservable(final_sup) = simulated_qc.get_state() {
30        println!("\nThe final superposition is:");
31        for (state, amplitude) in final_sup.into_iter() {
32            println!("|{}> : {}", state, amplitude);
33        }
34    }
35
36    Ok(())
37}
More examples
Hide additional examples
examples/qft.rs (line 31)
21fn main() -> Result<(), QuantrError> {
22    let mut qc: Circuit = Circuit::new(3)?;
23
24    // Apply qft
25    qc.add_repeating_gate(Gate::X, &[1, 2])?
26        .add_gate(Gate::Custom(qft, vec![0, 1], "QFT".to_string()), 2)?; // QFT on bits 0, 1 and 2
27
28    let mut printer = Printer::new(&qc);
29    printer.print_diagram();
30
31    qc.set_print_progress(true);
32
33    let simulated_circuit = qc.simulate();
34
35    if let Measurement::NonObservable(final_sup) = simulated_circuit.get_state() {
36        println!("\nThe final superposition is:");
37        for (state, amplitude) in final_sup.into_iter() {
38            println!("|{}> : {}", state, amplitude);
39        }
40    }
41
42    Ok(())
43}
examples/generalised_control_not_gate.rs (line 38)
21fn main() -> Result<(), QuantrError> {
22    let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;
23
24    // Multi-controlled gate used here.
25    qc.add_repeating_gate(Gate::X, &[0, 1, 2, 3, 4, 5])?
26        .add_gate(
27            Gate::Custom(
28                multicnot::<CIRCUIT_SIZE>,
29                vec![0, 1, 2, 3, 4],
30                "X".to_string(),
31            ),
32            5,
33        )?;
34
35    let mut circuit_printer: Printer = Printer::new(&qc);
36    circuit_printer.print_diagram();
37
38    qc.set_print_progress(true);
39    let simulated = qc.simulate();
40
41    // Prints the bin count of measured states.
42    if let Measurement::Observable(bin_count) = simulated.measure_all(50) {
43        println!("\nStates observed over 50 measurements:");
44        for (states, count) in bin_count.into_iter() {
45            println!("|{}> : {}", states, count);
46        }
47    }
48
49    Ok(())
50}
examples/custom_gate.rs (line 31)
18fn main() -> Result<(), QuantrError> {
19    let mut qc: Circuit = Circuit::new(4)?;
20
21    // Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
22    // the target on 3.
23    qc.add_repeating_gate(Gate::X, &[0, 1, 2])?
24        .add_gate(Gate::Custom(cccnot, vec![0, 1, 2], "X".to_string()), 3)?;
25
26    // Prints the circuit, viewing the custom gate.
27    let mut circuit_printer: Printer = Printer::new(&qc);
28    circuit_printer.print_diagram();
29
30    // Prints the simulation process of each gate (excluding identity gates).
31    qc.set_print_progress(true);
32    let simulated = qc.simulate();
33
34    // Prints the bin count of measured states.
35    if let Measurement::Observable(bin_count) = simulated.measure_all(50) {
36        println!("\nStates observed over 50 measurements:");
37        for (states, count) in bin_count.into_iter() {
38            println!("|{}> : {}", states, count);
39        }
40    }
41
42    Ok(())
43}
examples/grovers.rs (line 44)
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}
Source

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

Returns the slice 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, position: usize, ) -> Result<&mut Circuit, 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/post_select.rs (line 21)
17fn main() -> Result<(), QuantrError> {
18    let mut qc = Circuit::new(3)?;
19
20    qc.add_repeating_gate(Gate::H, &[0, 1, 2])?
21        .add_gate(Gate::Custom(post_select, vec![], "P".to_string()), 1)?;
22
23    let mut printer = Printer::new(&qc);
24    printer.print_diagram();
25
26    qc.set_print_progress(true);
27    let simulated_qc = qc.simulate();
28
29    if let Measurement::NonObservable(final_sup) = simulated_qc.get_state() {
30        println!("\nThe final superposition is:");
31        for (state, amplitude) in final_sup.into_iter() {
32            println!("|{}> : {}", state, amplitude);
33        }
34    }
35
36    Ok(())
37}
More examples
Hide additional examples
examples/qft.rs (line 26)
21fn main() -> Result<(), QuantrError> {
22    let mut qc: Circuit = Circuit::new(3)?;
23
24    // Apply qft
25    qc.add_repeating_gate(Gate::X, &[1, 2])?
26        .add_gate(Gate::Custom(qft, vec![0, 1], "QFT".to_string()), 2)?; // QFT on bits 0, 1 and 2
27
28    let mut printer = Printer::new(&qc);
29    printer.print_diagram();
30
31    qc.set_print_progress(true);
32
33    let simulated_circuit = qc.simulate();
34
35    if let Measurement::NonObservable(final_sup) = simulated_circuit.get_state() {
36        println!("\nThe final superposition is:");
37        for (state, amplitude) in final_sup.into_iter() {
38            println!("|{}> : {}", state, amplitude);
39        }
40    }
41
42    Ok(())
43}
44
45// A QFT implementation that can be used for other circuits. Note, the output is reveresed compared
46// to usual conventions; swap gates are needed.
47fn qft(input_state: ProductState) -> Option<SuperPosition> {
48    let qubit_num = input_state.num_qubits();
49    let mut mini_circuit: Circuit = Circuit::new(qubit_num).unwrap();
50
51    for pos in 0..qubit_num {
52        mini_circuit.add_gate(Gate::H, pos).unwrap();
53        for k in 2..=(qubit_num - pos) {
54            mini_circuit
55                .add_gate(Gate::CRk(k as i32, pos + k - 1), pos)
56                .unwrap();
57        }
58    }
59
60    mini_circuit
61        .change_register(SuperPosition::from(input_state))
62        .unwrap();
63
64    Some(mini_circuit.simulate().take_state().take())
65}
examples/generalised_control_not_gate.rs (lines 26-33)
21fn main() -> Result<(), QuantrError> {
22    let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;
23
24    // Multi-controlled gate used here.
25    qc.add_repeating_gate(Gate::X, &[0, 1, 2, 3, 4, 5])?
26        .add_gate(
27            Gate::Custom(
28                multicnot::<CIRCUIT_SIZE>,
29                vec![0, 1, 2, 3, 4],
30                "X".to_string(),
31            ),
32            5,
33        )?;
34
35    let mut circuit_printer: Printer = Printer::new(&qc);
36    circuit_printer.print_diagram();
37
38    qc.set_print_progress(true);
39    let simulated = qc.simulate();
40
41    // Prints the bin count of measured states.
42    if let Measurement::Observable(bin_count) = simulated.measure_all(50) {
43        println!("\nStates observed over 50 measurements:");
44        for (states, count) in bin_count.into_iter() {
45            println!("|{}> : {}", states, count);
46        }
47    }
48
49    Ok(())
50}
examples/custom_gate.rs (line 24)
18fn main() -> Result<(), QuantrError> {
19    let mut qc: Circuit = Circuit::new(4)?;
20
21    // Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
22    // the target on 3.
23    qc.add_repeating_gate(Gate::X, &[0, 1, 2])?
24        .add_gate(Gate::Custom(cccnot, vec![0, 1, 2], "X".to_string()), 3)?;
25
26    // Prints the circuit, viewing the custom gate.
27    let mut circuit_printer: Printer = Printer::new(&qc);
28    circuit_printer.print_diagram();
29
30    // Prints the simulation process of each gate (excluding identity gates).
31    qc.set_print_progress(true);
32    let simulated = qc.simulate();
33
34    // Prints the bin count of measured states.
35    if let Measurement::Observable(bin_count) = simulated.measure_all(50) {
36        println!("\nStates observed over 50 measurements:");
37        for (states, count) in bin_count.into_iter() {
38            println!("|{}> : {}", states, count);
39        }
40    }
41
42    Ok(())
43}
examples/grovers.rs (line 27)
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}
Source

pub fn add_gates_with_positions( &mut self, gates_with_positions: HashMap<usize, Gate>, ) -> Result<&mut Circuit, 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]) -> Result<&mut Circuit, 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, positions: &[usize], ) -> Result<&mut Circuit, 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/post_select.rs (line 20)
17fn main() -> Result<(), QuantrError> {
18    let mut qc = Circuit::new(3)?;
19
20    qc.add_repeating_gate(Gate::H, &[0, 1, 2])?
21        .add_gate(Gate::Custom(post_select, vec![], "P".to_string()), 1)?;
22
23    let mut printer = Printer::new(&qc);
24    printer.print_diagram();
25
26    qc.set_print_progress(true);
27    let simulated_qc = qc.simulate();
28
29    if let Measurement::NonObservable(final_sup) = simulated_qc.get_state() {
30        println!("\nThe final superposition is:");
31        for (state, amplitude) in final_sup.into_iter() {
32            println!("|{}> : {}", state, amplitude);
33        }
34    }
35
36    Ok(())
37}
More examples
Hide additional examples
examples/qft.rs (line 25)
21fn main() -> Result<(), QuantrError> {
22    let mut qc: Circuit = Circuit::new(3)?;
23
24    // Apply qft
25    qc.add_repeating_gate(Gate::X, &[1, 2])?
26        .add_gate(Gate::Custom(qft, vec![0, 1], "QFT".to_string()), 2)?; // QFT on bits 0, 1 and 2
27
28    let mut printer = Printer::new(&qc);
29    printer.print_diagram();
30
31    qc.set_print_progress(true);
32
33    let simulated_circuit = qc.simulate();
34
35    if let Measurement::NonObservable(final_sup) = simulated_circuit.get_state() {
36        println!("\nThe final superposition is:");
37        for (state, amplitude) in final_sup.into_iter() {
38            println!("|{}> : {}", state, amplitude);
39        }
40    }
41
42    Ok(())
43}
examples/generalised_control_not_gate.rs (line 25)
21fn main() -> Result<(), QuantrError> {
22    let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;
23
24    // Multi-controlled gate used here.
25    qc.add_repeating_gate(Gate::X, &[0, 1, 2, 3, 4, 5])?
26        .add_gate(
27            Gate::Custom(
28                multicnot::<CIRCUIT_SIZE>,
29                vec![0, 1, 2, 3, 4],
30                "X".to_string(),
31            ),
32            5,
33        )?;
34
35    let mut circuit_printer: Printer = Printer::new(&qc);
36    circuit_printer.print_diagram();
37
38    qc.set_print_progress(true);
39    let simulated = qc.simulate();
40
41    // Prints the bin count of measured states.
42    if let Measurement::Observable(bin_count) = simulated.measure_all(50) {
43        println!("\nStates observed over 50 measurements:");
44        for (states, count) in bin_count.into_iter() {
45            println!("|{}> : {}", states, count);
46        }
47    }
48
49    Ok(())
50}
examples/custom_gate.rs (line 23)
18fn main() -> Result<(), QuantrError> {
19    let mut qc: Circuit = Circuit::new(4)?;
20
21    // Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
22    // the target on 3.
23    qc.add_repeating_gate(Gate::X, &[0, 1, 2])?
24        .add_gate(Gate::Custom(cccnot, vec![0, 1, 2], "X".to_string()), 3)?;
25
26    // Prints the circuit, viewing the custom gate.
27    let mut circuit_printer: Printer = Printer::new(&qc);
28    circuit_printer.print_diagram();
29
30    // Prints the simulation process of each gate (excluding identity gates).
31    qc.set_print_progress(true);
32    let simulated = qc.simulate();
33
34    // Prints the bin count of measured states.
35    if let Measurement::Observable(bin_count) = simulated.measure_all(50) {
36        println!("\nStates observed over 50 measurements:");
37        for (states, count) in bin_count.into_iter() {
38            println!("|{}> : {}", states, count);
39        }
40    }
41
42    Ok(())
43}
examples/grovers.rs (line 24)
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}
Source

pub fn simulate(self) -> SimulatedCircuit

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

See SimulatedCircuit::get_state and SimulatedCircuit::measure_all for details on obtaining observables from the resulting superposition.

If you are not wanting the circuit to be consumed, please refer to Circuit::clone_and_simulate.

§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/post_select.rs (line 27)
17fn main() -> Result<(), QuantrError> {
18    let mut qc = Circuit::new(3)?;
19
20    qc.add_repeating_gate(Gate::H, &[0, 1, 2])?
21        .add_gate(Gate::Custom(post_select, vec![], "P".to_string()), 1)?;
22
23    let mut printer = Printer::new(&qc);
24    printer.print_diagram();
25
26    qc.set_print_progress(true);
27    let simulated_qc = qc.simulate();
28
29    if let Measurement::NonObservable(final_sup) = simulated_qc.get_state() {
30        println!("\nThe final superposition is:");
31        for (state, amplitude) in final_sup.into_iter() {
32            println!("|{}> : {}", state, amplitude);
33        }
34    }
35
36    Ok(())
37}
More examples
Hide additional examples
examples/qft.rs (line 33)
21fn main() -> Result<(), QuantrError> {
22    let mut qc: Circuit = Circuit::new(3)?;
23
24    // Apply qft
25    qc.add_repeating_gate(Gate::X, &[1, 2])?
26        .add_gate(Gate::Custom(qft, vec![0, 1], "QFT".to_string()), 2)?; // QFT on bits 0, 1 and 2
27
28    let mut printer = Printer::new(&qc);
29    printer.print_diagram();
30
31    qc.set_print_progress(true);
32
33    let simulated_circuit = qc.simulate();
34
35    if let Measurement::NonObservable(final_sup) = simulated_circuit.get_state() {
36        println!("\nThe final superposition is:");
37        for (state, amplitude) in final_sup.into_iter() {
38            println!("|{}> : {}", state, amplitude);
39        }
40    }
41
42    Ok(())
43}
44
45// A QFT implementation that can be used for other circuits. Note, the output is reveresed compared
46// to usual conventions; swap gates are needed.
47fn qft(input_state: ProductState) -> Option<SuperPosition> {
48    let qubit_num = input_state.num_qubits();
49    let mut mini_circuit: Circuit = Circuit::new(qubit_num).unwrap();
50
51    for pos in 0..qubit_num {
52        mini_circuit.add_gate(Gate::H, pos).unwrap();
53        for k in 2..=(qubit_num - pos) {
54            mini_circuit
55                .add_gate(Gate::CRk(k as i32, pos + k - 1), pos)
56                .unwrap();
57        }
58    }
59
60    mini_circuit
61        .change_register(SuperPosition::from(input_state))
62        .unwrap();
63
64    Some(mini_circuit.simulate().take_state().take())
65}
examples/generalised_control_not_gate.rs (line 39)
21fn main() -> Result<(), QuantrError> {
22    let mut qc: Circuit = Circuit::new(CIRCUIT_SIZE)?;
23
24    // Multi-controlled gate used here.
25    qc.add_repeating_gate(Gate::X, &[0, 1, 2, 3, 4, 5])?
26        .add_gate(
27            Gate::Custom(
28                multicnot::<CIRCUIT_SIZE>,
29                vec![0, 1, 2, 3, 4],
30                "X".to_string(),
31            ),
32            5,
33        )?;
34
35    let mut circuit_printer: Printer = Printer::new(&qc);
36    circuit_printer.print_diagram();
37
38    qc.set_print_progress(true);
39    let simulated = qc.simulate();
40
41    // Prints the bin count of measured states.
42    if let Measurement::Observable(bin_count) = simulated.measure_all(50) {
43        println!("\nStates observed over 50 measurements:");
44        for (states, count) in bin_count.into_iter() {
45            println!("|{}> : {}", states, count);
46        }
47    }
48
49    Ok(())
50}
examples/custom_gate.rs (line 32)
18fn main() -> Result<(), QuantrError> {
19    let mut qc: Circuit = Circuit::new(4)?;
20
21    // Build a circuit using a CCC-not gate, placing the control nodes on positions 0, 1, 2 and
22    // the target on 3.
23    qc.add_repeating_gate(Gate::X, &[0, 1, 2])?
24        .add_gate(Gate::Custom(cccnot, vec![0, 1, 2], "X".to_string()), 3)?;
25
26    // Prints the circuit, viewing the custom gate.
27    let mut circuit_printer: Printer = Printer::new(&qc);
28    circuit_printer.print_diagram();
29
30    // Prints the simulation process of each gate (excluding identity gates).
31    qc.set_print_progress(true);
32    let simulated = qc.simulate();
33
34    // Prints the bin count of measured states.
35    if let Measurement::Observable(bin_count) = simulated.measure_all(50) {
36        println!("\nStates observed over 50 measurements:");
37        for (states, count) in bin_count.into_iter() {
38            println!("|{}> : {}", states, count);
39        }
40    }
41
42    Ok(())
43}
examples/grovers.rs (line 47)
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}
Source

pub fn clone_and_simulate(&self) -> SimulatedCircuit

Attaches the register, |0…0>, to the circuit resulting in a superposition that can be measured, and will clone the contents of the register. This will duplicate the register, and so could lead to large memeory consumption for circuits with many qubits.

See SimulatedCircuit::get_state and SimulatedCircuit::measure_all for details on obtaining observables from the resulting superposition.

If you are wanting the circuit to be consumed, please refer to Circuit::simulate.

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

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

let simulated_with_H = circuit.clone_and_simulate();

// Below would be impossible if Circuit::simulate was used instead
let simulated_with_H_and_X = circuit.add_gate(Gate::X, 1);
Source

pub fn change_register( &mut self, super_pos: SuperPosition, ) -> Result<&mut Circuit, 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 61)
47fn qft(input_state: ProductState) -> Option<SuperPosition> {
48    let qubit_num = input_state.num_qubits();
49    let mut mini_circuit: Circuit = Circuit::new(qubit_num).unwrap();
50
51    for pos in 0..qubit_num {
52        mini_circuit.add_gate(Gate::H, pos).unwrap();
53        for k in 2..=(qubit_num - pos) {
54            mini_circuit
55                .add_gate(Gate::CRk(k as i32, pos + k - 1), pos)
56                .unwrap();
57        }
58    }
59
60    mini_circuit
61        .change_register(SuperPosition::from(input_state))
62        .unwrap();
63
64    Some(mini_circuit.simulate().take_state().take())
65}

Auto Trait Implementations§

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>,

Source§

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>,

Source§

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.