Skip to content

Commit

Permalink
More refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
ciaranra committed Jan 30, 2025
1 parent cc01c9b commit c0b6208
Show file tree
Hide file tree
Showing 31 changed files with 476 additions and 2,146 deletions.
1,999 changes: 77 additions & 1,922 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ parking_lot = "0.12.3"
serde_json = "1.0.137"
num-complex = "0.4"
num-traits = "0.2"
regex = "1"
tempfile = "3"
criterion = "0.5"

pecos-core = { version = "0.1.1", path = "crates/pecos-core" }
pecos-noise = { version = "0.1.1", path = "crates/pecos-noise" }
Expand Down
4 changes: 1 addition & 3 deletions crates/benchmarks/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ categories.workspace = true
publish = false

[dev-dependencies]
criterion = "0.5"
criterion = { workspace = true }
pecos = { workspace = true }
pecos-core = { workspace = true }
pecos-qsim = { workspace = true }
pecos-qec = { workspace = true }

[[bench]]
name = "benchmarks"
Expand Down
2 changes: 1 addition & 1 deletion crates/benchmarks/benches/modules/element_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// the License.

use criterion::{black_box, measurement::Measurement, BenchmarkGroup, Criterion};
use pecos_core::IndexableElement;
use pecos::prelude::*;

