radiate_alters/crossovers/
simulated_binary.rs

1use radiate_core::{
2    AlterResult, BoundedGene, Chromosome, Crossover, FloatGene, Gene, random_provider,
3};
4
5pub struct SimulatedBinaryCrossover {
6    contiguty: f32,
7    crossover_rate: f32,
8}
9
10impl SimulatedBinaryCrossover {
11    pub fn new(crossover_rate: f32, contiguty: f32) -> Self {
12        Self {
13            contiguty,
14            crossover_rate,
15        }
16    }
17}
18
19impl<C: Chromosome<Gene = FloatGene>> Crossover<C> for SimulatedBinaryCrossover {
20    fn rate(&self) -> f32 {
21        self.crossover_rate
22    }
23
24    #[inline]
25    fn cross_chromosomes(&self, chrom_one: &mut C, chrom_two: &mut C, _: f32) -> AlterResult {
26        let length = std::cmp::min(chrom_one.len(), chrom_two.len());
27
28        if length < 2 {
29            return AlterResult::empty();
30        }
31
32        let mut count = 0;
33
34        for i in 0..length {
35            if random_provider::bool(0.5) {
36                let u = random_provider::random::<f32>();
37                let beta = if u <= 0.5 {
38                    (2.0 * u).powf(1.0 / (self.contiguty + 1.0))
39                } else {
40                    (0.5 / (1.0 - u)).powf(1.0 / (self.contiguty + 1.0))
41                };
42
43                let v1 = chrom_one.get(i).allele();
44                let v2 = chrom_two.get(i).allele();
45
46                let v = if random_provider::bool(0.5) {
47                    (v1 - v2) * 0.5 - (beta * 0.5 * (v1 - v2).abs())
48                } else {
49                    (v1 - v2) * 0.5 + (beta * 0.5 * (v1 - v2).abs())
50                };
51
52                let new_gene = v.clamp(*chrom_one.get(i).min(), *chrom_one.get(i).max());
53
54                count += 1;
55
56                chrom_one.set(i, chrom_one.get(i).with_allele(&new_gene));
57            }
58        }
59
60        AlterResult::from(count)
61    }
62}