use rand::{seq::IteratorRandom, RngCore}; use std::fmt::Debug; use crate::{comparison::BetterThanOperator, fitness::FitnessFunction, population::{EvaluatedPopulation, EvaluatedChromosome}, 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 } 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) } }