pub fn benchmarks<M: Measurement>(c: &mut Criterion<M>) {
let mut group = c.benchmark_group("Element Operations");
Expand Down
2 changes: 1 addition & 1 deletion crates/benchmarks/benches/modules/set_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// the License.

use criterion::{black_box, measurement::Measurement, BenchmarkGroup, Criterion};
use pecos_core::{IndexableElement, Set, VecSet};
use pecos::prelude::*;

pub fn benchmarks<M: Measurement>(c: &mut Criterion<M>) {
let mut group = c.benchmark_group("Set Operations");
Expand Down
6 changes: 1 addition & 5 deletions crates/pecos-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ pecos = { workspace = true }
clap = { workspace = true }
log = { workspace = true }
env_logger = { workspace = true }
serde_json = "1"

[dev-dependencies]
assert_cmd = "2"
predicates = "3"
serde_json = { workspace = true }

[lints]
workspace = true
3 changes: 1 addition & 2 deletions crates/pecos-core/src/angle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use num_traits::{
Bounded, FromPrimitive, PrimInt, ToPrimitive, Unsigned, WrappingAdd, WrappingMul, WrappingNeg,
WrappingSub, Zero,
};
pub use parse::ParseAngleError;
use std::fmt;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, Sub, SubAssign};

Expand All @@ -38,8 +39,6 @@ pub type Angle8 = Angle<u8>;
#[allow(clippy::module_name_repetitions)]
pub type Angle16 = Angle<u16>;

pub use parse::ParseAngleError;

/// Alias for `Angle` with a 32-bit unsigned integer.
#[allow(clippy::module_name_repetitions)]
pub type Angle32 = Angle<u32>;
Expand Down
1 change: 0 additions & 1 deletion crates/pecos-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ pub use sets::vec_set::VecSet;
pub use crate::sims_rngs::chacha_rng::{ChaCha12Rng, ChaCha20Rng, ChaCha8Rng};
pub use crate::sims_rngs::choices::Choices;
pub use crate::sims_rngs::cyclic_rng::{CyclicRng, CyclicSeed};
// pub use crate::sims_rngs::mock_rng::MockRng;
pub use crate::sims_rngs::sim_rng::SimRng;
pub use crate::sims_rngs::xoshiro_rng::{
Xoshiro128PlusPlus, Xoshiro128StarStar, Xoshiro256PlusPlus, Xoshiro256StarStar,
Expand Down
1 change: 0 additions & 1 deletion crates/pecos-core/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ pub struct ShotResult {

// For communication
pub type CommandBatch = Vec<QuantumCommand>;
pub type MeasurementResult = u32;

// Statistics
#[derive(Debug)]
Expand Down
2 changes: 1 addition & 1 deletion crates/pecos-engines/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ os_pipe = { workspace = true }
lazy_static = { workspace = true }
parking_lot = { workspace = true }
serde_json = { workspace = true }
tempfile = "3"
tempfile = { workspace = true }

pecos-core = { workspace = true }
pecos-noise = { workspace = true }
Expand Down
31 changes: 28 additions & 3 deletions crates/pecos-engines/src/channels.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
// PECOS/crates/pecos-engines/src/channels.rs
use crate::errors::QueueError;
use pecos_core::types::{CommandBatch, MeasurementResult};
use pecos_core::types::CommandBatch;

pub trait CommandChannel: Send + Sync {
/// Sends a batch of quantum commands to the channel for processing.
///
/// # Parameters
/// - `cmds`: A batch of quantum commands to be sent.
///
/// # Errors
/// This function returns a `QueueError` if:
/// - There is an error locking the queue.
/// - The operation fails for any reason.
/// - An error occurs during serialization of the commands.
fn send_commands(&mut self, cmds: CommandBatch) -> Result<(), QueueError>;
/// Flushes any remaining commands in the channel, ensuring they are processed.
///
/// # Errors
/// This function returns a `QueueError` if:
/// - There is an error locking the queue.
/// - The flush operation fails for any reason.
fn flush(&mut self) -> Result<(), QueueError>;
}

pub trait MeasurementChannel: Send + Sync {
fn receive_measurement(&mut self) -> Result<MeasurementResult, QueueError>;
pub type Message = u32;

pub trait MessageChannel: Send + Sync {
/// Receives a message from the channel.
///
/// # Errors
/// This function returns a `QueueError` if:
/// - There is an error locking the queue.
/// - The operation fails for any reason.
/// - An error occurs during deserialization of the message.
fn receive_message(&mut self) -> Result<Message, QueueError>;
}

pub mod stdio;
Expand Down
8 changes: 4 additions & 4 deletions crates/pecos-engines/src/channels/shared_memory.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// PECOS/crates/pecos-engines/src/channels/shared_memory.rs
use super::{CommandChannel, MeasurementChannel};
use super::{CommandChannel, Message, MessageChannel};
use crate::errors::QueueError;
use memmap2::MmapMut;
use pecos_core::types::{CommandBatch, MeasurementResult};
use pecos_core::types::CommandBatch;
use std::fs::OpenOptions;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
Expand Down Expand Up @@ -61,8 +61,8 @@ impl CommandChannel for SharedMemoryChannel {
}
}

impl MeasurementChannel for SharedMemoryChannel {
fn receive_measurement(&mut self) -> Result<MeasurementResult, QueueError> {
impl MessageChannel for SharedMemoryChannel {
fn receive_message(&mut self) -> Result<Message, QueueError> {
let mmap = self.mmap.lock();
let read_pos = self.read_pos.load(Ordering::SeqCst) as usize;

Expand Down
41 changes: 37 additions & 4 deletions crates/pecos-engines/src/channels/stdio.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// PECOS/crates/pecos-engines/src/channels/stdio.rs
use super::{CommandChannel, MeasurementChannel};
use super::{CommandChannel, Message, MessageChannel};
use crate::errors::QueueError;
use log::trace;
use pecos_core::types::{CommandBatch, MeasurementResult, QuantumCommand};
use pecos_core::types::{CommandBatch, QuantumCommand};
use std::io::{self, BufRead, BufReader, BufWriter, Write};
use std::sync::{Arc, Mutex};

Expand Down Expand Up @@ -43,6 +43,23 @@ impl StdioChannel {
}

impl CommandChannel for StdioChannel {
/// Sends a batch of commands through the channel.
///
/// This function writes the commands to the writer, formatting them into a
/// specific protocol. The procedure includes:
/// - Writing "FLUSH_BEGIN" before the commands.
/// - Writing each command in the form "CMD <formatted_command>".
/// - Writing "FLUSH_END" after all commands.
///
/// The function ensures that the data is flushed to the writer before returning.
///
/// # Parameters
/// - `cmds`: A batch of quantum commands to be sent.
///
/// # Errors
/// This function returns a `QueueError` if:
/// - The writer cannot be locked.
/// - There is an I/O error while writing the commands or flushing the writer.
fn send_commands(&mut self, cmds: CommandBatch) -> Result<(), QueueError> {
let mut writer = self
.writer
Expand All @@ -62,6 +79,12 @@ impl CommandChannel for StdioChannel {
Ok(())
}

/// Flushes any remaining data in the writer, ensuring it is written out.
///
/// # Errors
/// This function returns a `QueueError` if:
/// - There is an error locking the writer.
/// - The flush operation fails for any reason.
fn flush(&mut self) -> Result<(), QueueError> {
let mut writer = self
.writer
Expand All @@ -72,8 +95,18 @@ impl CommandChannel for StdioChannel {
}
}

impl MeasurementChannel for StdioChannel {
fn receive_measurement(&mut self) -> Result<MeasurementResult, QueueError> {
impl MessageChannel for StdioChannel {
/// Receives a message (measurement) from the channel.
///
/// This method tries to read a line of input, parses it into a `Message` (u32),
/// and returns the result.
///
/// # Errors
/// This function returns a `QueueError` if:
/// - There is an error locking the reader.
/// - The operation fails to read a line from the reader.
/// - The parsed measurement is invalid (not a valid `u32`).
fn receive_message(&mut self) -> Result<Message, QueueError> {
let mut reader = self
.reader
.lock()
Expand Down
41 changes: 4 additions & 37 deletions crates/pecos-engines/src/engines.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,8 @@
mod classical;
pub mod hybrid;
pub mod phir_engine;
pub mod quantum;

pub use crate::channels::{CommandChannel, MeasurementChannel};
pub use crate::errors::QueueError;
use parking_lot::RwLock;
pub use pecos_core::types::{CommandBatch, MeasurementResult, QuantumCommand, ShotResult};
use pecos_noise::noise::NoiseModel;
use std::sync::Arc;

/// Classical engine that processes programs and handles measurements
pub trait ClassicalEngine: Send + Sync {
fn process_program(&mut self) -> Result<CommandBatch, QueueError>;
fn handle_measurement(&mut self, measurement: MeasurementResult) -> Result<(), QueueError>;
fn get_results(&self) -> Result<ShotResult, QueueError>;
fn compile(&self) -> Result<(), Box<dyn std::error::Error>>;
}

/// Quantum engine that processes commands and generates measurements
pub trait QuantumEngine: Send + Sync {
fn process_command(
&mut self,
cmd: &QuantumCommand,
) -> Result<Option<MeasurementResult>, QueueError>;

fn reset_state(&mut self) -> Result<(), QueueError>;
}

// Base implementation of Hybrid Engine
pub struct HybridEngine<C, M>
where
C: CommandChannel + Send + Sync + 'static,
M: MeasurementChannel + Send + Sync + 'static,
{
classical: Arc<RwLock<Box<dyn ClassicalEngine>>>,
quantum: Arc<RwLock<Box<dyn QuantumEngine>>>,
cmd_channel: Arc<RwLock<C>>,
meas_channel: Arc<RwLock<M>>,
noise_model: Arc<RwLock<Option<Box<dyn NoiseModel>>>>,
}
pub use classical::ClassicalEngine;
pub use hybrid::HybridEngine;
pub use quantum::QuantumEngine;
11 changes: 11 additions & 0 deletions crates/pecos-engines/src/engines/classical.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use crate::channels::Message;
use crate::errors::QueueError;
use pecos_core::types::{CommandBatch, ShotResult};

/// Classical engine that processes programs and handles measurements
pub trait ClassicalEngine: Send + Sync {
fn process_program(&mut self) -> Result<CommandBatch, QueueError>;
fn handle_measurement(&mut self, measurement: Message) -> Result<(), QueueError>;
fn get_results(&self) -> Result<ShotResult, QueueError>;
fn compile(&self) -> Result<(), Box<dyn std::error::Error>>;
}
23 changes: 18 additions & 5 deletions crates/pecos-engines/src/engines/hybrid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,29 @@ use rayon::prelude::*;
use std::collections::HashMap;
use std::sync::Arc;

use super::{ClassicalEngine, HybridEngine, QuantumEngine};
use crate::channels::{CommandChannel, MeasurementChannel};
use super::{ClassicalEngine, QuantumEngine};
use crate::channels::{CommandChannel, MessageChannel};
use crate::errors::QueueError;
use pecos_core::types::{GateType, MeasurementStatistics, QubitStats, ShotResult, ShotResults};
use pecos_noise::noise::NoiseModel;
use pecos_noise::NoiseModel;

// Base implementation of Hybrid Engine
pub struct HybridEngine<C, M>
where
C: CommandChannel + Send + Sync + 'static,
M: MessageChannel + Send + Sync + 'static,
{
classical: Arc<RwLock<Box<dyn ClassicalEngine>>>,
quantum: Arc<RwLock<Box<dyn QuantumEngine>>>,
cmd_channel: Arc<RwLock<C>>,
meas_channel: Arc<RwLock<M>>,
noise_model: Arc<RwLock<Option<Box<dyn NoiseModel>>>>,
}

impl<C, M> HybridEngine<C, M>
where
C: CommandChannel + Send + Sync + 'static + Clone,
M: MeasurementChannel + Send + Sync + 'static + Clone,
M: MessageChannel + Send + Sync + 'static + Clone,
{
pub fn new(
classical: Box<dyn ClassicalEngine>,
Expand Down Expand Up @@ -44,7 +57,7 @@ where
self.cmd_channel.write().send_commands(commands)?;

// Process measurements
let measurement = self.meas_channel.write().receive_measurement()?;
let measurement = self.meas_channel.write().receive_message()?;
self.classical.write().handle_measurement(measurement)?;

// Get final results
Expand Down
5 changes: 3 additions & 2 deletions crates/pecos-engines/src/engines/phir_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use std::collections::HashMap;
use std::path::Path;

use super::ClassicalEngine;
use crate::channels::Message;
use crate::errors::QueueError;
use pecos_core::types::{CommandBatch, GateType, MeasurementResult, QuantumCommand, ShotResult};
use pecos_core::types::{CommandBatch, GateType, QuantumCommand, ShotResult};

#[derive(Debug, Deserialize)]
struct PHIRProgram {
Expand Down Expand Up @@ -377,7 +378,7 @@ impl ClassicalEngine for PHIREngine {
}
}

fn handle_measurement(&mut self, measurement: MeasurementResult) -> Result<(), QueueError> {
fn handle_measurement(&mut self, measurement: Message) -> Result<(), QueueError> {
let result_id = self.measurement_results.len();
self.measurement_results
.insert(format!("measurement_{result_id}"), vec![measurement]);
Expand Down
Loading

0 comments on commit c0b6208

Please sign in to comment.