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>
impl<'a> Circuit<'a>
sourcepub 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.
pub const fn new(num_qubits: usize) -> Result<Circuit<'a>, QuantrErrorConst>
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?
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
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(())
}
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(())
}
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(())
}
sourcepub 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.
pub const 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 get_toggle_progress(&self) -> bool
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);
sourcepub fn get_gates(&self) -> &[Gate<'a>]
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]);
sourcepub fn add_gate(
&mut self,
gate: Gate<'a>,
position: usize
) -> Result<&mut Circuit<'a>, QuantrError>
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?
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
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(())
}
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(())
}
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(())
}
sourcepub fn add_gates_with_positions(
&mut self,
gates_with_positions: HashMap<usize, Gate<'a>>
) -> Result<&mut Circuit<'a>, QuantrError>
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 --
sourcepub fn add_gates(
&mut self,
gates: &[Gate<'a>]
) -> Result<&mut Circuit<'a>, QuantrError>
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 --
sourcepub fn add_repeating_gate(
&mut self,
gate: Gate<'a>,
positions: &[usize]
) -> Result<&mut Circuit<'a>, QuantrError>
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?
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
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(())
}
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(())
}
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(())
}
sourcepub fn simulate(&mut self)
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?
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
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(())
}
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(())
}
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(())
}
sourcepub 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.
pub const fn get_superposition( &self ) -> Result<Measurement<&SuperPosition>, QuantrErrorConst>
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?
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
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(())
}
sourcepub fn repeat_measurement(
&self,
shots: usize
) -> Result<Measurement<HashMap<ProductState, usize>>, QuantrErrorConst>
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?
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
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(())
}
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(())
}
sourcepub fn change_register(
&mut self,
super_pos: SuperPosition
) -> Result<&mut Circuit<'a>, QuantrError>
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?
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!");
}
}
sourcepub fn toggle_simulation_progress(&mut self)
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?
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
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(())
}
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(())
}
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(())
}