diff --git a/qip/examples/bell_inequalities.rs b/qip/examples/bell_inequalities.rs new file mode 100644 index 0000000..ece8841 --- /dev/null +++ b/qip/examples/bell_inequalities.rs @@ -0,0 +1,108 @@ +use qip::builder::StochasticMeasurementHandle; +#[cfg(feature = "macros")] +use qip::prelude::*; +#[cfg(feature = "macros")] +use qip::prelude::{CircuitBuilder, CircuitError}; +#[cfg(feature = "macros")] +use qip_macros::*; +#[cfg(feature = "macros")] +use qip::macros::program_ops::*; +use std::num::NonZeroUsize; + +#[cfg(feature = "macros")] +fn circuit1() -> &'static [f64]{ + let mut b = LocalBuilder::::default(); + let n = NonZeroUsize::new(2).unwrap(); + + let q = b.qubit(); + let r1 = b.register(n); + let r = program!(&mut b; r1; + not r; + h r[0]; + control not r[0], r[1]; + rz(std::f64::consts::FRAC_PI_3) r[1]; + h r; + ).unwrap(); + let (r, m_handle) = b.measure_stochastic(r); + + //run and get probabilities + let (r, m_handle) = b.measure_stochastic(r); //returns (Self::Register, Self::StochasticMeasurementHandle) + let (_, measurements) = b.calculate_state(); + let stochastic_measurement_probability = measurements.get_stochastic_measurement(m_handle); + return stochastic_measurement_probability; +} + +#[cfg(feature = "macros")] +fn circuit2() -> &'static [f64]{ + let mut b = LocalBuilder::::default(); + let n = NonZeroUsize::new(2).unwrap(); + + let r2 = b.register(n); + let r = program!( &mut b; r2; + not r; + h r[0]; + control not r[0], r[1]; + rz(2. * std::f64::consts::FRAC_PI_3) r[1]; + h r; + ).unwrap(); + let (r, m_handle) = b.measure_stochastic(r); + + // run and get probabilities + let (r, m_handle) = b.measure_stochastic(r); //returns (Self::Register, Self::StochasticMeasurementHandle) + let (_, measurements) = b.calculate_state(); + let stochastic_measurement_probability = measurements.get_stochastic_measurement(m_handle); + return stochastic_measurement_probability; +} +#[cfg(feature = "macros")] +fn circuit3() -> &'static [f64] { + let mut b = LocalBuilder::::default(); + let n = NonZeroUsize::new(2).unwrap(); + let r3 = b.register(n); + + let r = program!(&mut b; r3; + not r; + h r[0]; + control not r[0], r[1]; + rz(std::f64::consts::FRAC_PI_3) r[0]; + rz(2. * std::f64::consts::FRAC_PI_3) r[1]; + h r; + ).unwrap(); + let (r, m_handle) = b.measure_stochastic(r); //returns (Self::Register, Self::StochasticMeasurementHandle) + let (_, measurements) = b.calculate_state(); + let stochastic_measurement_probability = measurements.get_stochastic_measurement(m_handle); + return stochastic_measurement_probability; + +} + +#[cfg(not(feature = "macros"))] +fn main() -> () {} + + + +#[cfg(feature = "macros")] +fn main() -> Result<(), CircuitError> { + println!("Bell inequality: |P(a, b) - P(a, c)| - P(b, c) <= 1"); + + let a_b = circuit1(); + let p_of_a_b = (a_b[0] + a_b[3]) - (a_b[1] + a_b[2]); + println!("P(a, b) = {:.2}", p_of_a_b); + + let a_c = circuit2(); + let p_of_a_c = (a_c[0] + a_c[3]) - (a_c[1] + a_c[2]); + println!("P(a, c) = {:.2}", p_of_a_c); + + let b_c = circuit3(); + println!("{:?}", b_c); + let p_of_b_c = (b_c[0] + b_c[3]) - (b_c[1] + b_c[2]); + println!("P(b, c) = {:.2}", p_of_b_c); + + let left_side = (p_of_a_b - p_of_a_c).abs() - p_of_b_c; + println!( + "|{:.2} - {:.2}| - ({:.2}) = {:.2} IS NOT <= 1", + p_of_a_b, p_of_a_c, p_of_b_c, left_side + ); + + assert!(left_side > 1.0); + + Ok(()) +} diff --git a/qip/examples/cswap.rs b/qip/examples/cswap.rs new file mode 100644 index 0000000..d15e273 --- /dev/null +++ b/qip/examples/cswap.rs @@ -0,0 +1,27 @@ +use qip::prelude::*; +use std::num::NonZeroUsize; + +fn main() -> Result<(), CircuitError> { + let mut b = LocalBuilder::::default(); + let n = NonZeroUsize::new(3).unwrap(); + + let q = b.qubit(); + let ra = b.register(n); + let rb = b.register(n); + + let q = b.h(q); + + let mut cb = b.condition_with(q); + let (ra, rb) = cb.swap(ra, rb).unwrap(); + let q = cb.dissolve(); + + let q = b.h(q); + + let (q, m_handle) = b.measure(q); + + let (_, measured) = b.calculate_state_with_init([(&ra, 0b000), (&rb, 0b001)]); + let (result, p) = measured.get_measurement(m_handle); + println!("Measured: {:?} (with chance {:?})", result, p); + + Ok(()) +} diff --git a/qip/examples/dense_coding.rs b/qip/examples/dense_coding.rs new file mode 100644 index 0000000..d69bc5e --- /dev/null +++ b/qip/examples/dense_coding.rs @@ -0,0 +1,70 @@ +use qip::builder::Qudit; +use qip::prelude::*; +use std::num::NonZeroUsize; + +/// Encode the two classical bits Alice wants to communicate to Bob. +/// +/// Depending on the classical bits combination a different gate is applied: +/// 00: Do nothing (or apply Identity gate) +/// 01: Apply Pauli-X gate +/// 10: Apply Pauli-Z gate +/// 11: Apply Pauli-Y gate (or apply Pauli-Z gate followed by a Pauli-X gate) +/// +/// Returns Alice qubit with applied gate. +/// +/// https://en.wikipedia.org/wiki/Superdense_coding#Encoding +fn run_alice>( + b: &mut CB, + epr_alice: CB::Register, + bit_a: bool, + bit_b: bool, +) -> CB::Register { + match (bit_a, bit_b) { + (false, false) => epr_alice, + (false, true) => b.x(epr_alice), + (true, false) => b.z(epr_alice), + (true, true) => b.y(epr_alice), + } +} + +/// Decode the message Alice transmitted to Bob. +/// +/// Bob applies the restoration operation on his qubit and the one transmitted +/// by Alice to decode the original message. After restoration: +/// |00>: 00 +/// |10>: 10 +/// |01>: 01 +/// |11>: 11 +/// +/// Returns a pair of classical bits. +/// +/// https://en.wikipedia.org/wiki/Superdense_coding#Decoding +fn run_bob(b: &mut LocalBuilder

, r_alice: Qudit, epr_bob: Qudit) -> (bool, bool) { + let (r_alice, r_bob) = b.cnot(r_alice, epr_bob).unwrap(); + let r_alice = b.h(r_alice); + let r = b.merge_two_registers(r_bob, r_alice); + let (r, m) = b.measure(r); + let (_, measurements) = b.calculate_state(); + let (m, _) = measurements.get_measurement(m); + ((m & 2) == 2, (m & 1) == 1) +} + +fn main() { + let n = NonZeroUsize::new(1).unwrap(); + let bits_a = vec![true, false, true, false]; + let bits_b = vec![true, true, false, false]; + + for (bit_a, bit_b) in bits_a.into_iter().zip(bits_b.into_iter()) { + let mut b = LocalBuilder::::default(); + let epr_alice = b.register(n); + let epr_bob = b.register(n); + + let r_alice = run_alice(&mut b, epr_alice, bit_a, bit_b); + let (bob_a, bob_b) = run_bob(&mut b, r_alice, epr_bob); + + println!( + "Alice: ({:?},{:?}) \tBob: ({:?}, {:?})", + bit_a, bit_b, bob_a, bob_b + ); + } +}