oxigen/stop_criteria.rs
1//! This module contains the trait definition of StopCriterion and the provided stop criteria.
2
3/// This trait can be implemented to provide a stop criterion of the genetic algorithm
4/// using the generation, the progress of the last executions, the number of solutions
5/// found and the fitness of all individuals of the population.
6pub trait StopCriterion: Send + Sync {
7 /// Returns if the genetic algorithm has finished according to the generation,
8 /// the progress of the last generations, the number of solutions found and the
9 /// fitness of the population.
10 fn stop(
11 &self,
12 generation: u64,
13 progress: f64,
14 n_solutions: usize,
15 population_fitness: &[f64],
16 ) -> bool;
17}
18
19/// Provided stop criteria.
20pub enum StopCriteria {
21 /// Stop when a solution has been found.
22 SolutionFound,
23 /// Stop when this number of solutions have been found.
24 SolutionsFound(usize),
25 /// Stop when the specified solutions have been found or a specific generation,
26 /// what happens before
27 SolutionsFoundOrGeneration(usize, u64),
28 /// Stop in a specific generation.
29 Generation(u64),
30 /// Stop when the mean progress in the last generations is lower than a specific threshold.
31 Progress(f64),
32 /// Stop when the generation is bigger than the first value and the mean progress in the last
33 /// generations is lower than the specific threshold specified as the second value.
34 GenerationAndProgress(u64, f64),
35 /// Stop when the max fitness is bigger or equal than a specific threshold.
36 MaxFitness(f64),
37 /// Stop when the min fitness is bigger or equal than a specific threshold.
38 MinFitness(f64),
39 /// Stop when the average fitness is bigger or equal than a specific threshold.
40 AvgFitness(f64),
41}
42
43impl StopCriterion for StopCriteria {
44 fn stop(
45 &self,
46 generation: u64,
47 progress: f64,
48 n_solutions: usize,
49 population_fitness: &[f64],
50 ) -> bool {
51 match self {
52 StopCriteria::SolutionFound => n_solutions > 0,
53 StopCriteria::SolutionsFound(i) => n_solutions >= *i,
54 StopCriteria::SolutionsFoundOrGeneration(i, g) => n_solutions >= *i || generation >= *g,
55 StopCriteria::Generation(g) => generation >= *g,
56 StopCriteria::Progress(p) => progress <= *p,
57 StopCriteria::GenerationAndProgress(g, p) => generation >= *g && progress <= *p,
58 StopCriteria::MaxFitness(f) => {
59 *population_fitness
60 .iter()
61 .max_by(|x, y| x.partial_cmp(&y).unwrap())
62 .unwrap()
63 >= *f
64 }
65 StopCriteria::MinFitness(f) => {
66 *population_fitness
67 .iter()
68 .min_by(|x, y| x.partial_cmp(&y).unwrap())
69 .unwrap()
70 >= *f
71 }
72 StopCriteria::AvgFitness(f) => {
73 population_fitness.iter().sum::<f64>() / population_fitness.len() as f64 >= *f
74 }
75 }
76 }
77}