gas/mutation/
rotate.rs

1use super::Mutation;
2use crate::chromosone::Gene;
3
4#[cfg(test)]
5use mockall::*;
6
7#[mockall_double::double]
8use crate::rando::Rando;
9/**
10*   If `n` is 1 then this mutator swaps the genes at 2 locuses.   If `n` is 2 or more, then this mutator chooses n+1 locuses, and rotates the genes through those positions.
11**/
12pub struct Rotate<const N: usize, const NSYMS: usize> {
13    pub n: usize,
14}
15
16impl<const N: usize, const NSYMS: usize> Rotate<N, NSYMS> {
17    pub const fn new(n: usize) -> Rotate<N, NSYMS> {
18        Rotate { n }
19    }
20}
21
22impl<const N: usize, const NSYMS: usize> Mutation<N, NSYMS> for Rotate<N, NSYMS> {
23    fn run(&self, chromosone: &[Gene; N], rng: &mut Rando) -> [Gene; N] {
24        let mut mutated = chromosone.clone();
25        let mut curpos = rng.gen_range(0..chromosone.len());
26        let origval = chromosone[curpos];
27        let mut nextpos = curpos;
28        for _ in 0..self.n {
29            nextpos = rng.gen_range(0..chromosone.len());
30            mutated[curpos] = chromosone[nextpos];
31            curpos = nextpos;
32        }
33        mutated[nextpos] = origval;
34        mutated
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn test_rotate1() {
44        let mut r = Rando::default();
45        let m = Rotate::<5, 3>::new(1);
46        r.expect_gen_range()
47            .with(predicate::eq(0..5))
48            .times(1)
49            .return_const(1usize);
50        r.expect_gen_range()
51            .with(predicate::eq(0..5))
52            .times(1)
53            .return_const(3usize);
54        assert_eq!(m.run(&[0, 1, 2, 0, 1], &mut r), [0, 0, 2, 1, 1]);
55    }
56
57    #[test]
58    fn test_rotate2() {
59        let mut r = Rando::default();
60        let m = Rotate::<5, 3>::new(2);
61        r.expect_gen_range()
62            .with(predicate::eq(0..5))
63            .times(1)
64            .return_const(0usize);
65        r.expect_gen_range()
66            .with(predicate::eq(0..5))
67            .times(1)
68            .return_const(1usize);
69        r.expect_gen_range()
70            .with(predicate::eq(0..5))
71            .times(1)
72            .return_const(2usize);
73        assert_eq!(m.run(&[0, 1, 2, 0, 1], &mut r), [1, 2, 0, 0, 1]);
74    }
75}