@@ 0,0 1,89 @@
+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<TInput, TResult> {
+ pub evaluated_chromosome: EvaluatedChromosome<TInput, TResult>,
+ pub iteration: usize
+}
+
+pub struct EvolutionCandidatePopulation<TInput, TResult> {
+ pub current_population: EvaluatedPopulation<TInput, TResult>,
+ pub iteration: usize
+}
+
+pub struct EvolutionStats<TInput, TResult> {
+ pub best_candidates: Vec<EvolutionCandidate<TInput, TResult>>,
+}
+
+pub struct EvolutionResult<TInput, TResult> {
+ pub population: EvaluatedPopulation<TInput, TResult>,
+ pub stats: EvolutionStats<TInput, TResult>,
+ pub iterations: usize
+}
+
+pub fn evolution_algorithm<TChromosome: Clone, TResult: Clone>(
+ initial_population: Population<TChromosome>,
+ parents_count: usize,
+ fitness: &impl FitnessFunction<In = TChromosome, Out = TResult>,
+ selection: &mut impl Selection<TChromosome, TResult>,
+ pairing: &mut impl Pairing<Chromosome = TChromosome, Out = TResult>,
+ crossover: &mut impl Crossover<Chromosome = TChromosome, Out = TResult>,
+ perturbation: &mut impl PerturbationOperator<Chromosome = TChromosome>,
+ replacement: &mut impl Replacement<TChromosome, TResult>,
+ better_than: &impl BetterThanOperator<TResult>,
+ // TODO: termination condition
+ iterations: usize
+) -> Result<EvolutionResult<TChromosome, TResult>, Box<dyn Error>> {
+ 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<TChromosome, TResult> = 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
+ })
+}