use super::ga_core::GASolution;
use std::cmp::Ordering;
use std::iter::FromIterator;
#[derive(Clone, Copy)]
pub enum GAPopulationSortBasis
{
Raw,
Scaled,
}
#[derive(Clone, Copy)]
pub enum GAPopulationSortOrder
{
LowIsBest,
HighIsBest,
}
pub struct GAPopulation<T: GASolution>
{
population: Vec<T>,
sort_order: GAPopulationSortOrder,
population_order_raw: Vec<usize>,
is_raw_sorted: bool,
population_order_scaled: Vec<usize>,
is_scaled_sorted: bool,
}
impl<T: GASolution> GAPopulation<T>
{
pub fn new(p: Vec<T>, order: GAPopulationSortOrder) -> GAPopulation<T>
{
let gap = GAPopulation
{
population: p,
sort_order: order,
population_order_raw: vec![],
is_raw_sorted: false,
population_order_scaled: vec![],
is_scaled_sorted: false
};
gap
}
pub fn population(&mut self) -> &mut Vec<T>
{
return &mut self.population
}
pub fn evaluate(&mut self)
{
for ref mut ind in &mut self.population
{
ind.evaluate();
}
}
pub fn size(&self) -> usize
{
self.population.len()
}
pub fn order(&self) -> GAPopulationSortOrder
{
self.sort_order
}
pub fn select(&self) -> &T
{
self.individual(0, GAPopulationSortBasis::Scaled)
}
pub fn best(&self) -> &T
{
self.individual(0, GAPopulationSortBasis::Scaled)
}
pub fn worst(&self) -> &T
{
self.individual(self.size()-1, GAPopulationSortBasis::Scaled)
}
pub fn best_by_raw_score(&self) -> &T
{
self.individual(0, GAPopulationSortBasis::Raw)
}
pub fn worst_by_raw_score(&self) -> &T
{
self.individual(self.size()-1, GAPopulationSortBasis::Scaled)
}
pub fn best_by_scaled_score(&self) -> &T
{
self.individual(0, GAPopulationSortBasis::Raw)
}
pub fn worst_by_scaled_score(&self) -> &T
{
self.individual(self.size()-1, GAPopulationSortBasis::Scaled)
}
pub fn individual(&self, i : usize, sort_basis : GAPopulationSortBasis) -> &T
{
match sort_basis
{
GAPopulationSortBasis::Raw
=> { &self.population[self.population_order_raw[i]] },
GAPopulationSortBasis::Scaled
=> { &self.population[self.population_order_scaled[i]] },
}
}
pub fn sort(&mut self)
{
self.sort_int(false, GAPopulationSortBasis::Scaled);
self.sort_int(false, GAPopulationSortBasis::Raw);
}
pub fn sort_int(&mut self, force_sort: bool, sort_basis: GAPopulationSortBasis)
{
let mut ordered : Vec<usize> = Vec::from_iter(0..self.size());
match sort_basis
{
GAPopulationSortBasis::Raw
=> if (!self.is_raw_sorted) || force_sort
{
match self.sort_order
{
GAPopulationSortOrder::LowIsBest =>
{
ordered.sort_by(|s1: &usize, s2: &usize|
self.population[*s1].score()
.partial_cmp(&self.population[*s2].score()).unwrap_or(Ordering::Equal));
},
GAPopulationSortOrder::HighIsBest =>
{
ordered.sort_by(|s1: &usize, s2: &usize|
self.population[*s2].score()
.partial_cmp(&self.population[*s1].score()).unwrap_or(Ordering::Equal));
},
};
self.population_order_raw = ordered;
self.is_raw_sorted = true;
},
GAPopulationSortBasis::Scaled
=> if (!self.is_scaled_sorted) || force_sort
{
match self.sort_order
{
GAPopulationSortOrder::LowIsBest =>
{
ordered.sort_by(|s1: &usize, s2: &usize|
self.population[*s1].fitness()
.partial_cmp(&self.population[*s2].fitness()).unwrap_or(Ordering::Equal));
},
GAPopulationSortOrder::HighIsBest =>
{
ordered.sort_by(|s1: &usize, s2: &usize|
self.population[*s2].fitness()
.partial_cmp(&self.population[*s1].fitness()).unwrap_or(Ordering::Equal));
}
};
self.population_order_scaled = ordered;
self.is_scaled_sorted = true;
},
};
}
}
#[cfg(test)]
mod test
{
}