use rand::{seq::IteratorRandom, RngCore};
use std::fmt::Debug;
use crate::{comparison::BetterThanOperator, fitness::FitnessFunction, selection::{Selection, TournamentSelection}};
fn extract_by_indices<T>(mut x: Vec<T>, mut idxs: Vec<usize>) -> Vec<T> {
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<TChromosome> {
population: Vec<TChromosome>
}
#[derive(Clone, Debug)]
pub struct EvaluatedChromosome<TChromosome, TResult> {
pub chromosome: TChromosome,
pub evaluation: TResult,
}
#[derive(Clone, Debug)]
pub struct EvaluatedPopulation<TChromosome, TResult> {
pub population: Vec<EvaluatedChromosome<TChromosome, TResult>>
}
impl<TChromosome> Population<TChromosome> {
pub fn from_vec(vec: Vec<TChromosome>) -> Self {
Self {
population: vec
}
}
pub fn from_iterator(iter: impl Iterator<Item = TChromosome>) -> Self {
Self::from_vec(iter.collect())
}
pub fn evaluate<T: FitnessFunction<In = TChromosome>>(self, func: &T) -> Result<EvaluatedPopulation<TChromosome, T::Out>, T::Err> {
EvaluatedPopulation::evaluate(
self.population,
func
)
}
pub fn iter(&mut self) -> impl Iterator<Item = &TChromosome> {
self.population.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut TChromosome> {
self.population.iter_mut()
}
}
impl<TInput, TResult> EvaluatedChromosome<TInput, TResult> {
pub fn deconstruct(self) -> (TInput, TResult) {
(self.chromosome, self.evaluation)
}
}
impl<TChromosome, TResult> EvaluatedPopulation<TChromosome, TResult> {
pub fn new() -> Self {
Self {
population: vec![]
}
}
pub fn evaluate<T: FitnessFunction<In = TChromosome, Out = TResult>>(chromosomes: Vec<TChromosome>, func: &T) -> Result<Self, T::Err> {
Ok(EvaluatedPopulation::from_vec(
chromosomes.into_iter()
.map(|chromosome|
Ok(EvaluatedChromosome {
evaluation: func.fit(&chromosome)?,
chromosome
}))
.collect::<Result<_, _>>()?))
}
pub fn from_vec(vec: Vec<EvaluatedChromosome<TChromosome, TResult>>) -> Self {
Self {
population: vec
}
}
pub fn best_candidate(&self, better_than: &impl BetterThanOperator<TResult>) -> &EvaluatedChromosome<TChromosome, TResult> {
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<TChromosome, TResult>) {
self.population.push(c)
}
pub fn deconstruct(self) -> Vec<EvaluatedChromosome<TChromosome, TResult>> {
self.population
}
fn join(&mut self, mut offsprings: EvaluatedPopulation<TChromosome, TResult>) {
self.population.append(&mut offsprings.population);
}
pub fn iter(&mut self) -> impl Iterator<Item = &EvaluatedChromosome<TChromosome, TResult>> {
self.population.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut EvaluatedChromosome<TChromosome, TResult>> {
self.population.iter_mut()
}
}
impl<TChromosome, TResult: Copy> EvaluatedPopulation<TChromosome, TResult> {
pub fn evaluations_vec(&self) -> Vec<TResult> {
self.population
.iter()
.map(|individual| individual.evaluation)
.collect()
}
}
pub trait Replacement<TChromosome, TResult> {
fn replace(
&mut self,
parents_evaluations: EvaluatedPopulation<TChromosome, TResult>,
offsprings_evaluations: EvaluatedPopulation<TChromosome, TResult>,
better_than: &dyn BetterThanOperator<TResult>
) -> EvaluatedPopulation<TChromosome, TResult>;
}
pub struct BestReplacement;
impl BestReplacement {
pub fn new() -> Self {
Self
}
}
impl<TChromosome, TResult: Copy + Debug> Replacement<TChromosome, TResult> for BestReplacement {
fn replace(
&mut self,
parents_evaluations: EvaluatedPopulation<TChromosome, TResult>,
offsprings_evaluations: EvaluatedPopulation<TChromosome, TResult>,
better_than: &dyn BetterThanOperator<TResult>
) -> EvaluatedPopulation<TChromosome, TResult> {
let count = parents_evaluations.population.len();
let mut population = parents_evaluations;
population.join(offsprings_evaluations);
let mut idxs = (0..population.population.len())
.collect::<Vec<_>>();
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<TInput, TResult> Replacement<TInput, TResult> for GenerationalReplacement {
fn replace(
&mut self,
parents: EvaluatedPopulation<TInput, TResult>,
mut offsprings: EvaluatedPopulation<TInput, TResult>,
_: &dyn BetterThanOperator<TResult>
) -> EvaluatedPopulation<TInput, TResult> {
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 {
rng: Box<dyn RngCore>
}
impl RandomReplacement {
pub fn new() -> Self {
Self {
rng: Box::new(rand::rng())
}
}
}
impl<TInput, TResult> Replacement<TInput, TResult> for RandomReplacement {
fn replace(
&mut self,
parents: EvaluatedPopulation<TInput, TResult>,
offsprings: EvaluatedPopulation<TInput, TResult>,
_: &dyn BetterThanOperator<TResult>
) -> EvaluatedPopulation<TInput, TResult> {
let count = parents.population.len();
EvaluatedPopulation::from_vec(
parents.deconstruct()
.into_iter()
.chain(offsprings.deconstruct().into_iter())
.choose_multiple(&mut self.rng, count))
}
}
pub struct TournamentReplacement {
selection: TournamentSelection,
evaluation_pool: Vec<f64>
}
impl TournamentReplacement {
pub fn new(k: usize, p: f64) -> Self {
TournamentReplacement {
evaluation_pool: vec![],
selection: TournamentSelection::new(
k,
p,
)
}
}
}
impl<TInput, TResult: Copy> Replacement<TInput, TResult> for TournamentReplacement {
fn replace(
&mut self,
parents: EvaluatedPopulation<TInput, TResult>,
offsprings: EvaluatedPopulation<TInput, TResult>,
better_than: &dyn BetterThanOperator<TResult>
) -> EvaluatedPopulation<TInput, TResult> {
let count = parents.population.len();
let mut population = parents;
population.join(offsprings);
self.evaluation_pool.clear();
// TODO: use a pool instead of allocating vector every run of this function
let selected = self.selection.select(count, &population, better_than)
.collect::<Vec<_>>();
let mut population = population.deconstruct();
for (write_idx, read_idx) in selected.into_iter().enumerate() {
population.swap(read_idx, write_idx);
}
population.truncate(count);
EvaluatedPopulation::from_vec(population)
}
}