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
impl Circuit
Sourcepub fn new(num_qubits: usize) -> Result<Circuit, QuantrError>
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?
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
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}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}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}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}Sourcepub fn get_num_qubits(&self) -> usize
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);Sourcepub fn set_print_progress(&mut self, progress: bool)
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?
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
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}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}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}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}Sourcepub fn get_gates(&self) -> &[Gate]
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]);Sourcepub fn add_gate(
&mut self,
gate: Gate,
position: usize,
) -> Result<&mut Circuit, QuantrError>
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?
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
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}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}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}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}Sourcepub fn add_gates_with_positions(
&mut self,
gates_with_positions: HashMap<usize, Gate>,
) -> Result<&mut Circuit, QuantrError>
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 --Sourcepub fn add_gates(&mut self, gates: &[Gate]) -> Result<&mut Circuit, QuantrError>
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 --Sourcepub fn add_repeating_gate(
&mut self,
gate: Gate,
positions: &[usize],
) -> Result<&mut Circuit, QuantrError>
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?
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
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}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}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}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}Sourcepub fn simulate(self) -> SimulatedCircuit
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?
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
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}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}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}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}Sourcepub fn clone_and_simulate(&self) -> SimulatedCircuit
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);Sourcepub fn change_register(
&mut self,
super_pos: SuperPosition,
) -> Result<&mut Circuit, QuantrError>
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?
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}