1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use std::mem::swap;

use mop_blocks::{mp::mphos::Mphos, SolutionMut};
use rand::{thread_rng, Rng};

use genetic_algorithm::operators::mutation::Mutation;


#[derive(Clone, Debug)]
pub struct Swap {
    genes_num: usize,
    probability: f64,
}

impl Swap {
    
    pub fn new(genes_num: usize, probability: f64) -> Self {
        Swap {
            genes_num,
            probability,
        }
    }

    /// Swap individual genes
    fn swap_ind_genes<R, T>(solution: &mut SolutionMut<T>, vars_range: usize, rng: &mut R)
    where
        R: Rng,
    {
        let var_idx = rng.gen_range(0, vars_range);
        let mut first_idx;
        let mut second_idx;
        loop {
            first_idx = rng.gen_range(0, solution.events());
            second_idx = rng.gen_range(0, solution.events());
            if second_idx > first_idx {
                break;
            }
        }
        let (mut a, mut b) = solution.two_events_mut(first_idx, second_idx);
        let first_var = a.var_mut(var_idx);
        let second_var = b.var_mut(var_idx);
        if first_var.is_some() && second_var.is_some() {
            swap(first_var.unwrap(), second_var.unwrap());
        }
    }
}

impl<C, N, V> Mutation<C, N, V> for Swap {
    fn mutation(&self, or: &mut Mphos<C, N, V>) {
        let vars_range = or.definitions().vars_domains().len();
        let mut rng = thread_rng();
        or.results_mut().iter_mut().for_each(|mut x| {
            if self.probability >= rng.gen_range(0.0, 100.0) {
                for _ in 0..self.genes_num {
                    Self::swap_ind_genes(x.solution_mut(), vars_range, &mut rng);
                }
            }
        });
    }
}