radiate_alters/mutators/
polynomial.rs1use radiate_core::{BoundedGene, Chromosome, FloatGene, Gene, Mutate, Rate, random_provider};
2use radiate_utils::{Float, Primitive};
3
4#[derive(Debug, Clone)]
21pub struct PolynomialMutator {
22 rate: Rate,
23 eta: f32,
24}
25
26impl PolynomialMutator {
27 pub fn new(rate: impl Into<Rate>, eta: f32) -> Self {
28 let rate = rate.into();
29 PolynomialMutator { rate, eta }
30 }
31
32 fn polynomial_mutation(&self, value: f64, min: f64, max: f64, eta: f64) -> f64 {
33 let u = random_provider::random::<f64>();
34
35 if (max - min).abs() < f64::EPSILON {
36 return value;
37 }
38
39 let delta1 = (value - min) / (max - min);
40 let delta2 = (max - value) / (max - min);
41
42 let mutq = if u <= 0.5 {
43 let term1 = 2.0 * u;
45 let term2 = (1.0 - 2.0 * u) * (1.0 - delta1).powf(eta + 1.0);
46 (term1 + term2).powf(1.0 / (eta + 1.0))
47 } else {
48 let term1 = 2.0 * (1.0 - u);
50 let term2 = 2.0 * (u - 0.5) * (1.0 - delta2).powf(eta + 1.0);
51 1.0 - (term1 + term2).powf(1.0 / (eta + 1.0))
52 };
53
54 min + mutq * (max - min)
55 }
56}
57
58impl<F, C> Mutate<C> for PolynomialMutator
59where
60 F: Float + Primitive,
61 C: Chromosome<Gene = FloatGene<F>>,
62{
63 fn rate(&self) -> Rate {
64 self.rate.clone()
65 }
66
67 #[inline]
68 fn mutate_gene(&self, gene: &mut C::Gene) -> usize {
69 let (lower, upper) = gene.bounds();
70 let min = lower.extract::<f64>().unwrap();
71 let max = upper.extract::<f64>().unwrap();
72 let value = gene.allele().extract::<f64>().unwrap();
73 let eta = self.eta as f64;
74
75 let new_value = self.polynomial_mutation(value, min, max, eta);
76
77 let clamped_value = new_value.clamp(min, max);
78 *gene.allele_mut() = clamped_value.extract::<F>().unwrap();
79 1
80 }
81}