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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use crate::engines::alterers::alter::Alter;
use crate::engines::genome::genes::gene::Gene;
use crate::engines::genome::phenotype::Phenotype;
use crate::engines::genome::population::Population;
use crate::engines::optimize::Optimize;
use crate::engines::schema::subset;

use super::alter::{AlterWrap, Alterer};
use super::crossovers::multipoint_crossover::MultiPointCrossover;
use super::crossovers::uniform_crossover::UniformCrossover;
use super::mutators::mutator::Mutator;
use super::mutators::swap_mutator::SwapMutator;


pub struct CompositeAlterer<G: Gene<G, A>, A> {
    alterers: Vec<AlterWrap<G, A>>,
}

impl<G: Gene<G, A>, A> CompositeAlterer<G, A> {

    pub fn new(alterers: Vec<Alterer<G, A>>) -> Self {
        let mut alterer_wraps = Vec::new();
        for alterer in alterers {
            match alterer {
                Alterer::Mutator(rate) => {
                    alterer_wraps.push(AlterWrap {
                        rate,
                        mutator: Some(Box::new(Mutator::new(rate))),
                        crossover: None,
                    });
                },
                Alterer::UniformCrossover(rate) => {
                    alterer_wraps.push(AlterWrap {
                        rate,
                        mutator: None,
                        crossover: Some(Box::new(UniformCrossover::new(rate))),
                    });
                },
                Alterer::SinglePointCrossover(rate) => {
                    alterer_wraps.push(AlterWrap {
                        rate,
                        mutator: None,
                        crossover: Some(Box::new(MultiPointCrossover::new(rate, 1))),
                    });
                },
                Alterer::MultiPointCrossover(rate, num_points) => {
                    alterer_wraps.push(AlterWrap {
                        rate,
                        mutator: None,
                        crossover: Some(Box::new(MultiPointCrossover::new(rate, num_points))),
                    });
                },
                Alterer::SwapMutator(rate) => {
                    alterer_wraps.push(AlterWrap {
                        rate,
                        mutator: Some(Box::new(SwapMutator::new(rate))),
                        crossover: None,
                    });
                },
                Alterer::Mutation(mutation) => {
                    alterer_wraps.push(AlterWrap {
                        rate: mutation.mutate_rate(),
                        mutator: Some(mutation),
                        crossover: None,
                    });
                },
                Alterer::Crossover(crossover) => {
                    alterer_wraps.push(AlterWrap {
                        rate: crossover.cross_rate(),
                        mutator: None,
                        crossover: Some(crossover),
                    });
                },
            }
        }

        CompositeAlterer { alterers: alterer_wraps }
    }
}

impl<G: Gene<G, A>, A> Alter<G, A> for CompositeAlterer<G, A> {

    fn alter(&self, population: &mut Population<G, A>, optimize: &Optimize, generation: i32) {
        optimize.sort(population);

        for alterer in self.alterers.iter() {
            match alterer.mutator {
                Some(ref mutator) => {
                    let probability = alterer.rate.powf(1.0 / 3.0);
                    let range = ((((std::i32::MAX as i64 - (std::i32::MIN as i64)) as f32) * probability)
                        + (std::i32::MIN as f32)) as i32;
            
                    for phenotype in population.iter_mut() {
                        if rand::random::<i32>() > range {
                            let mut genotype = phenotype.genotype().clone();
            
                            let mutation_count = mutator.mutate_genotype(&mut genotype, range, probability);

                            if mutation_count > 0 {
                                *phenotype = Phenotype::from_genotype(genotype, generation);
                            }
                        }
                    }
                },
                None => (),
            };
            match alterer.crossover {
                Some(ref crossover) => {
                    let mut random = rand::thread_rng();

                    for i in 0..population.len() {
                        if rand::random::<f32>() < alterer.rate {
                            let parent_indexes = subset::individual_indexes(&mut random, i, population.len(), 2);
                            crossover.cross(population, &parent_indexes, generation);
                        }
                    }
                },
                None => (),
            };
        }
    }
}