rust_monster/ga/
ga_population.rs

1// TODO: COPYRIGHT, USE & AUTHORS
2
3use super::ga_core::GASolution;
4
5use std::cmp::Ordering;
6use std::iter::FromIterator;
7
8// Better name than 'Basis'?
9#[derive(Clone, Copy)]
10pub enum GAPopulationSortBasis
11{
12    Raw,
13    Scaled,
14}
15
16// The 'Copy' trait requires the 'Clone' trait.
17// 'Copy' removes the 'move' semantics from an assignment or a function return of value.
18#[derive(Clone, Copy)]
19pub enum GAPopulationSortOrder
20{
21    LowIsBest,
22    HighIsBest,
23}
24
25/// Genetic Algorithm Population
26// TODO: RUST DOCS!
27pub struct GAPopulation<T: GASolution>
28{
29    population: Vec<T>,
30
31    sort_order: GAPopulationSortOrder,
32
33    // 'population' ordered by Raw score.
34    population_order_raw: Vec<usize>,
35    // Is 'population_order_raw' sorted?
36    is_raw_sorted: bool,
37
38    // 'population' ordered by Scaled score.
39    population_order_scaled: Vec<usize>,
40    // Is 'population_scaled' sorted?
41    is_scaled_sorted: bool,
42
43    // We keep 2 lists of indexes to the population vector.
44    // One sorted by Raw Score and one by Scaled Score (Fitness).
45}
46impl<T: GASolution> GAPopulation<T>
47{
48    // TODO: New should use some parameters, maybe a Config
49    pub fn new(p: Vec<T>, order: GAPopulationSortOrder) -> GAPopulation<T>
50    {
51        let gap = GAPopulation 
52                  {
53                      population: p,
54                      sort_order: order,
55                      population_order_raw: vec![],
56                      is_raw_sorted: false,
57                      population_order_scaled: vec![],
58                      is_scaled_sorted: false
59                  };
60
61        gap
62    }
63
64    pub fn population(&mut self) -> &mut Vec<T>
65    {
66        return &mut self.population
67    }
68
69    pub fn evaluate(&mut self)
70    {
71        for ref mut ind in &mut self.population
72        {
73            ind.evaluate();
74        }
75    }
76
77    pub fn size(&self) -> usize
78    {
79        self.population.len()
80    }
81
82    pub fn order(&self) -> GAPopulationSortOrder
83    {
84        // This is not a 'move', but a copy (GAPopulationSortOrder implements the
85        // 'Copy' trait). A move from a borrowed reference (such as 'self') would 
86        // not be permitted.
87        self.sort_order
88    }
89
90    //TODO: this is a temporary implementation
91    pub fn select(&self) -> &T
92    {
93        self.individual(0, GAPopulationSortBasis::Scaled)
94    }
95
96    //TODO: This is a temporary implementation 
97    pub fn best(&self) -> &T
98    {
99        // TODO: Call GAPopulation.scale().
100
101        self.individual(0, GAPopulationSortBasis::Scaled)
102    }
103
104    //TODO: This is a temporary implementation 
105    pub fn worst(&self) -> &T
106    {
107        self.individual(self.size()-1, GAPopulationSortBasis::Scaled)
108    }
109
110    pub fn best_by_raw_score(&self) -> &T
111    {
112        self.individual(0, GAPopulationSortBasis::Raw)
113    }
114
115    pub fn worst_by_raw_score(&self) -> &T
116    {
117        self.individual(self.size()-1, GAPopulationSortBasis::Scaled)
118    }
119
120    pub fn best_by_scaled_score(&self) -> &T
121    {
122        self.individual(0, GAPopulationSortBasis::Raw)
123    }
124
125    pub fn worst_by_scaled_score(&self) -> &T
126    {
127        self.individual(self.size()-1, GAPopulationSortBasis::Scaled)
128    }
129
130    pub fn individual(&self, i : usize, sort_basis : GAPopulationSortBasis) -> &T
131    {
132        // TODO: Check that i makes sense
133        match sort_basis
134        {
135            GAPopulationSortBasis::Raw
136            => { &self.population[self.population_order_raw[i]] },
137            GAPopulationSortBasis::Scaled
138            => { &self.population[self.population_order_scaled[i]] },
139        }
140    }
141
142    pub fn sort(&mut self)
143    {
144        self.sort_int(false, GAPopulationSortBasis::Scaled);
145        self.sort_int(false, GAPopulationSortBasis::Raw);
146    }
147
148    //TODO: I hate this name
149    pub fn sort_int(&mut self, force_sort: bool, sort_basis: GAPopulationSortBasis)
150    {
151        let mut ordered : Vec<usize> = Vec::from_iter(0..self.size());
152        match sort_basis
153        {
154            GAPopulationSortBasis::Raw
155            =>  if (!self.is_raw_sorted) || force_sort
156                {
157                    match self.sort_order
158                    {
159                        GAPopulationSortOrder::LowIsBest =>
160                        {
161                            ordered.sort_by(|s1: &usize, s2: &usize|
162                                            self.population[*s1].score()
163                                                .partial_cmp(&self.population[*s2].score()).unwrap_or(Ordering::Equal));
164
165                        },
166                        GAPopulationSortOrder::HighIsBest =>
167                        {
168                            ordered.sort_by(|s1: &usize, s2: &usize|
169                                            self.population[*s2].score()
170                                                .partial_cmp(&self.population[*s1].score()).unwrap_or(Ordering::Equal));
171                                                                  
172                        },
173                    };
174                    self.population_order_raw = ordered;
175                    self.is_raw_sorted = true;
176                },
177
178            GAPopulationSortBasis::Scaled
179            =>  if (!self.is_scaled_sorted) || force_sort
180                {
181                    match self.sort_order
182                    {
183                        GAPopulationSortOrder::LowIsBest =>
184                        { 
185                            ordered.sort_by(|s1: &usize, s2: &usize|
186                                            self.population[*s1].fitness()
187                                                .partial_cmp(&self.population[*s2].fitness()).unwrap_or(Ordering::Equal));
188                        },
189
190                        GAPopulationSortOrder::HighIsBest =>
191                        {
192                            ordered.sort_by(|s1: &usize, s2: &usize|
193                                            self.population[*s2].fitness()
194                                                .partial_cmp(&self.population[*s1].fitness()).unwrap_or(Ordering::Equal));
195                        }
196                    };
197                    self.population_order_scaled = ordered;
198                    self.is_scaled_sorted = true;
199                },
200        };
201    }
202}
203
204
205#[cfg(test)]
206mod test
207{
208}