radiate_alters/crossovers/
simulated_binary.rs1use 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}