use std::error::Error; use crate::{comparison::BetterThanOperator, crossover::Crossover, fitness::FitnessFunction, pairing::Pairing, perturbation::PerturbationOperator, replacement::{EvaluatedChromosome, EvaluatedPopulation, Population, Replacement}, selection::Selection}; pub struct EvolutionCandidate { pub evaluated_chromosome: EvaluatedChromosome, pub iteration: usize } pub struct EvolutionCandidatePopulation { pub current_population: EvaluatedPopulation, pub iteration: usize } pub struct EvolutionStats { pub best_candidates: Vec>, } pub struct EvolutionResult { pub population: EvaluatedPopulation, pub stats: EvolutionStats, pub iterations: usize } pub fn evolution_algorithm( initial_population: Population, parents_count: usize, fitness: &impl FitnessFunction, selection: &mut impl Selection, pairing: &mut impl Pairing, crossover: &mut impl Crossover, perturbation: &mut impl PerturbationOperator, replacement: &mut impl Replacement, better_than: &impl BetterThanOperator, // TODO: termination condition iterations: usize ) -> Result, Box> { let mut current_population = initial_population.evaluate(fitness)?; let mut last_best_candidate = EvolutionCandidate { evaluated_chromosome: current_population.best_candidate(better_than).clone(), iteration: 0 }; let mut stats: EvolutionStats = EvolutionStats { best_candidates: vec![] }; for iteration in 0..iterations { // Figure out best candidate and save it if better than last time let best_candidate = current_population.best_candidate(better_than); if better_than.better_than( &best_candidate.evaluation, &last_best_candidate.evaluated_chromosome.evaluation ) { stats.best_candidates.push(last_best_candidate); last_best_candidate = EvolutionCandidate { evaluated_chromosome: best_candidate.clone(), iteration } } // Selection let parents = selection.select(parents_count, ¤t_population, better_than); let parent_pairings = pairing.pair(¤t_population, parents); // Crossover let mut offsprings = crossover.crossover(¤t_population, parent_pairings); // Mutation for offspring in offsprings.iter_mut() { *offspring = perturbation.perturb(offspring); } let evaluated_offsprings = offsprings.evaluate(fitness)?; // Replace current_population = replacement.replace(current_population, evaluated_offsprings, better_than); } stats.best_candidates.push(last_best_candidate); Ok(EvolutionResult { population: current_population, stats, iterations }) }