radiate_alters/mutators/
arithmetic.rs

1use radiate_core::{AlterResult, ArithmeticGene, Chromosome, Mutate, random_provider};
2
3/// Arithmetic Mutator. Mutates genes by performing arithmetic operations on them.
4/// The [ArithmeticMutator] takes a rate parameter that determines the likelihood that
5/// a gene will be mutated. The [ArithmeticMutator] can perform addition, subtraction,
6/// multiplication, and division on genes.
7///
8/// This is a simple mutator that can be used with any gene that implements the
9/// `Add`, `Sub`, `Mul`, and `Div` traits - [ArithmeticGene] is a good example.
10#[derive(Debug, Clone)]
11pub struct ArithmeticMutator {
12    rate: f32,
13}
14
15impl ArithmeticMutator {
16    /// Create a new instance of the `ArithmeticMutator` with the given rate.
17    /// The rate must be between 0.0 and 1.0.
18    pub fn new(rate: f32) -> Self {
19        if !(0.0..=1.0).contains(&rate) {
20            panic!("Rate must be between 0 and 1");
21        }
22
23        Self { rate }
24    }
25}
26
27impl<G: ArithmeticGene, C: Chromosome<Gene = G>> Mutate<C> for ArithmeticMutator {
28    fn rate(&self) -> f32 {
29        self.rate
30    }
31
32    /// Mutate a gene by performing an arithmetic operation on it.
33    /// Randomly select a number between 0 and 3, and perform the corresponding
34    /// arithmetic operation on the gene.
35    #[inline]
36    fn mutate_chromosome(&self, chromosome: &mut C, rate: f32) -> AlterResult {
37        let mut mutations = 0;
38        for gene in chromosome.iter_mut() {
39            if random_provider::bool(rate) {
40                let operator = random_provider::range(0..4);
41
42                let new_gene = match operator {
43                    0 => gene.clone() + gene.new_instance(),
44                    1 => gene.clone() - gene.new_instance(),
45                    2 => gene.clone() * gene.new_instance(),
46                    3 => gene.clone() / gene.new_instance(),
47                    _ => panic!("Invalid operator - this shouldn't happen: {}", operator),
48                };
49
50                *gene = new_gene;
51                mutations += 1;
52            }
53        }
54
55        AlterResult::from(mutations)
56    }
57}