use crate::core::{
context::Context, individual::Individual, offspring::Offspring, population::Population,
state::State,
};
use crate::operators::GeneticOperator;
use crate::operators::sequential::mutation::creep::CreepMutate;
use rand::{Rng, RngExt, SeedableRng};
use super::GeneCollection;
#[derive(Debug, Clone, Copy)]
pub struct Creep<T> {
step: T,
min: Option<T>,
max: Option<T>,
}
impl<T> Creep<T> {
pub fn new(step: T) -> Self {
Self { step, min: None, max: None }
}
pub fn min(mut self, min: T) -> Self {
self.min = Some(min);
self
}
pub fn max(mut self, max: T) -> Self {
self.max = Some(max);
self
}
}
impl<G, F, R, Fe, T, C> GeneticOperator<G, F, Fe, R, C> for Creep<T>
where
G: Clone + AsMut<[T]> + GeneCollection + Send + Sync,
T: CreepMutate + Ord + Send + Sync,
F: Send,
R: Rng + SeedableRng,
Fe: Sync,
C: Sync,
Individual<G, F>: Sync,
{
fn apply(&self, state: &State<G, F>, ctx: &mut Context<Fe, R, C>) -> Offspring<G, F> {
let individuals = state.population().as_slice();
let step = self.step;
let min = self.min;
let max = self.max;
let inputs: vecpool::PoolVec<(u64, usize)> = (0..individuals.len())
.map(|i| (ctx.rng().random::<u64>(), i))
.collect();
let results = ctx.pool().map(&inputs, |(seed, idx)| {
let mut rng = R::seed_from_u64(*seed);
let mut genome = individuals[*idx].genome().clone();
let genes = genome.as_mut();
let gene_idx = rng.random_range(0..genes.len());
genes[gene_idx] = genes[gene_idx].creep(step, &mut rng);
if let Some(lo) = min { genes[gene_idx] = std::cmp::max(genes[gene_idx], lo); }
if let Some(hi) = max { genes[gene_idx] = std::cmp::min(genes[gene_idx], hi); }
Individual::new(genome)
});
let mut population = Population::with_capacity(individuals.len());
for r in results {
population.add(r.expect("pool task panicked"));
}
Offspring::Multiple(population)
}
}