use rand::{seq::IteratorRandom, RngCore}; use std::fmt::Debug; use crate::{comparison::BetterThanOperator, fitness::FitnessFunction, selection::{Selection, TournamentSelection}}; fn extract_by_indices(mut x: Vec, mut idxs: Vec) -> Vec { idxs.sort_unstable_by(|a, b| b.cmp(a)); let mut result = Vec::with_capacity(idxs.len()); for idx in idxs { if idx < x.len() { result.push(x.swap_remove(idx)); } } result.reverse(); result } #[derive(Clone, Debug)] pub struct Population { population: Vec } #[derive(Clone, Debug)] pub struct EvaluatedChromosome { pub chromosome: TChromosome, pub evaluation: TResult, } #[derive(Clone, Debug)] pub struct EvaluatedPopulation { pub population: Vec> } impl Population { pub fn from_vec(vec: Vec) -> Self { Self { population: vec } } pub fn from_iterator(iter: impl Iterator) -> Self { Self::from_vec(iter.collect()) } pub fn evaluate>(self, func: &T) -> Result, T::Err> { EvaluatedPopulation::evaluate( self.population, func ) } pub fn evaluate_mut(self, func: &mut dyn FnMut(&TChromosome) -> TResult) -> EvaluatedPopulation { EvaluatedPopulation::evaluate_mut( self.population, func ) } pub fn into_iter(self) -> impl Iterator { self.population.into_iter() } pub fn iter(&self) -> impl Iterator { self.population.iter() } pub fn iter_mut(&mut self) -> impl Iterator { self.population.iter_mut() } } impl EvaluatedChromosome { pub fn deconstruct(self) -> (TInput, TResult) { (self.chromosome, self.evaluation) } } impl EvaluatedPopulation { pub fn new() -> Self { Self { population: vec![] } } pub fn evaluate>(chromosomes: Vec, func: &T) -> Result { Ok(EvaluatedPopulation::from_vec( chromosomes.into_iter() .map(|chromosome| Ok(EvaluatedChromosome { evaluation: func.fit(&chromosome)?, chromosome })) .collect::>()?)) } pub fn evaluate_mut(chromosomes: Vec, func: &mut dyn FnMut(&TChromosome) -> TResult) -> Self { EvaluatedPopulation::from_vec( chromosomes.into_iter() .map(|chromosome| EvaluatedChromosome { evaluation: func(&chromosome), chromosome }) .collect::>()) } pub fn from_vec(vec: Vec>) -> Self { Self { population: vec } } pub fn best_candidate(&self, better_than: &impl BetterThanOperator) -> &EvaluatedChromosome { let mut best_so_far = &self.population[0]; for individual in self.population.iter().skip(1) { if better_than.better_than(&individual.evaluation, &best_so_far.evaluation) { best_so_far = individual; } } best_so_far } pub fn add(&mut self, c: EvaluatedChromosome) { self.population.push(c) } pub fn deconstruct(self) -> Vec> { self.population } fn join(&mut self, mut offsprings: EvaluatedPopulation) { self.population.append(&mut offsprings.population); } pub fn iter(&self) -> impl Iterator> { self.population.iter() } pub fn iter_mut(&mut self) -> impl Iterator> { self.population.iter_mut() } } impl EvaluatedPopulation { pub fn evaluations_vec(&self) -> Vec { self.population .iter() .map(|individual| individual.evaluation) .collect() } } pub trait Replacement { fn replace( &self, parents_evaluations: EvaluatedPopulation, offsprings_evaluations: EvaluatedPopulation, better_than: &dyn BetterThanOperator, rng: &mut dyn RngCore ) -> EvaluatedPopulation; } pub struct BestReplacement; impl BestReplacement { pub fn new() -> Self { Self } } impl Replacement for BestReplacement { fn replace( &self, parents_evaluations: EvaluatedPopulation, offsprings_evaluations: EvaluatedPopulation, better_than: &dyn BetterThanOperator, _rng: &mut dyn RngCore ) -> EvaluatedPopulation { let count = parents_evaluations.population.len(); let mut population = parents_evaluations; population.join(offsprings_evaluations); let mut idxs = (0..population.population.len()) .collect::>(); idxs.sort_unstable_by(|&i, &j| better_than.ordering( &population.population[i].evaluation, &population.population[j].evaluation) ); idxs.truncate(count); EvaluatedPopulation::from_vec( extract_by_indices(population.deconstruct(), idxs) ) } } pub struct GenerationalReplacement; impl Replacement for GenerationalReplacement { fn replace( &self, parents: EvaluatedPopulation, mut offsprings: EvaluatedPopulation, _: &dyn BetterThanOperator, _rng: &mut dyn RngCore ) -> EvaluatedPopulation { let count = parents.population.len(); if count == offsprings.population.len() { return offsprings; } offsprings.join(parents); offsprings.population.truncate(count); // let population = offsprings.deconstruct(); // population.truncate(count); // EvaluatedPopulation::from_vec(population) offsprings } } pub struct RandomReplacement; impl RandomReplacement { pub fn new() -> Self { Self } } impl Replacement for RandomReplacement { fn replace( &self, parents: EvaluatedPopulation, offsprings: EvaluatedPopulation, _: &dyn BetterThanOperator, rng: &mut dyn RngCore ) -> EvaluatedPopulation { let count = parents.population.len(); EvaluatedPopulation::from_vec( parents.deconstruct() .into_iter() .chain(offsprings.deconstruct().into_iter()) .choose_multiple(rng, count)) } } pub struct TournamentReplacement { selection: TournamentSelection, evaluation_pool: Vec } impl TournamentReplacement { pub fn new(k: usize, p: f64) -> Self { TournamentReplacement { evaluation_pool: vec![], selection: TournamentSelection::new( k, p, ) } } } impl Replacement for TournamentReplacement { fn replace( &self, parents: EvaluatedPopulation, offsprings: EvaluatedPopulation, better_than: &dyn BetterThanOperator, rng: &mut dyn RngCore ) -> EvaluatedPopulation { let count = parents.population.len(); let mut population = parents; population.join(offsprings); // TODO: use a pool instead of allocating vector every run of this function let selected = self.selection.select(count, &population, better_than, rng) .collect::>(); let population = population.deconstruct(); let population = extract_by_indices(population, selected); EvaluatedPopulation::from_vec(population) } }