Termination Criteria Reference

Termination criteria define when evolution should stop.

Module

use fugue_evo::termination::{
    MaxGenerations, MaxEvaluations, TargetFitness,
    FitnessStagnation, DiversityThreshold, AnyOf, AllOf
};

Trait

pub trait TerminationCriterion<G, F>: Send + Sync {
    fn should_terminate(&self, state: &EvolutionState<G, F>) -> bool;
}

Built-in Criteria

MaxGenerations

Stop after N generations.

let term = MaxGenerations::new(500);

MaxEvaluations

Stop after N fitness evaluations.

let term = MaxEvaluations::new(100000);

TargetFitness

Stop when fitness threshold reached.

let term = TargetFitness::new(threshold);

For minimization (negated fitness):

let term = TargetFitness::new(-0.001);  // Stop when fitness >= -0.001

FitnessStagnation

Stop if no improvement for N generations.

let term = FitnessStagnation::new(generations);
ParameterDescription
generationsGenerations without improvement

DiversityThreshold

Stop when population diversity falls below threshold.

let term = DiversityThreshold::new(threshold);

Combinators

AnyOf

Stop when ANY criterion is met (OR).

let term = AnyOf::new(vec![
    Box::new(MaxGenerations::new(1000)),
    Box::new(TargetFitness::new(-0.001)),
    Box::new(FitnessStagnation::new(50)),
]);

AllOf

Stop when ALL criteria are met (AND).

let term = AllOf::new(vec![
    Box::new(MinGenerations::new(100)),  // At least 100 generations
    Box::new(FitnessStagnation::new(20)), // And stagnated
]);

Usage

With Builder

SimpleGABuilder::new()
    .max_generations(200)  // Shorthand for MaxGenerations
    // ...

Custom Termination

SimpleGABuilder::new()
    .termination(AnyOf::new(vec![
        Box::new(MaxGenerations::new(1000)),
        Box::new(TargetFitness::new(-0.001)),
    ]))
    // ...

Termination Reason

Results include termination reason:

let result = ga.run(&mut rng)?;
println!("Stopped because: {:?}", result.termination_reason);

Custom Criteria

struct TimeBudget {
    start: Instant,
    budget: Duration,
}

impl<G, F> TerminationCriterion<G, F> for TimeBudget {
    fn should_terminate(&self, _state: &EvolutionState<G, F>) -> bool {
        self.start.elapsed() >= self.budget
    }
}

// Usage
let term = TimeBudget {
    start: Instant::now(),
    budget: Duration::from_secs(60),
};

Recommendations

ScenarioRecommended
Unknown runtimeAnyOf(MaxGen, Stagnation)
Known optimumAnyOf(MaxGen, TargetFitness)
Time-limitedCustom TimeBudget
ResearchMaxGenerations for reproducibility

See Also