scirs2_optimize/multi_objective/mutation/
mod.rs1use scirs2_core::random::Rng;
6use scirs2_core::random::{Distribution, Normal};
7
8pub trait MutationOperator {
10 fn mutate(&self, solution: &mut [f64], bounds: &[(f64, f64)]);
12}
13
14#[derive(Debug, Clone)]
16pub struct PolynomialMutation {
17 mutation_probability: f64,
18 distribution_index: f64,
19}
20
21impl PolynomialMutation {
22 pub fn new(mutation_probability: f64, distribution_index: f64) -> Self {
23 Self {
24 mutation_probability,
25 distribution_index,
26 }
27 }
28
29 fn calculate_delta(&self, rng: &mut impl Rng) -> f64 {
30 let u = rng.random::<f64>();
31 if u < 0.5 {
32 (2.0 * u).powf(1.0 / (self.distribution_index + 1.0)) - 1.0
33 } else {
34 1.0 - (2.0 * (1.0 - u)).powf(1.0 / (self.distribution_index + 1.0))
35 }
36 }
37}
38
39impl MutationOperator for PolynomialMutation {
40 fn mutate(&self, solution: &mut [f64], bounds: &[(f64, f64)]) {
41 let mut rng = scirs2_core::random::rng();
42 let n = solution.len();
43
44 for i in 0..n {
45 if rng.random::<f64>() <= self.mutation_probability {
46 let (lower, upper) = bounds[i];
47 let delta = self.calculate_delta(&mut rng);
48 let max_delta = upper - lower;
49
50 solution[i] += delta * max_delta;
51 solution[i] = solution[i].max(lower).min(upper);
52 }
53 }
54 }
55}
56
57#[derive(Debug, Clone)]
59pub struct GaussianMutation {
60 mutation_probability: f64,
61 std_dev: f64,
62}
63
64impl GaussianMutation {
65 pub fn new(mutation_probability: f64, std_dev: f64) -> Self {
66 Self {
67 mutation_probability,
68 std_dev,
69 }
70 }
71}
72
73impl MutationOperator for GaussianMutation {
74 fn mutate(&self, solution: &mut [f64], bounds: &[(f64, f64)]) {
75 let mut rng = scirs2_core::random::rng();
76 let normal = Normal::new(0.0, self.std_dev).unwrap();
77
78 for i in 0..solution.len() {
79 if rng.random::<f64>() <= self.mutation_probability {
80 let (lower, upper) = bounds[i];
81 let perturbation = normal.sample(&mut rng);
82
83 solution[i] += perturbation;
84 solution[i] = solution[i].max(lower).min(upper);
85 }
86 }
87 }
88}
89
90#[derive(Debug, Clone)]
92pub struct UniformMutation {
93 mutation_probability: f64,
94}
95
96impl UniformMutation {
97 pub fn new(mutation_probability: f64) -> Self {
98 Self {
99 mutation_probability,
100 }
101 }
102}
103
104impl MutationOperator for UniformMutation {
105 fn mutate(&self, solution: &mut [f64], bounds: &[(f64, f64)]) {
106 let mut rng = scirs2_core::random::rng();
107
108 for i in 0..solution.len() {
109 if rng.random::<f64>() <= self.mutation_probability {
110 let (lower, upper) = bounds[i];
111 solution[i] = rng.gen_range(lower..upper);
112 }
113 }
114 }
115}