~ruther/ctu-fee-eoa

51a8da0c55de6d386aca5f541e47e514f5c7dda5 — Rutherther 11 days ago 41658e7
refactor: add possibility to use different logic for obtaining best candidate
1 files changed, 66 insertions(+), 11 deletions(-)

M codes/eoa_lib/src/evolution.rs
M codes/eoa_lib/src/evolution.rs => codes/eoa_lib/src/evolution.rs +66 -11
@@ 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,
        &current_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,
            &current_population,
          &mut last_best_candidate);
            &mut last_best_candidate,
            &better_than_stats
        );

        // Replace
        current_population = replacement.replace(current_population, evaluated_offsprings, better_than, rng);