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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use super::Probe;
use crate::ga::{individual::IndividualTrait, GAMetadata};
/// Wrapper probe. It holds a list of probes and calls them sequentially.
///
/// This structs implements [Probe] trait and can be used with GA
pub struct AggregatedProbe<IndividualT: IndividualTrait> {
probes: Vec<Box<dyn Probe<IndividualT>>>,
}
impl<IndividualT: IndividualTrait> AggregatedProbe<IndividualT> {
/// Returns new instance of [AggregatedProbe]
pub fn new() -> Self {
Self { probes: Vec::new() }
}
/// Add probe to list
///
/// **Note**: Probes will be called in order they were added
pub fn add_probe<Pr: Probe<IndividualT> + 'static>(mut self, probe: Pr) -> Self {
self.probes.push(Box::new(probe));
self
}
}
impl<IndividualT: IndividualTrait> Probe<IndividualT> for AggregatedProbe<IndividualT> {
/// This method is called in the very beginning of genetic algorithm, even before
/// initial population is generated.
///
/// Calls all the probes sequentially
///
/// ### Arguments
///
/// * `metadata` - Structure containing metadata information on genetic algorithm.
/// See [GAMetadata] for reference. When running this method only `start_time`
/// field has meaningful value.
fn on_start(&mut self, metadata: &GAMetadata) {
for probe in &mut self.probes {
probe.on_start(metadata);
}
}
/// This method is called directly after initial populationn is created and fitness
/// of the individuals is evaluated
///
/// Calls all the probes sequentially
///
/// ### Arguments
///
/// * `population` - Freshly generated population
fn on_initial_population_created(&mut self, population: &[IndividualT]) {
for probe in &mut self.probes {
probe.on_initial_population_created(population);
}
}
/// This method is called every time new best individual is found (irrespectively of generation)
///
/// Calls all the probes sequentially
///
/// ### Arguments
///
/// * `metadata` - Structure containing metadata information on genetic algorithm.
/// See [GAMetadata] for reference.
/// * `individual` - New best individual
fn on_new_best(&mut self, metadata: &GAMetadata, individual: &IndividualT) {
for probe in &mut self.probes {
probe.on_new_best(metadata, individual);
}
}
/// This method is called every time a new generation is created (but not for initial population)
///
/// Calls all the probes sequentially
///
/// ### Arguments
///
/// * `generation` - Newly created generation
fn on_new_generation(&mut self, metadata: &GAMetadata, generation: &[IndividualT]) {
/* defaults to noop */
for probe in &mut self.probes {
probe.on_new_generation(metadata, generation);
}
}
/// This method is called once per generation with best individual in it
///
/// Calls all the probes sequentially
///
/// ### Arguments
///
/// * `metadata` - Structure containing metadata information on genetic algorithm.
/// See [GAMetadata] for reference.
/// * `individual` - Best individual in current generation
fn on_best_fit_in_generation(&mut self, metadata: &GAMetadata, individual: &IndividualT) {
for probe in &mut self.probes {
probe.on_best_fit_in_generation(metadata, individual);
}
}
/// This method is called in the very begining of algorithm's main loop
///
/// Calls all the probes sequentially
///
/// ### Arguments
///
/// * `metadata` - Structure containing metadata information on genetic algorithm.
/// See [GAMetadata] for reference.
fn on_iteration_start(&mut self, metadata: &GAMetadata) {
/* defaults to noop */
for probe in &mut self.probes {
probe.on_iteration_start(metadata);
}
}
/// This method is called in the very end of algorithm's main loop, just before
/// termination conditions are evaluated
///
/// Calls all the probes sequentially
///
/// ### Arguments
///
/// * `metadata` - Structure containing metadata information on genetic algorithm.
/// See [GAMetadata] for reference.
fn on_iteration_end(&mut self, metadata: &GAMetadata) {
/* defaults to noop */
for probe in &mut self.probes {
probe.on_iteration_end(metadata);
}
}
/// This method is called after algorithm 's main loop is exited, just before the `run`
/// method returns
///
/// Calls all the probes sequentially
///
/// ### Arguments
///
/// * `metadata` - Structure containing metadata information on genetic algorithm.
/// See [GAMetadata] for reference.
/// * `population` - Final population
/// * `best_individual` - Best individual found by algorithm
fn on_end(&mut self, metadata: &GAMetadata, population: &[IndividualT], best_individual: &IndividualT) {
for probe in &mut self.probes {
probe.on_end(metadata, population, best_individual);
}
}
}