1use crate::PgmChromosome;
2use radiate_core::alter::{AlterResult, Mutate};
3use radiate_core::random_provider;
4use radiate_utils::Value;
5
6#[derive(Clone, Debug)]
7pub struct PgmParamMutator {
8 pub factor_rate: f32,
10 pub entry_rate: f32,
12 pub step: f32,
14}
15
16impl PgmParamMutator {
17 pub fn new(factor_rate: f32, entry_rate: f32, step: f32) -> Self {
18 Self {
19 factor_rate,
20 entry_rate,
21 step,
22 }
23 }
24}
25
26impl Mutate<PgmChromosome> for PgmParamMutator {
27 #[inline]
28 fn mutate_chromosome(&self, chromosome: &mut PgmChromosome, _: f32) -> AlterResult {
29 let mut count = 0;
30 for f in chromosome.factors.iter_mut() {
31 if random_provider::bool(self.factor_rate) {
32 let Value::Array { values, .. } = &mut f.params else {
33 continue;
34 };
35
36 random_provider::with_rng(|rng| {
37 let n = values.len().max(1);
38 let k = ((n as f32) * self.entry_rate).ceil() as usize;
39 let k = k.clamp(1, n);
40
41 let idxs = rng.sample_indices(0..n, k);
42 let vals = std::sync::Arc::make_mut(values);
43
44 for &i in &idxs {
45 vals[i] += rng.range(-self.step..self.step);
46 }
47
48 k
49 });
50
51 count += 1;
52 }
53 }
54
55 AlterResult::from(count)
56 }
57}
58
59#[derive(Clone, Debug)]
61pub struct PgmScopeMutator {
62 pub factor_rate: f32,
63 pub max_scope: usize,
64}
65
66impl PgmScopeMutator {
67 pub fn new(factor_rate: f32, max_scope: usize) -> Self {
68 Self {
69 factor_rate,
70 max_scope,
71 }
72 }
73}
74
75impl Mutate<PgmChromosome> for PgmScopeMutator {
76 #[inline]
77 fn mutate_chromosome(&self, chromosome: &mut PgmChromosome, _rate: f32) -> AlterResult {
78 let mut count = 0;
79
80 let vars = chromosome.vars.clone();
81 for f in chromosome.factors.iter_mut() {
82 if random_provider::bool(self.factor_rate) {
83 f.resample_scope(&vars, self.max_scope);
84 count += 1;
85 }
86 }
87
88 AlterResult::from(count)
89 }
90}