use std;
use individual::{Individual, IndividualWrapper};
use population::Population;
pub struct PopulationBuilder<T: Individual> {
population: Population<T>,
}
error_chain! {
errors {
IndividualsTooLow
LimitEndTooLow
}
}
impl<T: Individual + Clone> PopulationBuilder<T> {
pub fn new() -> PopulationBuilder<T> {
PopulationBuilder {
population: Population {
num_of_individuals: 0,
population: Vec::new(),
reset_limit: 0,
reset_limit_start: 1000,
reset_limit_end: 10000,
reset_limit_increment: 1000,
reset_counter: 0,
id: 1,
fitness_counter: 0
}
}
}
pub fn initial_population(mut self, individuals: &[T]) -> PopulationBuilder<T> {
self.population.num_of_individuals = individuals.len() as u32;
for individual in individuals {
self.population.population.push(IndividualWrapper {
individual: (*individual).clone(),
fitness: std::f64::MAX,
num_of_mutations: 1,
id: self.population.id,
});
}
self
}
pub fn increasing_mutation_rate(mut self) -> PopulationBuilder<T> {
let mut mutation_rate = 1;
for wrapper in &mut self.population.population {
wrapper.num_of_mutations = mutation_rate;
mutation_rate += 1;
}
self
}
pub fn increasing_exp_mutation_rate(mut self, base: f64) -> PopulationBuilder<T> {
let mut mutation_rate = 1;
for wrapper in &mut self.population.population {
wrapper.num_of_mutations = base.powi(mutation_rate).floor() as u32;
mutation_rate += 1;
}
self
}
pub fn mutation_rate(mut self, mutation_rate: Vec<u32>) -> PopulationBuilder<T> {
assert!(self.population.population.len() == mutation_rate.len());
for (individual, mutation_rate) in self.population
.population
.iter_mut()
.zip(mutation_rate.into_iter()) {
individual.num_of_mutations = mutation_rate;
}
self
}
pub fn reset_limit_start(mut self, reset_limit_start: u32) -> PopulationBuilder<T> {
self.population.reset_limit_start = reset_limit_start;
self.population.reset_limit = reset_limit_start;
self
}
pub fn reset_limit_end(mut self, reset_limit_end: u32) -> PopulationBuilder<T> {
self.population.reset_limit_end = reset_limit_end;
self
}
pub fn reset_limit_increment(mut self, reset_limit_increment: u32) -> PopulationBuilder<T> {
self.population.reset_limit_increment = reset_limit_increment;
self
}
pub fn set_id(mut self, id: u32) -> PopulationBuilder<T> {
for individual in &mut self.population.population {
individual.id = id;
}
self.population.id = id;
self
}
pub fn finalize(self) -> Result<Population<T>> {
match self.population {
Population { num_of_individuals: 0...2, ..} => {
Err(ErrorKind::IndividualsTooLow.into())
}
Population { reset_limit_start: start,
reset_limit_end: end, ..} if (end > 0) && (start >= end) => {
Err(ErrorKind::LimitEndTooLow.into())
}
_ => Ok(self.population)
}
}
}