flow-gate-core 0.1.0

Pure-Rust implementation of the ISAC Gating-ML 2.0 gate evaluation engine — transforms, gates, and event matrices
Documentation
use std::fmt::{Debug, Display, Formatter};
use std::sync::Arc;

use bitvec::{order::Lsb0, vec::BitVec as InnerBitVec};

use crate::error::FlowGateError;
use crate::event::EventMatrix;
use crate::gate::GateRegistry;

#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ParameterName(pub Arc<str>);

impl ParameterName {
    pub fn new(name: impl AsRef<str>) -> Self {
        Self(Arc::<str>::from(name.as_ref()))
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl Display for ParameterName {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_str(self.as_str())
    }
}

impl From<&str> for ParameterName {
    fn from(value: &str) -> Self {
        Self::new(value)
    }
}

impl From<String> for ParameterName {
    fn from(value: String) -> Self {
        Self(Arc::<str>::from(value))
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct GateId(pub Arc<str>);

impl GateId {
    pub fn new(id: impl AsRef<str>) -> Self {
        Self(Arc::<str>::from(id.as_ref()))
    }

    pub fn as_str(&self) -> &str {
        &self.0
    }
}

impl Display for GateId {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_str(self.as_str())
    }
}

impl From<&str> for GateId {
    fn from(value: &str) -> Self {
        Self::new(value)
    }
}

impl From<String> for GateId {
    fn from(value: String) -> Self {
        Self(Arc::<str>::from(value))
    }
}

pub type BitVec = InnerBitVec<u64, Lsb0>;

pub trait Transform: Send + Sync + Clone + Debug {
    fn apply(&self, value: f64) -> f64;
    fn invert(&self, scaled: f64) -> f64;

    fn apply_batch(&self, values: &[f64], out: &mut [f64]) {
        debug_assert_eq!(values.len(), out.len());
        values
            .iter()
            .zip(out.iter_mut())
            .for_each(|(&v, o)| *o = self.apply(v));
    }

    fn transform_id(&self) -> &str;
}

pub trait Gate: Send + Sync + Debug {
    fn dimensions(&self) -> &[ParameterName];
    fn contains(&self, coords: &[f64]) -> bool;
    fn gate_id(&self) -> &GateId;
    fn parent_id(&self) -> Option<&GateId>;
}

pub trait ApplyGate: Gate {
    /// Classify events in the matrix against this gate.
    /// Returns a `BitVec` where each bit indicates whether the corresponding
    /// event is inside the gate.
    fn classify(
        &self,
        matrix: &EventMatrix,
        gate_map: &GateRegistry,
    ) -> Result<BitVec, FlowGateError>;
}