use crate::{operators::MutationOperator, random::RandomGenerator};
use ndarray::ArrayViewMut1;
#[derive(Debug, Clone)]
pub struct UniformBinaryMutation {
pub gene_mutation_rate: f64,
}
impl UniformBinaryMutation {
pub fn new(gene_mutation_rate: f64) -> Self {
Self { gene_mutation_rate }
}
}
impl MutationOperator for UniformBinaryMutation {
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 rng.gen_bool(0.5) { 1.0 } else { 0.0 };
}
}
}
}
#[derive(Debug, Clone)]
pub struct UniformRealMutation {
pub gene_mutation_rate: f64,
pub lower: f64,
pub upper: f64,
}
impl UniformRealMutation {
pub fn new(gene_mutation_rate: f64, lower: f64, upper: f64) -> Self {
Self {
gene_mutation_rate,
lower,
upper,
}
}
}
impl MutationOperator for UniformRealMutation {
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) {
let u: f64 = rng.gen_range_f64(self.lower, self.upper);
*gene = u;
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::random::{RandomGenerator, TestDummyRng};
use ndarray::array;
struct FakeUniformRng {
dummy: TestDummyRng,
step: usize,
}
impl FakeUniformRng {
fn new() -> Self {
Self {
dummy: TestDummyRng,
step: 0,
}
}
}
impl RandomGenerator for FakeUniformRng {
type R = TestDummyRng;
fn rng(&mut self) -> &mut TestDummyRng {
&mut self.dummy
}
fn gen_bool(&mut self, _p: f64) -> bool {
let out = match self.step {
0 | 2 => true,
1 => true, _ => false, };
self.step += 1;
out
}
}
#[test]
fn test_uniform_mutation() {
let mut pop = array![[0.0, 1.0, 0.0, 0.0]];
let op = UniformBinaryMutation::new(1.0);
let mut rng = FakeUniformRng::new();
op.mutate(pop.row_mut(0), &mut rng);
assert_eq!(pop.row(0), array![1.0, 0.0, 0.0, 0.0]);
}
struct FakeRandomGeneratorReal {
dummy: TestDummyRng,
values: Vec<f64>,
idx: usize,
}
impl FakeRandomGeneratorReal {
fn new(values: Vec<f64>) -> Self {
Self {
dummy: TestDummyRng,
values,
idx: 0,
}
}
}
impl RandomGenerator for FakeRandomGeneratorReal {
type R = TestDummyRng;
fn rng(&mut self) -> &mut TestDummyRng {
&mut self.dummy
}
fn gen_bool(&mut self, _p: f64) -> bool {
true
}
fn gen_range_f64(&mut self, _low: f64, _high: f64) -> f64 {
let v = self.values[self.idx];
self.idx += 1;
v
}
}
#[test]
fn test_uniform_real_mutation_controlled() {
let mut pop = array![[2.0, -1.0, 0.5]];
let op = UniformRealMutation::new(1.0, -2.0, 3.0);
let mut rng = FakeRandomGeneratorReal::new(vec![0.0, 3.0, -2.0]);
op.mutate(pop.row_mut(0), &mut rng);
let expected = array![0.0, 3.0, -2.0];
assert_eq!(expected, pop.row(0));
}
}