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 rand::{thread_rng, Rng};
use std::cmp::min;
use std::mem::swap;
use std::slice;

use mop_blocks::mp::mphos::Morhos;

use genetic_algorithm::operators::crossover::Crossover;


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

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

    /// Swap individuals data
    fn swap_inds_data<T>(&self, first: &mut [T], second: &mut [T]) {
        let slices_len = min(first.len(), second.len());
        let step = slices_len / self.points;
        for idx in 0..slices_len {
            if idx % step == 0 {
                swap(&mut first[idx], &mut second[idx]);
            }
        }
    }
}

impl<N, V> Crossover<N, V> for MultiPoint {
    fn crossover(&self, or: &mut Morhos<N, V>) {
        let mut rng = thread_rng();
        for _ in 0..or.len() {
            if self.probability < rng.gen_range(0.0, 100.0) {
                break;
            }
            let first_solut_slice = {
                let index = rng.gen_range(0, or.len());
                let mut opt_result = or.get_mut(index);
                let vm = opt_result.solution_mut().variables_mut();
                unsafe { slice::from_raw_parts_mut(vm.as_mut_ptr(), vm.len()) }
            };
            let second_solut_slice = {
                let index = rng.gen_range(0, or.len());
                let mut opt_result = or.get_mut(index);
                let vm = opt_result.solution_mut().variables_mut();
                unsafe { slice::from_raw_parts_mut(vm.as_mut_ptr(), vm.len()) }
            };
            self.swap_inds_data(first_solut_slice, second_solut_slice)
        }
    }
}