From 5f058c9b67e0f96e0dd89bbeff0afe8e08bde25b Mon Sep 17 00:00:00 2001 From: hachem Date: Fri, 18 Oct 2024 09:34:36 +0200 Subject: Allow named registers and tiny refactor --- libpsi-core/src/core/circuit.rs | 40 ++------ libpsi-core/src/core/classical_components.rs | 63 ++++++++++++ libpsi-core/src/core/component.rs | 147 --------------------------- libpsi-core/src/core/gates.rs | 10 +- libpsi-core/src/core/mod.rs | 8 +- libpsi-core/src/core/quantum_components.rs | 145 ++++++++++++++++++++++++++ libpsi-core/src/core/runtime.rs | 22 ---- libpsi-core/src/lib.rs | 7 +- libpsi-core/src/runtimes/basic_rt.rs | 39 ------- libpsi-core/src/runtimes/mod.rs | 3 - 10 files changed, 229 insertions(+), 255 deletions(-) create mode 100644 libpsi-core/src/core/classical_components.rs delete mode 100644 libpsi-core/src/core/component.rs create mode 100644 libpsi-core/src/core/quantum_components.rs delete mode 100644 libpsi-core/src/core/runtime.rs delete mode 100644 libpsi-core/src/runtimes/basic_rt.rs delete mode 100644 libpsi-core/src/runtimes/mod.rs (limited to 'libpsi-core/src') diff --git a/libpsi-core/src/core/circuit.rs b/libpsi-core/src/core/circuit.rs index 4d9d286..27c106d 100644 --- a/libpsi-core/src/core/circuit.rs +++ b/libpsi-core/src/core/circuit.rs @@ -1,39 +1,19 @@ -use super::{ClassicalRegister, QuantumGate, QuantumRegister}; - -#[derive(Clone)] -pub enum Instruction<'a> { - ApplyGate(&'a QuantumGate, &'a [usize], usize), - Measure(usize), -} +use super::{ClassicalRegister, QuantumRegister}; +#[allow(unused)] pub struct QuantumCircuit<'a> { - quantum_register: QuantumRegister, - classical_register: ClassicalRegister, - instructions: Vec>, + quantum_registers: &'a [QuantumRegister<'a>], + classical_registers: &'a [ClassicalRegister<'a>], } impl<'a> QuantumCircuit<'a> { - pub fn new(quantum_bit_count: usize, classical_bit_count: usize) -> QuantumCircuit<'a> { + pub fn new( + quantum_registers: &'a [QuantumRegister<'a>], + classical_registers: &'a [ClassicalRegister<'a>], + ) -> QuantumCircuit<'a> { QuantumCircuit { - quantum_register: QuantumRegister::new(quantum_bit_count), - classical_register: ClassicalRegister::new(classical_bit_count), - instructions: Vec::new(), + quantum_registers, + classical_registers, } } - - pub fn execute(&mut self, instruction: Instruction<'a>) { - self.instructions.push(instruction); - } - - pub fn get_quantum_register(&self) -> QuantumRegister { - self.quantum_register.clone() - } - - pub fn get_classical_registers(&self) -> ClassicalRegister { - self.classical_register.clone() - } - - pub fn get_instructions(&self) -> Vec { - self.instructions.clone() - } } diff --git a/libpsi-core/src/core/classical_components.rs b/libpsi-core/src/core/classical_components.rs new file mode 100644 index 0000000..6710e9d --- /dev/null +++ b/libpsi-core/src/core/classical_components.rs @@ -0,0 +1,63 @@ +use core::ops; + +#[derive(Clone, Copy)] +pub struct ClassicalBit<'a> { + state: bool, + name: &'a str, +} + +#[derive(Clone)] +pub struct ClassicalRegister<'a> { + bits: Vec>, + name: &'a str, +} + +impl<'a> ClassicalBit<'a> { + pub fn new(name: &'a str, state: bool) -> ClassicalBit { + ClassicalBit { name, state } + } + + pub fn get_name(&self) -> &'a str { + self.name + } + + pub fn get_state(&self) -> bool { + self.state + } +} + +impl<'a> ClassicalRegister<'a> { + pub fn new(name: &'a str, names: &'a [&'a str]) -> ClassicalRegister<'a> { + let mut bits: Vec> = Vec::new(); + for i in 0..names.len() { + bits.push(ClassicalBit::new(names[i], false)); + } + ClassicalRegister { name, bits } + } + + pub fn set_bits(&mut self, bits: Vec>) { + self.bits = bits; + } + + pub fn get_bits(&self) -> Vec> { + self.bits.clone() + } + + pub fn get_name(&self) -> &'a str { + self.name + } +} + +impl<'a> ops::Index for ClassicalRegister<'a> { + type Output = ClassicalBit<'a>; + + fn index(&self, index: usize) -> &Self::Output { + &self.bits[index] + } +} + +impl<'a> ops::IndexMut for ClassicalRegister<'a> { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.bits[index] + } +} diff --git a/libpsi-core/src/core/component.rs b/libpsi-core/src/core/component.rs deleted file mode 100644 index 7748ac5..0000000 --- a/libpsi-core/src/core/component.rs +++ /dev/null @@ -1,147 +0,0 @@ -use crate::{complex, ColumnVector, Complex, Matrix, Vector, VectorMatrix}; -use core::{fmt, ops}; - -pub type QuantumState = ColumnVector>; -pub type QuantumBit = QuantumState; - -#[derive(Clone)] -pub struct QuantumGate { - pub name: &'static str, - pub matrix: Matrix>, -} - -#[derive(Clone)] -pub struct ClassicalRegister { - bits: Vec, -} - -#[derive(Clone)] -pub struct QuantumRegister { - state_vector: QuantumState, - qubits: Vec, -} - -#[macro_export] -macro_rules! count { - () => { 0 }; - ($head:expr $(,$tail:expr)*) => { 1 + count!($( $tail ),*) }; -} - -#[macro_export] -macro_rules! qubit { - ($(($re:expr, $im:expr)),*) => { - { - let mut vector = Vec::new(); - $( - vector.push(complex!($re, $im)); - )* - QuantumBit::new(vector) - } - }; -} - -#[macro_export] -macro_rules! quantum_register { - ($($bit:expr),*) => { - { - const N: usize = count!($($bit),*); - let mut bits: [QuantumBit; N] = [$($bit),*]; - QuantumRegister::from(&mut bits) - } - }; -} - -impl QuantumBit { - 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 fmt::Display for QuantumGate { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.name) - } -} - -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; - } - - pub fn get_bits(&self) -> Vec { - self.bits.clone() - } -} - -impl QuantumRegister { - 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..] { - new_result = new_result.kronecker(matrix); - } - - self.state_vector = ColumnVector::from_matrix(&new_result); - } - - pub fn new(count: usize) -> QuantumRegister { - QuantumRegister::from(&mut vec![QuantumBit::state_0(); count]) - } - - pub fn from(bits: &mut [QuantumBit]) -> QuantumRegister { - let mut register = QuantumRegister { - qubits: bits.to_vec(), - state_vector: ColumnVector::new(vec![]), - }; - - register.update(); - register - } - - pub fn get_bits(&self) -> Vec { - self.qubits.clone() - } - - pub fn get_state(&self) -> QuantumState { - self.state_vector.clone() - } -} - -impl ops::Index for QuantumRegister { - type Output = QuantumBit; - - fn index(&self, index: usize) -> &Self::Output { - &self.qubits[index] - } -} - -impl ops::IndexMut for QuantumRegister { - fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &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-core/src/core/gates.rs b/libpsi-core/src/core/gates.rs index 97254fc..854313d 100644 --- a/libpsi-core/src/core/gates.rs +++ b/libpsi-core/src/core/gates.rs @@ -2,32 +2,32 @@ use crate::{complex, matrix, QuantumGate}; #[rustfmt::skip] lazy_static::lazy_static! { - pub static ref HADAMARD: QuantumGate = QuantumGate { + pub static ref HADAMARD: QuantumGate<'static> = QuantumGate { name: "H", matrix: 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 PAULI_X: QuantumGate = QuantumGate { + pub static ref PAULI_X: QuantumGate<'static> = QuantumGate { name: "Pauli-X", matrix: 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_Y: QuantumGate = QuantumGate { + pub static ref PAULI_Y: QuantumGate<'static> = QuantumGate { name: "Pauli-Y", matrix: 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_Z: QuantumGate = QuantumGate { + pub static ref PAULI_Z: QuantumGate<'static> = QuantumGate { name: "Pauli-Z", matrix: matrix!([complex!(1.0, 0.0), complex!( 0.0, 0.0)]; [complex!(0.0, 0.0), complex!(-1.0, 0.0)]) }; - pub static ref CNOT: QuantumGate = QuantumGate { + pub static ref CNOT: QuantumGate<'static> = QuantumGate { name: "CNOT", matrix: 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)]; diff --git a/libpsi-core/src/core/mod.rs b/libpsi-core/src/core/mod.rs index e8e2a4b..6936487 100644 --- a/libpsi-core/src/core/mod.rs +++ b/libpsi-core/src/core/mod.rs @@ -1,9 +1,9 @@ pub mod circuit; -pub mod component; +pub mod classical_components; pub mod gates; -pub mod runtime; +pub mod quantum_components; pub use circuit::*; -pub use component::*; +pub use classical_components::*; pub use gates::*; -pub use runtime::*; +pub use quantum_components::*; diff --git a/libpsi-core/src/core/quantum_components.rs b/libpsi-core/src/core/quantum_components.rs new file mode 100644 index 0000000..e6931a0 --- /dev/null +++ b/libpsi-core/src/core/quantum_components.rs @@ -0,0 +1,145 @@ +use crate::{column_vector, complex, ColumnVector, Complex, Matrix, Vector, VectorMatrix}; +use core::{fmt, ops}; + +// TODO(Hachem): Redo these macros to work with the new function definition. +#[macro_export] +macro_rules! count { + () => { 0 }; + ($head:expr $(,$tail:expr)*) => { 1 + count!($( $tail ),*) }; +} + +#[macro_export] +macro_rules! qubit { + ($(($re:expr, $im:expr)),*) => { + { + let mut vector = Vec::new(); + $( + vector.push(complex!($re, $im)); + )* + QuantumBit::new(vector) + } + }; +} + +#[macro_export] +macro_rules! quantum_register { + ($($bit:expr),*) => { + { + const N: usize = count!($($bit),*); + let mut bits: [QuantumBit; N] = [$($bit),*]; + QuantumRegister::from(&mut bits) + } + }; +} + +pub type QuantumState = ColumnVector>; +impl QuantumState { + pub fn state_0() -> QuantumState { + column_vector![complex!(1.0, 0.0), complex!(0.0, 0.0)] + } + + pub fn state_1() -> QuantumState { + column_vector![complex!(0.0, 0.0), complex!(1.0, 0.0)] + } +} + +#[derive(Clone)] +pub struct QuantumBit<'a> { + state: QuantumState, + name: &'a str, +} + +#[derive(Clone)] +pub struct QuantumRegister<'a> { + state_vector: QuantumState, + name: &'a str, + qubits: Vec>, +} + +#[derive(Clone)] +pub struct QuantumGate<'a> { + pub name: &'a str, + pub matrix: Matrix>, +} + +impl<'a> QuantumBit<'a> { + pub fn new(name: &'a str, state: QuantumState) -> QuantumBit<'a> { + QuantumBit { name, state } + } + + pub fn get_state(&self) -> QuantumState { + self.state.clone() + } + + pub fn get_name(&self) -> &'a str { + self.name + } +} + +impl<'a> QuantumRegister<'a> { + pub fn new(name: &'a str, names: &[&'a str]) -> QuantumRegister<'a> { + let mut bits: Vec> = Vec::new(); + for i in 0..names.len() { + bits.push(QuantumBit::new(names[i], QuantumState::state_0())) + } + + QuantumRegister::from(name, &mut bits) + } + + pub fn from(name: &'a str, bits: &mut [QuantumBit<'a>]) -> QuantumRegister<'a> { + let mut register = QuantumRegister { + name, + qubits: bits.to_vec(), + state_vector: ColumnVector::new(vec![]), + }; + + register.update(); + register + } + + fn update(&mut self) { + let matrices: Vec>> = self + .qubits + .iter() + .map(|qubit| qubit.state.to_matrix()) + .collect(); + let mut new_result = matrices[0].clone(); + for matrix in &matrices[1..] { + new_result = new_result.kronecker(matrix); + } + + self.state_vector = ColumnVector::from_matrix(&new_result); + } + + pub fn get_bits(&self) -> Vec { + self.qubits.clone() + } + + pub fn get_state(&self) -> QuantumState { + self.state_vector.clone() + } + + pub fn get_name(&self) -> &'a str { + self.name + } +} + +impl<'a> ops::Index for QuantumRegister<'a> { + type Output = QuantumBit<'a>; + + fn index(&self, index: usize) -> &Self::Output { + &self.qubits[index] + } +} + +impl<'a> ops::IndexMut for QuantumRegister<'a> { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.qubits[index] + } +} + +impl<'a> fmt::Display for QuantumGate<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.name) + } +} diff --git a/libpsi-core/src/core/runtime.rs b/libpsi-core/src/core/runtime.rs deleted file mode 100644 index f3e52ac..0000000 --- a/libpsi-core/src/core/runtime.rs +++ /dev/null @@ -1,22 +0,0 @@ -use super::{ClassicalRegister, QuantumCircuit, QuantumRegister, QuantumState}; - -pub struct RuntimeData { - pub quantum_register: QuantumRegister, - pub classical_states: ClassicalRegister, -} - -impl RuntimeData { - pub fn new(quantum_register: QuantumRegister, classical_states: ClassicalRegister) -> Self { - RuntimeData { - quantum_register, - classical_states, - } - } -} - -pub trait Runtime<'a> { - fn new(circuit: &'a QuantumCircuit) -> Self; - fn execute(&self, repeat: usize) -> Vec; - fn get_state(&self) -> QuantumState; - fn get_circuit(&self) -> &QuantumCircuit; -} diff --git a/libpsi-core/src/lib.rs b/libpsi-core/src/lib.rs index 91b853e..81c9fe2 100644 --- a/libpsi-core/src/lib.rs +++ b/libpsi-core/src/lib.rs @@ -1,6 +1,5 @@ pub mod core; pub mod maths; -pub mod runtimes; pub use maths::complex::*; pub use maths::matrix::*; @@ -8,8 +7,6 @@ pub use maths::numeric::*; pub use maths::vector::*; pub use core::circuit::*; -pub use core::component::*; +pub use core::classical_components::*; pub use core::gates; -pub use core::runtime::*; - -pub use runtimes::*; +pub use core::quantum_components::*; diff --git a/libpsi-core/src/runtimes/basic_rt.rs b/libpsi-core/src/runtimes/basic_rt.rs deleted file mode 100644 index b8c412f..0000000 --- a/libpsi-core/src/runtimes/basic_rt.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::{Instruction, QuantumCircuit, QuantumState, Runtime, RuntimeData}; - -pub struct BasicRT<'a> { - circuit: &'a QuantumCircuit<'a>, -} - -impl<'a> Runtime<'a> for BasicRT<'a> { - fn new(circuit: &'a QuantumCircuit) -> BasicRT<'a> { - BasicRT { circuit } - } - - fn execute(&self, repeat: usize) -> Vec { - let mut result: Vec = Vec::with_capacity(repeat); - for _ in 0..repeat { - let executation_data = RuntimeData::new( - self.circuit.get_quantum_register(), - self.circuit.get_classical_registers(), - ); - - for instruction in self.circuit.get_instructions() { - match instruction { - Instruction::ApplyGate(_gate, _control_bits, _target) => print!(""), - Instruction::Measure(_bit) => print!(""), - } - } - - result.push(executation_data); - } - result - } - - fn get_state(&self) -> QuantumState { - todo!() - } - - fn get_circuit(&self) -> &QuantumCircuit { - &self.circuit - } -} diff --git a/libpsi-core/src/runtimes/mod.rs b/libpsi-core/src/runtimes/mod.rs deleted file mode 100644 index 4c2030c..0000000 --- a/libpsi-core/src/runtimes/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod basic_rt; - -pub use basic_rt::*; -- cgit v1.3