From 62595f5e13c66e19b57db343ff0856f28df40522 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sat, 8 Nov 2025 16:08:42 +0100 Subject: [PATCH] chore: move population structs to separate module --- codes/eoa_lib/src/crossover.rs | 2 +- codes/eoa_lib/src/evolution.rs | 4 +- codes/eoa_lib/src/lib.rs | 1 + codes/eoa_lib/src/pairing.rs | 2 +- codes/eoa_lib/src/population.rs | 138 ++++++++++++++++++++++++++++++ codes/eoa_lib/src/replacement.rs | 139 +------------------------------ codes/eoa_lib/src/selection.rs | 2 +- codes/tsp_hw01/src/crossovers.rs | 14 ++-- codes/tsp_hw01/src/main.rs | 14 ++-- 9 files changed, 159 insertions(+), 157 deletions(-) create mode 100644 codes/eoa_lib/src/population.rs diff --git a/codes/eoa_lib/src/crossover.rs b/codes/eoa_lib/src/crossover.rs index 1f5c62c1979a3e5468f399d0b796205ac5f1e626..da398d4a1a8d7ebdebc90967ed2de0d6e6031392 100644 --- a/codes/eoa_lib/src/crossover.rs +++ b/codes/eoa_lib/src/crossover.rs @@ -4,7 +4,7 @@ use nalgebra::{allocator::Allocator, DefaultAllocator, Dim, OVector, Scalar, U1} use rand::{seq::IteratorRandom, Rng, RngCore}; use rand_distr::Uniform; -use crate::{binary_string::BinaryString, pairing::ParentPairing, replacement::{EvaluatedPopulation, Population}}; +use crate::{binary_string::BinaryString, pairing::ParentPairing, population::{EvaluatedPopulation, Population}}; pub trait Crossover { type Chromosome; diff --git a/codes/eoa_lib/src/evolution.rs b/codes/eoa_lib/src/evolution.rs index 0cad35bdc4a8d23736e0ec29773de42b23187576..837c3b54643e101be22922a460071a60d39e763e 100644 --- a/codes/eoa_lib/src/evolution.rs +++ b/codes/eoa_lib/src/evolution.rs @@ -1,7 +1,7 @@ use std::error::Error; use rand::RngCore; -use crate::{comparison::BetterThanOperator, crossover::Crossover, fitness::FitnessFunction, pairing::Pairing, perturbation::PerturbationOperator, replacement::{EvaluatedChromosome, EvaluatedPopulation, Population, Replacement}, selection::Selection}; +use crate::{comparison::BetterThanOperator, crossover::Crossover, fitness::FitnessFunction, pairing::Pairing, perturbation::PerturbationOperator, population::{EvaluatedChromosome, EvaluatedPopulation, Population}, replacement::Replacement, selection::Selection}; #[derive(Clone, Debug)] pub struct EvolutionCandidate { @@ -173,7 +173,7 @@ pub fn evolution_algorithm pub mod tests { use nalgebra::Const; - use crate::{binary_string::BinaryString, comparison::MinimizingOperator, crossover::BinaryOnePointCrossover, fitness::one_max::OneMax, initializer::{Initializer, RandomInitializer}, pairing::AdjacentPairing, perturbation::{BinaryStringBitPerturbation, BinaryStringFlipPerturbation, BinaryStringSingleBitPerturbation, CombinedPerturbation, MutationPerturbation}, replacement::{BestReplacement, Population, TournamentReplacement}, selection::TournamentSelection}; + use crate::{binary_string::BinaryString, comparison::MinimizingOperator, crossover::BinaryOnePointCrossover, fitness::one_max::OneMax, initializer::{Initializer, RandomInitializer}, pairing::AdjacentPairing, perturbation::{BinaryStringBitPerturbation, BinaryStringFlipPerturbation, BinaryStringSingleBitPerturbation, CombinedPerturbation, MutationPerturbation}, population::Population, replacement::{BestReplacement, TournamentReplacement}, selection::TournamentSelection}; use super::evolution_algorithm; diff --git a/codes/eoa_lib/src/lib.rs b/codes/eoa_lib/src/lib.rs index 0042eee494ad5c4163145c64962116ef0e1d3d7f..34fd57d1b472d47dd0b14a98f84431fb08bcb688 100644 --- a/codes/eoa_lib/src/lib.rs +++ b/codes/eoa_lib/src/lib.rs @@ -1,5 +1,6 @@ pub mod fitness; pub mod pairing; +pub mod population; pub mod evolution; pub mod crossover; pub mod bounded; diff --git a/codes/eoa_lib/src/pairing.rs b/codes/eoa_lib/src/pairing.rs index 1d18cf66c6aa07a06e80d2a92adb51ddfeb29833..40b920628eb33d5bd19df3c1d02fba23d519799b 100644 --- a/codes/eoa_lib/src/pairing.rs +++ b/codes/eoa_lib/src/pairing.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use nalgebra::{Const, OVector, SVector}; -use crate::replacement::EvaluatedPopulation; +use crate::population::EvaluatedPopulation; pub type ParentPairing = OVector>; diff --git a/codes/eoa_lib/src/population.rs b/codes/eoa_lib/src/population.rs new file mode 100644 index 0000000000000000000000000000000000000000..686ba771ef2166ea66a232b80486b054d4da244e --- /dev/null +++ b/codes/eoa_lib/src/population.rs @@ -0,0 +1,138 @@ +use crate::{comparison::BetterThanOperator, fitness::FitnessFunction}; + +#[derive(Clone, Debug)] +pub struct Population { + population: Vec +} + +#[derive(Clone, Debug)] +pub struct EvaluatedChromosome { + pub chromosome: TChromosome, + pub evaluation: TResult, +} + +#[derive(Clone, Debug)] +pub struct EvaluatedPopulation { + pub population: Vec> +} + +impl Population { + pub fn from_vec(vec: Vec) -> Self { + Self { + population: vec + } + } + + pub fn from_iterator(iter: impl Iterator) -> Self { + Self::from_vec(iter.collect()) + } + + pub fn evaluate>(self, func: &T) -> Result, T::Err> { + EvaluatedPopulation::evaluate( + self.population, + func + ) + } + + pub fn evaluate_mut(self, func: &mut dyn FnMut(&TChromosome) -> TResult) -> EvaluatedPopulation { + EvaluatedPopulation::evaluate_mut( + self.population, + func + ) + } + + pub fn into_iter(self) -> impl Iterator { + self.population.into_iter() + } + + pub fn iter(&self) -> impl Iterator { + self.population.iter() + } + + pub fn iter_mut(&mut self) -> impl Iterator { + self.population.iter_mut() + } +} + +impl EvaluatedChromosome { + pub fn deconstruct(self) -> (TInput, TResult) { + (self.chromosome, self.evaluation) + } +} + +impl EvaluatedPopulation { + pub fn new() -> Self { + Self { + population: vec![] + } + } + + pub fn evaluate>(chromosomes: Vec, func: &T) -> Result { + Ok(EvaluatedPopulation::from_vec( + chromosomes.into_iter() + .map(|chromosome| + Ok(EvaluatedChromosome { + evaluation: func.fit(&chromosome)?, + chromosome + })) + .collect::>()?)) + } + + pub fn evaluate_mut(chromosomes: Vec, func: &mut dyn FnMut(&TChromosome) -> TResult) -> Self { + EvaluatedPopulation::from_vec( + chromosomes.into_iter() + .map(|chromosome| + EvaluatedChromosome { + evaluation: func(&chromosome), + chromosome + }) + .collect::>()) + } + + pub fn from_vec(vec: Vec>) -> Self { + Self { + population: vec + } + } + + pub fn best_candidate(&self, better_than: &impl BetterThanOperator) -> &EvaluatedChromosome { + 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) { + self.population.push(c) + } + + pub fn deconstruct(self) -> Vec> { + self.population + } + + pub fn join(&mut self, mut offsprings: EvaluatedPopulation) { + self.population.append(&mut offsprings.population); + } + + pub fn iter(&self) -> impl Iterator> { + self.population.iter() + } + + pub fn iter_mut(&mut self) -> impl Iterator> { + self.population.iter_mut() + } + +} + +impl EvaluatedPopulation { + pub fn evaluations_vec(&self) -> Vec { + self.population + .iter() + .map(|individual| individual.evaluation) + .collect() + } +} diff --git a/codes/eoa_lib/src/replacement.rs b/codes/eoa_lib/src/replacement.rs index 5de7fae4b3b39260fd18a36be39fc901f3d8a5e4..bc4358b4e3288c4014ae40b94e89b1e8f8fae87b 100644 --- a/codes/eoa_lib/src/replacement.rs +++ b/codes/eoa_lib/src/replacement.rs @@ -1,7 +1,7 @@ use rand::{seq::IteratorRandom, RngCore}; use std::fmt::Debug; -use crate::{comparison::BetterThanOperator, fitness::FitnessFunction, selection::{Selection, TournamentSelection}}; +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)); @@ -17,143 +17,6 @@ fn extract_by_indices(mut x: Vec, mut idxs: Vec) -> Vec { result } -#[derive(Clone, Debug)] -pub struct Population { - population: Vec -} - -#[derive(Clone, Debug)] -pub struct EvaluatedChromosome { - pub chromosome: TChromosome, - pub evaluation: TResult, -} - -#[derive(Clone, Debug)] -pub struct EvaluatedPopulation { - pub population: Vec> -} - -impl Population { - pub fn from_vec(vec: Vec) -> Self { - Self { - population: vec - } - } - - pub fn from_iterator(iter: impl Iterator) -> Self { - Self::from_vec(iter.collect()) - } - - pub fn evaluate>(self, func: &T) -> Result, T::Err> { - EvaluatedPopulation::evaluate( - self.population, - func - ) - } - - pub fn evaluate_mut(self, func: &mut dyn FnMut(&TChromosome) -> TResult) -> EvaluatedPopulation { - EvaluatedPopulation::evaluate_mut( - self.population, - func - ) - } - - pub fn into_iter(self) -> impl Iterator { - self.population.into_iter() - } - - pub fn iter(&self) -> impl Iterator { - self.population.iter() - } - - pub fn iter_mut(&mut self) -> impl Iterator { - self.population.iter_mut() - } -} - -impl EvaluatedChromosome { - pub fn deconstruct(self) -> (TInput, TResult) { - (self.chromosome, self.evaluation) - } -} - -impl EvaluatedPopulation { - pub fn new() -> Self { - Self { - population: vec![] - } - } - - pub fn evaluate>(chromosomes: Vec, func: &T) -> Result { - Ok(EvaluatedPopulation::from_vec( - chromosomes.into_iter() - .map(|chromosome| - Ok(EvaluatedChromosome { - evaluation: func.fit(&chromosome)?, - chromosome - })) - .collect::>()?)) - } - - pub fn evaluate_mut(chromosomes: Vec, func: &mut dyn FnMut(&TChromosome) -> TResult) -> Self { - EvaluatedPopulation::from_vec( - chromosomes.into_iter() - .map(|chromosome| - EvaluatedChromosome { - evaluation: func(&chromosome), - chromosome - }) - .collect::>()) - } - - pub fn from_vec(vec: Vec>) -> Self { - Self { - population: vec - } - } - - pub fn best_candidate(&self, better_than: &impl BetterThanOperator) -> &EvaluatedChromosome { - 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) { - self.population.push(c) - } - - pub fn deconstruct(self) -> Vec> { - self.population - } - - fn join(&mut self, mut offsprings: EvaluatedPopulation) { - self.population.append(&mut offsprings.population); - } - - pub fn iter(&self) -> impl Iterator> { - self.population.iter() - } - - pub fn iter_mut(&mut self) -> impl Iterator> { - self.population.iter_mut() - } - -} - -impl EvaluatedPopulation { - pub fn evaluations_vec(&self) -> Vec { - self.population - .iter() - .map(|individual| individual.evaluation) - .collect() - } -} - pub trait Replacement { fn replace( &self, diff --git a/codes/eoa_lib/src/selection.rs b/codes/eoa_lib/src/selection.rs index ca1e4f6f8527afea0f831b15c1cb7885bf1df69b..6c67ba3c9f1cb73078e5ce71cde408d9c14f7d9c 100644 --- a/codes/eoa_lib/src/selection.rs +++ b/codes/eoa_lib/src/selection.rs @@ -3,7 +3,7 @@ use rand::{seq::IteratorRandom, Rng, RngCore}; use rand_distr::uniform::{SampleRange, SampleUniform}; use std::{cmp::Ordering, fmt::Debug, ops::{AddAssign, Sub}}; -use crate::{comparison::BetterThanOperator, replacement::EvaluatedPopulation}; +use crate::{comparison::BetterThanOperator, population::EvaluatedPopulation}; pub trait Selection { fn select(&self, diff --git a/codes/tsp_hw01/src/crossovers.rs b/codes/tsp_hw01/src/crossovers.rs index d6eb4e917f4e6f518102b6366237ab095ffa8bbd..59085eb89fb5bcece9ef81ab9f72c21df08c6a47 100644 --- a/codes/tsp_hw01/src/crossovers.rs +++ b/codes/tsp_hw01/src/crossovers.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; use nalgebra::{allocator::Allocator, Const, DefaultAllocator, Dim, OMatrix, OVector, U1}; use rand::{prelude::IteratorRandom, Rng, RngCore}; -use eoa_lib::replacement::Population; +use eoa_lib::population::Population; use itertools::Itertools; use eoa_lib::crossover::Crossover; use crate::tsp::NodePermutation; @@ -26,7 +26,7 @@ where fn crossover( &self, - parents: &eoa_lib::replacement::EvaluatedPopulation, + parents: &eoa_lib::population::EvaluatedPopulation, pairs: impl Iterator>, _: &mut dyn RngCore ) -> Population { @@ -62,10 +62,10 @@ where fn crossover( &self, - parents: &eoa_lib::replacement::EvaluatedPopulation, + parents: &eoa_lib::population::EvaluatedPopulation, pairs: impl Iterator>, rng: &mut dyn RngCore - ) -> eoa_lib::replacement::Population { + ) -> eoa_lib::population::Population { let mut offsprings = vec![]; let permutation = &parents.population[0].chromosome.permutation; @@ -225,7 +225,7 @@ where fn crossover( &self, - parents: &eoa_lib::replacement::EvaluatedPopulation, + parents: &eoa_lib::population::EvaluatedPopulation, pairs: impl Iterator>, rng: &mut dyn RngCore ) -> Population { @@ -309,7 +309,7 @@ where fn crossover( &self, - parents: &eoa_lib::replacement::EvaluatedPopulation, + parents: &eoa_lib::population::EvaluatedPopulation, pairs: impl Iterator>, rng: &mut dyn RngCore ) -> Population { @@ -343,7 +343,7 @@ mod tests { use std::convert::Infallible; use nalgebra::{SVector, U6}; use rand::{rngs::StdRng, RngCore, SeedableRng}; - use eoa_lib::{fitness::FitnessFunction, initializer::Initializer, pairing::{AdjacentPairing, Pairing}, replacement::Population}; + use eoa_lib::{fitness::FitnessFunction, initializer::Initializer, pairing::{AdjacentPairing, Pairing}, population::Population}; use crate::initializers::TSPRandomInitializer; use crate::tsp::{NodePermutation, TSPInstance}; diff --git a/codes/tsp_hw01/src/main.rs b/codes/tsp_hw01/src/main.rs index c17fe564492cb5f2b1df65a964718373119ddd9b..d23a9b1f40b637ffcb85ab40453086186085907e 100644 --- a/codes/tsp_hw01/src/main.rs +++ b/codes/tsp_hw01/src/main.rs @@ -262,7 +262,7 @@ fn run_evolution_algorithm(instance: &TSPInstance) -> Result) -> Result) -> Result) -> Result) -> Result) -> Result) -> Result