use rand::{Rng};
use rand::distributions::{IndependentSample, Range};
use serde::de::{DeserializeOwned};
use serde::ser::Serialize;
use std;
use context::*;
use math::*;
use neuro::{MultilayeredNetwork};
use problem::*;
use result::*;
use settings::*;
#[allow(dead_code, unused_variables)]
pub trait Individual{
fn new() -> Self;
fn init<R: Rng>(&mut self, size: usize, &mut R);
fn get_fitness(&self) -> f32;
fn set_fitness(&mut self, fitness: f32);
fn to_vec(&self) -> Option<&[f32]>;
fn to_vec_mut(&mut self) -> Option<&mut Vec<f32>>;
fn to_net(&mut self) -> Option<&MultilayeredNetwork> {None}
fn to_net_mut(&mut self) -> Option<&mut MultilayeredNetwork> {None}
fn set_net(&mut self, net: MultilayeredNetwork) {}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RealCodedIndividual {
pub genes: Vec<f32>,
pub fitness: f32,
}
impl RealCodedIndividual {
}
impl Individual for RealCodedIndividual{
fn new() -> Self {
RealCodedIndividual{genes: Vec::new(), fitness: std::f32::NAN}
}
fn init<R: Rng>(&mut self, size: usize, mut rng: &mut R) {
self.genes = rand_vector_std_gauss(size as usize, rng);
}
fn get_fitness(&self) -> f32 {
self.fitness
}
fn set_fitness(&mut self, fitness: f32) {
self.fitness = fitness;
}
fn to_vec(&self) -> Option<&[f32]> {
Some(&self.genes)
}
fn to_vec_mut(&mut self) -> Option<&mut Vec<f32>> {
Some(&mut self.genes)
}
}
pub trait EA<'a, P> where P: Problem {
type IndType: Individual+Clone+Serialize+DeserializeOwned;
fn run_multiple(&mut self, settings: EASettings, run_num: u32) -> Result<EAResultMultiple<Self::IndType>, ()> {
let run_ress = (0..run_num).into_iter()
.map(|_| {
self.run(settings.clone()).expect("Error during GA run").clone()
})
.collect::<Vec<EAResult<Self::IndType>>>();
let res = EAResultMultiple::new(&run_ress);
Ok(res)
}
fn run_with_context(&self, ctx: &mut EAContext<Self::IndType>, problem: &P, gen_count: u32) { for t in 0..gen_count {
self.evaluate(ctx, problem);
let sel_inds = self.select(ctx);
let mut children: Vec<Self::IndType> = Vec::with_capacity(ctx.settings.pop_size as usize);
self.breed(ctx, &sel_inds, &mut children);
self.next_generation(ctx, &children);
println!("> {} : {:?}", t, ctx.fitness);
println!(" Best fitness at generation {} : {}\n", t, min(&ctx.fitness));
}
}
fn evaluate(&self, ctx: &mut EAContext<Self::IndType>, problem: &P) {
let cur_result = &mut ctx.result;
let popul = &mut ctx.population;
ctx.fitness = popul.iter_mut().map(|ref mut ind| {
let f = problem.compute(ind as &mut Self::IndType);
ind.set_fitness(f);
f
}).collect::<Vec<f32>>();
let fits = &ctx.fitness;
if cur_result.first_hit_fe_count == 0 {
for k in 0..fits.len() {
if problem.is_solution(fits[k]) {
cur_result.first_hit_fe_count = cur_result.fe_count + (k+1) as u32;
break;
}
}
}
cur_result.avg_fitness.push(mean(&fits));
cur_result.max_fitness.push(max(&fits));
let last_min_fitness = min(&fits);
cur_result.min_fitness.push(last_min_fitness);
if cur_result.best.get_fitness().is_nan() || (cur_result.best.get_fitness() > last_min_fitness) {
let idx = (&fits).iter().position(|&x| x == last_min_fitness).expect("Min fitness is not found");
cur_result.best = popul[idx].clone();
cur_result.best_fe_count = cur_result.fe_count + (idx+1) as u32;
}
cur_result.best.set_fitness(last_min_fitness);
cur_result.fe_count += fits.len() as u32;
}
fn select(&self, ctx: &mut EAContext<Self::IndType>) -> Vec<usize> {
select_tournament(&ctx.fitness, ctx.settings.tour_size, &mut ctx.rng)
}
fn next_generation(&self, ctx: &mut EAContext<Self::IndType>, children: &Vec<Self::IndType>) {
ctx.population = Vec::with_capacity(children.len());
for k in 0..children.len() {
ctx.population.push(children[k].clone());
}
ctx.population.truncate(ctx.settings.pop_size as usize);
}
fn breed(&self, ctx: &mut EAContext<Self::IndType>, sel_inds: &Vec<usize>, children: &mut Vec<Self::IndType>);
fn run(&mut self, settings: EASettings) -> Result<&EAResult<Self::IndType>, ()>;
}
pub fn create_population<T: Individual, P: Problem, R: Rng+Sized>(pop_size: u32, ind_size: u32, mut rng: &mut R, problem: &P) -> Vec<T> {
println!("Creating population of {} individuals having size {}", pop_size, ind_size);
let mut res = Vec::with_capacity(pop_size as usize);
for _ in 0..pop_size {
res.push(problem.get_random_individual::<T, R>(ind_size as usize, rng));
}
res
}
fn select_tournament(fits: &Vec<f32>, tour_size: u32, mut rng: &mut Rng) -> Vec<usize> {
let range = Range::new(0, fits.len());
let mut sel_inds: Vec<usize> = Vec::with_capacity(fits.len()); for _ in 0..fits.len() {
let tour_inds = (0..tour_size).map(|_| range.ind_sample(&mut rng)).collect::<Vec<usize>>();
let winner = tour_inds.iter().fold(tour_inds[0], |w_idx, &k|
if fits[w_idx] < fits[k] {w_idx}
else {k}
);
sel_inds.push(winner);
}
sel_inds
}
pub fn get_best_individual<T: Individual+Clone>(popul: &Vec<T>) -> T {
let min_fitness = popul.into_iter().fold(std::f32::MAX, |s, ref ind| if s < ind.get_fitness() {s} else {ind.get_fitness()});
let idx = popul.into_iter().position(|ref x| x.get_fitness() == min_fitness).expect("Min fitness is not found");
popul[idx].clone()
}
#[allow(unused_imports)]
#[cfg(test)]
mod test {
use rand;
use ea::*;
use math::*;
#[test]
fn test_tournament_selection() {
const IND_COUNT: usize = 100;
const TRIAL_COUNT: u32 = 100;
let mut prev_mean = 0.5f32; let mut rng = rand::thread_rng();
for t in 2..10 {
let mut cur_mean = 0f32;
for _ in 0..TRIAL_COUNT {
let fitness_vals = rand_vector(IND_COUNT, &mut rng);
let sel_inds = select_tournament(&fitness_vals, t, &mut rng);
let tmp_mean = sel_inds.iter().fold(0f32, |s, &idx| s + fitness_vals[idx]) / IND_COUNT as f32;
cur_mean += tmp_mean;
}
cur_mean /= TRIAL_COUNT as f32;
assert!(cur_mean < prev_mean);
prev_mean = cur_mean;
}
}
}