use ndarray::{Array2, ArrayViewMut1, Axis};
use crate::random::RandomGenerator;
mod bitflip;
mod displacement;
mod gaussian;
mod inversion;
mod scramble;
mod swap;
mod uniform;
pub use bitflip::BitFlipMutation;
pub use displacement::DisplacementMutation;
pub use gaussian::GaussianMutation;
pub use inversion::InversionMutation;
pub use scramble::ScrambleMutation;
pub use swap::SwapMutation;
pub use uniform::{UniformBinaryMutation, UniformRealMutation};
pub trait MutationOperator {
fn mutate<'a>(&self, individual: ArrayViewMut1<'a, f64>, rng: &mut impl RandomGenerator);
fn select_individuals_for_mutation(
&self,
population_size: usize,
mutation_rate: f64,
rng: &mut impl RandomGenerator,
) -> Vec<bool> {
(0..population_size)
.map(|_| rng.gen_bool(mutation_rate))
.collect()
}
fn operate(
&self,
population: &mut Array2<f64>,
mutation_rate: f64,
rng: &mut impl RandomGenerator,
) {
let population_size = population.len_of(Axis(0));
let mask: Vec<bool> =
self.select_individuals_for_mutation(population_size, mutation_rate, rng);
for (i, mut individual) in population.outer_iter_mut().enumerate() {
if mask[i] {
self.mutate(individual.view_mut(), rng);
}
}
}
}