From d8580bdc2c159bd7c925cfecb4a9d53921288722 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sun, 26 Oct 2025 21:42:30 +0100 Subject: [PATCH] feat: add evolution algorithm --- env/src/evolution.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++ env/src/main.rs | 1 + 2 files changed, 90 insertions(+) create mode 100644 env/src/evolution.rs diff --git a/env/src/evolution.rs b/env/src/evolution.rs new file mode 100644 index 0000000000000000000000000000000000000000..7c79a48bafca246eba91c88a3540014a84e6a1e2 --- /dev/null +++ b/env/src/evolution.rs @@ -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 { + 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 + }) +} diff --git a/env/src/main.rs b/env/src/main.rs index 50c14dcd56cc4247be9641df42ce074d2a2f2f0d..b27e4400b2264f58bbf7d4ab147488e4b9c8892f 100644 --- a/env/src/main.rs +++ b/env/src/main.rs @@ -1,5 +1,6 @@ pub mod fitness; pub mod pairing; +pub mod evolution; pub mod crossover; pub mod bounded; pub mod selection;