1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//! Termination determines when to stop the process of the genetic algorithm.
//! Common termination conditions are:
//!
//! * A solution is found that satisfies minimum criteria
//! * A fixed number of generations is reached
//! * An allocated budget (computation time/money) is reached
//! * The highest ranking solution's fitness is reaching or has reached a
//!   plateau such that successive iterations no longer produce better results
//! * ...or a combination of such termination conditions.
//!
//! Termination conditions are defined by implementing the `Termination` trait.
//! Each kind of termination condition should be implemented as a separate
//! type. Terminations conditions are combined using combinators such as
//! logical and and logical or.
//!
//! A combinator is a special `Termination` condition that combines two other
//! `Termination` conditions with a logical operation. The most important
//! combinators are provided in the `combinator` package.
//!
//! For convenience the provided combinators can be instantiated by using
//! the public functions `and` and `or` which are reexported by this module.

pub mod combinator;
pub use self::combinator::{and, or};

pub mod limit;

use crate::{algorithm::Algorithm, simulation::State};

/// The `StopFlag` is the result of the `Termination` function. It tells
/// the simulation whether it shall stop or if it can continue.
///
/// If the `StopFlag` indicates that the simulation must stop, also the reason
/// (`StopReason`) must be specified.
#[derive(Clone, Debug, PartialEq)]
pub enum StopFlag {
    /// Flag for 'Stop the simulation now'.
    StopNow(StopReason),
    /// Flag for 'Continue with the simulation'.
    Continue,
}

/// A `StopReason` should explain to the user of the simulation why the
/// simulation has been stopped. Examples:
/// * "Simulation stopped after the maximum of 100 generations have been
///   processed"
/// * "Simulation stopped after a solution with a fitness value of 81 has
///   been found which is above the target fitness of 80.
pub type StopReason = String;

/// A `Termination` defines a condition when the `Simulation` shall stop.
///
/// One implementation of the trait `Termination` should only handle one
/// single termination condition. In the simulation multiple termination
/// conditions can be combined through `combinator`s.
pub trait Termination<A>
where
    A: Algorithm,
{
    /// Evaluates the termination condition and returns a `StopFlag` depending
    /// on the result. The `StopFlag` indicates whether the simulation shall
    /// stop or continue.
    ///
    /// In case the simulation shall be stopped, i.e. a `StopFlag::StopNow` is
    /// returned also a the reason why the simulation shall be stopped is
    /// returned. This reason should explain to the user of the simulation,
    /// why the simulation has been stopped.
    fn evaluate(&mut self, state: &State<A>) -> StopFlag;

    /// Resets the state of this `Termination` condition. This function is
    /// called on each `Termination` instance when the simulation is reset.
    ///
    /// This function only needs to be implemented by an implementation of
    /// `Termination` if it has its own state, e.g. for counting or tracking
    /// of progress.
    ///
    /// The default implementation does nothing.
    fn reset(&mut self) {}
}