diff --git a/src/lib.rs b/src/lib.rs index 9508737..e94ca92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ extern crate simple_parallel; use rand::{Rand, Rng}; use std::cmp::PartialOrd; use simple_parallel::Pool; +use std::ops::Deref; pub mod bit_string; @@ -93,44 +94,27 @@ pub trait Evaluator: Sync { fn fitness(&self, individual: &I) -> F; } -/// Caches the `fitness` value for an individual. -#[derive(Clone, Debug)] -pub struct EvaluatedIndividual { - individual: I, - fitness: Option, -} - -impl EvaluatedIndividual { - pub fn new(ind: I) -> EvaluatedIndividual { - EvaluatedIndividual { - individual: ind, - fitness: None, - } - } - #[inline(always)] - pub fn fitness(&self) -> Option { - self.fitness.clone() - } - #[inline(always)] - pub fn individual<'a>(&'a self) -> &'a I { - &self.individual - } -} - /// Manages a population of individuals. #[derive(Clone, Debug)] -pub struct Population { - population: Vec>, +pub struct Population +where W:Deref, + I:Individual, + F:Fitness, +{ + population: Vec<(W, Option)>, } // XXX: Have Population and EvaluatedPopulation. This avoids having two arrays. -impl Population +impl Population +where W:Deref, + I:Individual, + F:Fitness, { - pub fn new() -> Population { + pub fn new() -> Population { Population { population: Vec::new() } } - pub fn with_capacity(capa: usize) -> Population { + pub fn with_capacity(capa: usize) -> Population { Population { population: Vec::with_capacity(capa) } } @@ -143,8 +127,8 @@ impl Population pub fn fittest(&self) -> Option<(usize, F)> { let mut fittest: Option<(usize, F)> = None; - for (i, ref ind) in self.population.iter().enumerate() { - if let Some(ref f) = ind.fitness { + for (i, ref elm) in self.population.iter().enumerate() { + if let Some(ref f) = elm.1 { let mut is_better = true; if let Some((_, ref best_f)) = fittest { if !f.fitter_than(best_f) { @@ -161,20 +145,20 @@ impl Population #[inline] pub fn get_individual(&self, idx: usize) -> &I { - &self.population[idx].individual + &self.population[idx].0 } #[inline] pub fn get_fitness(&self, idx: usize) -> F { - (&self.population[idx]).fitness.clone().unwrap() + (&self.population[idx]).1.clone().unwrap() } - pub fn add_individual(&mut self, ind: I) { - self.population.push(EvaluatedIndividual::new(ind)); + pub fn add_individual(&mut self, ind: W) { + self.population.push((ind, None)); } pub fn add_individual_with_fitness(&mut self, ind: I, fitness: F) { - self.population.push(EvaluatedIndividual{individual: ind, fitness: Some(fitness)}); + self.population.push((ind, Some(fitness))); } /// Evaluates the whole population, i.e. determines the fitness of @@ -185,10 +169,10 @@ impl Population { let mut nevals = 0; for i in self.population.iter_mut() { - if i.fitness.is_some() { + if i.1.is_some() { continue; } - i.fitness = Some(evaluator.fitness(&i.individual)); + i.1 = Some(evaluator.fitness(&(*i.0))); nevals += 1; } return nevals; @@ -215,8 +199,8 @@ impl Population } }); */ - pool.for_(self.population.iter_mut(), |ind| { - ind.fitness = Some(evaluator.fitness(&ind.individual)); + pool.for_(self.population.iter_mut().map(|ind| ind), |ind| { + ind.1 = Some(evaluator.fitness(&ind.0)); }); return nevals;