use ndarray::ArrayViewMut1;
use crate::{operators::MutationOperator, random::RandomGenerator};
#[derive(Debug, Clone)]
pub struct BitFlipMutation {
pub gene_mutation_rate: f64,
}
impl BitFlipMutation {
#[allow(dead_code)]
pub fn new(gene_mutation_rate: f64) -> Self {
Self { gene_mutation_rate }
}
}
impl MutationOperator for BitFlipMutation {
fn mutate<'a>(&self, mut individual: ArrayViewMut1<'a, f64>, rng: &mut impl RandomGenerator) {
for gene in individual.iter_mut() {
if rng.gen_bool(self.gene_mutation_rate) {
*gene = if *gene == 0.0 { 1.0 } else { 0.0 };
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::random::{RandomGenerator, TestDummyRng};
use ndarray::array;
struct FakeRandomGeneratorTrue {
dummy: TestDummyRng,
}
impl FakeRandomGeneratorTrue {
fn new() -> Self {
Self {
dummy: TestDummyRng,
}
}
}
impl RandomGenerator for FakeRandomGeneratorTrue {
type R = TestDummyRng;
fn rng(&mut self) -> &mut TestDummyRng {
&mut self.dummy
}
fn gen_bool(&mut self, _p: f64) -> bool {
true
}
}
#[test]
fn test_bit_flip_mutation_controlled() {
let mut pop = array![[0.0, 0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0, 1.0]];
let mutation_operator = BitFlipMutation::new(1.0);
let mut rng = FakeRandomGeneratorTrue::new();
mutation_operator.operate(&mut pop, 1.0, &mut rng);
let expected_pop = array![[1.0, 1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0, 0.0]];
assert_eq!(expected_pop, pop);
}
}