@@ 101,6 101,64 @@ pub fn evolution_algorithm
&mut TReplacement
)
) -> Result<EvolutionResult<TChromosome, TResult>, Box<dyn Error>> {
+ evolution_algorithm_best_candidate(
+ initial_population,
+ parents_count,
+ fitness,
+ selection,
+ pairing,
+ crossover,
+ perturbation,
+ replacement,
+ better_than,
+ iterations,
+ rng,
+ evolutionary_strategy,
+ |_, evaluation, last_best_candidate| last_best_candidate.is_none() ||
+ better_than.better_than(
+ evaluation,
+ &last_best_candidate.as_ref().unwrap().evaluated_chromosome.evaluation
+ ))
+}
+
+pub fn evolution_algorithm_best_candidate
+ <TChromosome: Clone,
+ TResult: Clone,
+ const DParents: usize,
+ TSelection: Selection<TChromosome, TResult>,
+ TFitness: FitnessFunction<In = TChromosome, Out = TResult>,
+ TPairing: Pairing<DParents, Chromosome = TChromosome, Out = TResult>,
+ TCrossover: Crossover<DParents, Chromosome = TChromosome, Out = TResult>,
+ TReplacement: Replacement<TChromosome, TResult>,
+ TPerturbation: PerturbationOperator<Chromosome = TChromosome>>(
+ initial_population: Population<TChromosome>,
+ parents_count: usize,
+ fitness: &mut TFitness,
+ selection: &mut TSelection,
+ pairing: &mut TPairing,
+ crossover: &mut TCrossover,
+ perturbation: &mut TPerturbation,
+ replacement: &mut TReplacement,
+ better_than: &impl BetterThanOperator<TResult>,
+ // TODO: termination condition
+ iterations: usize,
+ rng: &mut dyn RngCore,
+ mut evolutionary_strategy: impl FnMut(
+ usize,
+ &EvolutionStats<TChromosome, TResult>,
+ &EvaluatedPopulation<TChromosome, TResult>,
+
+ &mut TFitness,
+ &mut TSelection,
+ &mut TPairing,
+ &mut TCrossover,
+ &mut TPerturbation,
+ &mut TReplacement
+ ),
+ // For the statistics, evaluate if a candidate is better. Potential for different functrion than better_than that's used
+ // for the replacement, selection etc.
+ better_than_stats: impl Fn(&TChromosome, &TResult, &Option<EvolutionCandidate<TChromosome, TResult>>) -> bool,
+) -> Result<EvolutionResult<TChromosome, TResult>, Box<dyn Error>> {
let mut current_evaluation = 0;
let mut last_best_candidate: Option<EvolutionCandidate<TChromosome, TResult>> = None;
@@ 110,21 168,17 @@ pub fn evolution_algorithm
fn apply_new_eval<TChromosome: Clone, TResult: Clone>(
current_evaluation: &mut usize,
- better_than: &impl BetterThanOperator<TResult>,
current_iteration: &usize,
stats: &mut EvolutionStats<TChromosome, TResult>,
population: &EvaluatedPopulation<TChromosome, TResult>,
- last_best_candidate: &mut Option<EvolutionCandidate<TChromosome, TResult>>
+ last_best_candidate: &mut Option<EvolutionCandidate<TChromosome, TResult>>,
+ better_than_stats: &impl Fn(&TChromosome, &TResult, &Option<EvolutionCandidate<TChromosome, TResult>>) -> bool,
) {
for individual in population.iter() {
let evaluation = &individual.evaluation;
let chromosome = &individual.chromosome;
- if last_best_candidate.is_none() ||
- better_than.better_than(
- evaluation,
- &last_best_candidate.as_ref().unwrap().evaluated_chromosome.evaluation
- ) {
+ if better_than_stats(chromosome, evaluation, last_best_candidate) {
let previous_best = std::mem::replace(
last_best_candidate,
Some(EvolutionCandidate {
@@ 148,11 202,11 @@ pub fn evolution_algorithm
initial_population.evaluate(fitness)?;
apply_new_eval(
&mut current_evaluation,
- better_than,
&0,
&mut stats,
¤t_population,
- &mut last_best_candidate);
+ &mut last_best_candidate,
+ &better_than_stats);
for iteration in 1..=iterations {
// Selection
@@ 171,11 225,12 @@ pub fn evolution_algorithm
offsprings.evaluate(fitness)?;
apply_new_eval(
&mut current_evaluation,
- better_than,
&iteration,
&mut stats,
¤t_population,
- &mut last_best_candidate);
+ &mut last_best_candidate,
+ &better_than_stats
+ );
// Replace
current_population = replacement.replace(current_population, evaluated_offsprings, better_than, rng);