radiate_alters/mutators/
gaussian.rs1use radiate_core::{
2 AlterContext, AlterResult, BoundedGene, Chromosome, FloatGene, Gene, Mutate, Rate, Valid,
3 random_provider,
4};
5use radiate_utils::{Float, Primitive};
6
7#[derive(Debug, Clone)]
11pub struct GaussianMutator {
12 rate: Rate,
13}
14
15impl GaussianMutator {
16 pub fn new(rate: impl Into<Rate>) -> Self {
19 let rate = rate.into();
20
21 if !rate.is_valid() {
22 panic!("Rate is not valid: {:?}", rate);
23 }
24
25 GaussianMutator { rate }
26 }
27}
28
29impl<F, C> Mutate<C> for GaussianMutator
30where
31 F: Float + Primitive,
32 C: Chromosome<Gene = FloatGene<F>>,
33{
34 fn rate(&self) -> Rate {
35 self.rate.clone()
36 }
37
38 #[inline]
39 fn mutate_chromosome(&mut self, chromosome: &mut C, ctx: &mut AlterContext) -> AlterResult {
40 let mut count = 0;
41
42 random_provider::with_rng(|rand| {
43 for gene in chromosome.as_mut_slice() {
44 if rand.bool(ctx.rate()) {
45 let min = gene.min().extract::<f64>().unwrap();
49 let max = gene.max().extract::<f64>().unwrap();
50
51 let std_dev = (max - min) * 0.25;
52 let value = gene.allele().extract::<f64>().unwrap();
53
54 let gaussian = rand.gaussian(value, std_dev);
55 let allele = gaussian.clamp(min, max);
56
57 *gene.allele_mut() = allele.extract::<F>().unwrap();
58
59 count += 1;
60 }
61 }
62 });
63
64 AlterResult::from(count)
65 }
66}