From 57ea5b058d5038e1cdbffbc9b518d8717b1b7ba9 Mon Sep 17 00:00:00 2001 From: hachem Date: Sun, 22 Sep 2024 18:57:25 +0200 Subject: More gates and fix bugs --- libpsi-tester/src/main.rs | 22 ++++++++++- libpsi/src/core/component.rs | 91 ++++++++++++++++++++++++++++++++++++-------- libpsi/src/core/gates.rs | 26 ++++++------- libpsi/src/core/mod.rs | 2 + libpsi/src/lib.rs | 5 ++- libpsi/src/maths/vector.rs | 3 -- 6 files changed, 115 insertions(+), 34 deletions(-) diff --git a/libpsi-tester/src/main.rs b/libpsi-tester/src/main.rs index f328e4d..08229f2 100644 --- a/libpsi-tester/src/main.rs +++ b/libpsi-tester/src/main.rs @@ -1 +1,21 @@ -fn main() {} +use libpsi::*; + +fn main() { + let mut quantum_register = quantum_register![QuantumBit::state_0()]; + let mut classical_register = ClassicalRegister::new(1); + + quantum_register.measure(&mut classical_register); + println!("|{}>", classical_register[0]); + + quantum_register.apply(&gates::HADAMARD, 0); + quantum_register.measure(&mut classical_register); + println!("|{}>", classical_register[0]); + + quantum_register.apply(&gates::HADAMARD, 0); + quantum_register.measure(&mut classical_register); + println!("|{}>", classical_register[0]); + + quantum_register.apply(&gates::HADAMARD, 0); + quantum_register.measure(&mut classical_register); + println!("|{}>", classical_register[0]); +} diff --git a/libpsi/src/core/component.rs b/libpsi/src/core/component.rs index 51e0551..331021f 100644 --- a/libpsi/src/core/component.rs +++ b/libpsi/src/core/component.rs @@ -1,14 +1,9 @@ -use crate::{ColumnVector, Complex, Matrix, VectorMatrix}; +use crate::{complex, ColumnVector, Complex, Matrix, Vector, VectorMatrix}; use std::ops; pub type QuantumBit = ColumnVector>; pub type QuantumGate = Matrix>; -pub struct QuantumRegister { - state: ColumnVector>, - qubits: Vec, -} - #[macro_export] macro_rules! count { () => { 0 }; @@ -39,29 +34,81 @@ macro_rules! quantum_register { }; } +pub struct ClassicalRegister { + bits: Vec, +} + +pub struct QuantumRegister { + state: ColumnVector>, + qubits: Vec, +} + impl QuantumBit { - pub fn get_state(&self) -> i32 { - (self[1] != Complex::new(0.0, 0.0)) as i32 + pub fn measure(&self) -> i32 { + let alpha_abs = self[0].abs(); + let beta_abs = self[1].abs(); + + let alpha_norm = alpha_abs * alpha_abs; + let beta_norm = beta_abs * beta_abs; + + if alpha_norm > beta_norm { + 0 + } else { + 1 + } + } + + pub fn state_0() -> QuantumBit { + QuantumBit::new(vec![complex!(1.0, 0.0), complex!(0.0, 0.0)]) + } + + pub fn state_1() -> QuantumBit { + QuantumBit::new(vec![complex!(0.0, 0.0), complex!(1.0, 0.0)]) + } +} + +impl ClassicalRegister { + pub fn new(count: usize) -> ClassicalRegister { + ClassicalRegister { + bits: Vec::with_capacity(count), + } + } + + pub fn set_bits(&mut self, bits: Vec) { + self.bits = bits; } } impl QuantumRegister { - pub fn from(bits: &mut [QuantumBit]) -> QuantumRegister { - let matrices: Vec>> = bits.iter().map(|bit| bit.to_matrix()).collect(); - let mut result = matrices[0].clone(); + fn update(&mut self) { + let matrices: Vec>> = + self.qubits.iter().map(|qubit| qubit.to_matrix()).collect(); + let mut new_result = matrices[0].clone(); for matrix in &matrices[1..] { - result = result.kronecker(matrix); + new_result = new_result.kronecker(matrix); } - QuantumRegister { + self.state = ColumnVector::from_matrix(&new_result); + } + + pub fn from(bits: &mut [QuantumBit]) -> QuantumRegister { + let mut register = QuantumRegister { qubits: bits.to_vec(), - state: ColumnVector::from_matrix(&result), - } + state: ColumnVector::new(vec![]), + }; + + register.update(); + register + } + + pub fn measure(&self, classical_register: &mut ClassicalRegister) { + classical_register.set_bits(self.qubits.iter().map(|qubit| qubit.measure()).collect()); } pub fn apply(&mut self, gate: &QuantumGate, index: usize) { let result: ColumnVector> = self.state.mul_matrix(gate).unwrap(); self.qubits[index] = result; + self.update(); } } @@ -78,3 +125,17 @@ impl ops::IndexMut for QuantumRegister { &mut self.qubits[index] } } + +impl ops::Index for ClassicalRegister { + type Output = i32; + + fn index(&self, index: usize) -> &Self::Output { + &self.bits[index] + } +} + +impl ops::IndexMut for ClassicalRegister { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.bits[index] + } +} diff --git a/libpsi/src/core/gates.rs b/libpsi/src/core/gates.rs index 227df9a..e9077ad 100644 --- a/libpsi/src/core/gates.rs +++ b/libpsi/src/core/gates.rs @@ -2,21 +2,21 @@ use crate::{complex, matrix, QuantumGate}; #[rustfmt::skip] lazy_static::lazy_static! { - static ref HADAMARD: QuantumGate = matrix!([complex!(1.0, 0.0), complex!( 1.0, 0.0)]; - [complex!(1.0, 0.0), complex!(-1.0, 0.0)]) * - complex!(1.0/2.0_f64.sqrt(), 0.0); + pub static ref HADAMARD: QuantumGate = matrix!([complex!(1.0, 0.0), complex!( 1.0, 0.0)]; + [complex!(1.0, 0.0), complex!(-1.0, 0.0)]) * + complex!(1.0/2.0_f64.sqrt(), 0.0); - static ref PAULI_X: QuantumGate = matrix!([complex!(0.0, 0.0), complex!(1.0, 0.0)]; - [complex!(1.0, 0.0), complex!(0.0, 0.0)]); + pub static ref PAULI_X: QuantumGate = matrix!([complex!(0.0, 0.0), complex!(1.0, 0.0)]; + [complex!(1.0, 0.0), complex!(0.0, 0.0)]); - static ref PAULI_Y: QuantumGate = matrix!([complex!(0.0, 0.0), complex!(0.0, -1.0)]; - [complex!(0.0, 1.0), complex!(0.0, 0.0)]); + pub static ref PAULI_Y: QuantumGate = matrix!([complex!(0.0, 0.0), complex!(0.0, -1.0)]; + [complex!(0.0, 1.0), complex!(0.0, 0.0)]); - static ref PAULI_Z: QuantumGate = matrix!([complex!(1.0, 0.0), complex!( 0.0, 0.0)]; - [complex!(0.0, 0.0), complex!(-1.0, 0.0)]); + pub static ref PAULI_Z: QuantumGate = matrix!([complex!(1.0, 0.0), complex!( 0.0, 0.0)]; + [complex!(0.0, 0.0), complex!(-1.0, 0.0)]); - static ref CNOT: QuantumGate = matrix!([complex!(1.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0)]; - [complex!(0.0, 0.0), complex!(1.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0)]; - [complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(1.0, 0.0)]; - [complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(1.0, 0.0), complex!(0.0, 0.0)]); + pub static ref CNOT: QuantumGate = matrix!([complex!(1.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0)]; + [complex!(0.0, 0.0), complex!(1.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0)]; + [complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(1.0, 0.0)]; + [complex!(0.0, 0.0), complex!(0.0, 0.0), complex!(1.0, 0.0), complex!(0.0, 0.0)]); } diff --git a/libpsi/src/core/mod.rs b/libpsi/src/core/mod.rs index 86ddfaa..374c555 100644 --- a/libpsi/src/core/mod.rs +++ b/libpsi/src/core/mod.rs @@ -1,2 +1,4 @@ pub mod component; pub mod gates; + +pub use gates::*; diff --git a/libpsi/src/lib.rs b/libpsi/src/lib.rs index 1d0d125..af50663 100644 --- a/libpsi/src/lib.rs +++ b/libpsi/src/lib.rs @@ -1,5 +1,5 @@ -mod core; -mod maths; +pub mod core; +pub mod maths; pub use maths::complex::*; pub use maths::matrix::*; @@ -7,3 +7,4 @@ pub use maths::numeric_traits::*; pub use maths::vector::*; pub use core::component::*; +pub use core::gates; diff --git a/libpsi/src/maths/vector.rs b/libpsi/src/maths/vector.rs index a21cf36..07ff7fb 100644 --- a/libpsi/src/maths/vector.rs +++ b/libpsi/src/maths/vector.rs @@ -1,6 +1,3 @@ -// TODO(Hachem): Operators Matrix/Vector don't work -// TODO(Hachem): Refactor - use super::{Float, Matrix}; use core::{fmt, ops}; -- cgit v1.3