use nalgebra::SVector; use rand::{distr::Distribution, Rng}; use rand_distr::{Normal, NormalError}; use crate::binary_string::BinaryString; pub trait PerturbationOperator { type Chromosome; fn perturb(self: &mut Self, chromosome: &Self::Chromosome) -> Self::Chromosome; } pub struct BinaryStringBitPerturbation { rng: TRng, p: f64, } impl BinaryStringBitPerturbation { pub fn new(p: f64) -> Self { Self { rng: rand::rng(), p } } } impl PerturbationOperator for BinaryStringBitPerturbation { type Chromosome = BinaryString; fn perturb(self: &mut Self, chromosome: &Self::Chromosome) -> Self::Chromosome { chromosome.perturb(&mut self.rng, self.p) } } pub struct RandomDistributionPerturbation> { distribution: TDistribution, rng: TRng } impl RandomDistributionPerturbation> { pub fn normal(variance: f64) -> Result { Ok(Self { distribution: Normal::new(0.0, variance)?, rng: rand::rng() }) } } impl, const LEN: usize> PerturbationOperator for RandomDistributionPerturbation { type Chromosome = SVector; fn perturb(self: &mut Self, chromosome: &Self::Chromosome) -> Self::Chromosome { chromosome + Self::Chromosome::zeros().map(|_| self.distribution.sample(&mut self.rng)) } } #[cfg(test)] pub mod tests { use crate::binary_string::BinaryString; #[test] fn test_perturb() { let mut rng = rand::rng(); assert_eq!( *BinaryString::new(vec![1, 1, 0, 0]) .perturb(&mut rng, 1.0) .vec(), vec![0, 0, 1, 1] ); assert_eq!( *BinaryString::new(vec![1, 1, 0, 0]) .perturb(&mut rng, 0.0) .vec(), vec![1, 1, 0, 0] ); } }