genomic/chromosome/
mod.rs

1use rand::{distributions::Distribution, Rng};
2
3mod uniform;
4pub use uniform::*;
5
6mod fixed;
7pub use fixed::*;
8
9pub trait Chromosome {
10    /// Mutates the chromosome, with `rate` being a number between `0.0` and `1.0`.
11    ///
12    /// A `rate` of `1.0` means that the chromosome should take a fully random value.
13    fn mutate(&mut self, rate: f64, rng: &mut impl Rng);
14}
15
16macro_rules! impl_ch_int {
17    ( $type:ty ) => {
18        impl Chromosome for $type {
19            fn mutate(&mut self, rate: f64, rng: &mut impl Rng) {
20                debug_assert!(rate <= 1.0);
21                debug_assert!(rate >= 0.0);
22                let distribution = rand::distributions::Bernoulli::new(rate * 0.5)
23                    .expect("`rate` should be between 0.0 and 1.0");
24
25                for (bit, should_flip) in (0..<$type>::BITS).zip(distribution.sample_iter(rng)) {
26                    if should_flip {
27                        *self ^= 1 << bit;
28                    }
29                }
30            }
31        }
32    };
33}
34
35impl_ch_int!(u8);
36impl_ch_int!(u16);
37impl_ch_int!(u32);
38impl_ch_int!(u64);
39impl_ch_int!(u128);
40impl_ch_int!(i8);
41impl_ch_int!(i16);
42impl_ch_int!(i32);
43impl_ch_int!(i64);
44impl_ch_int!(i128);
45
46impl Chromosome for () {
47    /// Does nothing
48    fn mutate(&mut self, _rate: f64, _rng: &mut impl Rng) {
49        // noop
50    }
51}
52
53impl<T: Chromosome + ?Sized> Chromosome for Box<T> {
54    fn mutate(&mut self, rate: f64, rng: &mut impl Rng) {
55        self.as_mut().mutate(rate, rng);
56    }
57}
58
59impl Chromosome for bool {
60    fn mutate(&mut self, rate: f64, rng: &mut impl Rng) {
61        if rng.gen_bool(rate * 0.5) {
62            *self = !*self;
63        }
64    }
65}