use crate::chromosomes::Range as RangeChromosome;
use crate::traits::ChromosomeT;
use rand::distr::uniform::SampleUniform;
use rand::Rng;
use std::borrow::Cow;
use std::fmt::Debug;
pub fn creep_mutation<T>(individual: &mut RangeChromosome<T>, step: T)
where
T: Sync
+ Send
+ Clone
+ Default
+ Debug
+ PartialOrd
+ SampleUniform
+ Copy
+ 'static
+ std::ops::Add<Output = T>
+ std::ops::Sub<Output = T>,
{
let len = individual.dna().len();
if len == 0 {
return;
}
let mut rng = crate::rng::make_rng();
let idx = rng.random_range(0..len);
let mut dna = individual.dna().to_vec();
let mut gene = dna[idx].clone();
if gene.ranges.is_empty() {
return;
}
let range_idx = rng.random_range(0..gene.ranges.len());
let (lo, hi) = gene.ranges[range_idx];
let current = gene.value;
let perturb_lo = if current - step > lo {
current - step
} else {
lo
};
let perturb_hi = if current + step < hi {
current + step
} else {
hi
};
let new_val = rng.random_range(perturb_lo..=perturb_hi);
gene.value = new_val;
dna[idx] = gene;
individual.set_dna(Cow::Owned(dna));
}