1use std::sync::Arc;
2
3use crate::engines::alterers::alter::Alter;
4use crate::engines::genetic_engine_params::GeneticEngineParams;
5use crate::engines::genome::genes::gene::Gene;
6use crate::engines::genome::population::Population;
7use crate::engines::optimize::Optimize;
8use crate::engines::schema::timer::Timer;
9use crate::engines::score::Score;
10
11use super::engine_context::EngineContext;
12use super::genome::phenotype::Phenotype;
13use super::selectors::selector::Select;
14use super::codexes::Codex;
15
16pub struct GeneticEngine<'a, G, A, T>
17where
18 G: Gene<G, A>,
19 T: Clone,
20{
21 pub params: GeneticEngineParams<'a, G, A, T>,
22}
23
24impl<'a, G, A, T> GeneticEngine<'a, G, A, T>
25where
26 G: Gene<G, A>,
27 T: Clone
28{
29
30 pub fn new(params: GeneticEngineParams<'a, G, A, T>) -> Self {
31 GeneticEngine { params }
32 }
33
34 pub fn from_codex(codex: &'a impl Codex<G, A, T>) -> GeneticEngineParams<G, A, T> {
35 GeneticEngineParams::new().codex(codex)
36 }
37
38 pub fn run<F>(&self, limit: F) -> EngineContext<G, A, T>
39 where
40 F: Fn(&EngineContext<G, A, T>) -> bool
41 {
42 let mut ctx = self.start();
43
44 loop {
45 self.evaluate(&mut ctx);
46
47 let mut survivors = self.select_survivors(&ctx.population);
48 let mut offspring = self.select_offspring(&ctx.population);
49
50 self.alter(&mut offspring, ctx.index);
51
52 self.filter(&mut survivors, ctx.index);
53 self.filter(&mut offspring, ctx.index);
54
55 self.recombine(&mut ctx, survivors, offspring);
56
57 self.evaluate(&mut ctx);
58 self.audit(&mut ctx);
59
60 if limit(&ctx) {
61 break self.stop(&mut ctx)
62 }
63 }
64 }
65
66 fn evaluate(&self, handle: &mut EngineContext<G, A, T>) {
67 let codex = self.codex();
68 let fitness_fn = self.fitness_fn();
69 let optimize = self.optimize();
70
71 for idx in 0..handle.population.len() {
72 let individual = handle.population.get_mut(idx);
73 if !individual.score().is_some() {
74 let decoded = codex.decode(individual.genotype());
75 let score = fitness_fn(decoded);
76
77 individual.set_score(Some(score));
78 }
79 }
80
81 optimize.sort(&mut handle.population);
82 }
83
84 fn select_survivors(&self, population: &Population<G, A>) -> Population<G, A> {
85 let selector = self.survivor_selector();
86 let count = self.survivor_count();
87 let optimize = self.optimize();
88
89 selector.select(population, optimize, count)
90 }
91
92 fn select_offspring(&self, population: &Population<G, A>) -> Population<G, A> {
93 let selector = self.offspring_selector();
94 let count = self.offspring_count();
95 let optimize = self.optimize();
96
97 selector.select(population, optimize, count)
98 }
99
100 fn alter(&self, population: &mut Population<G, A>, generation: i32) {
101 let alterer = self.alterer();
102 let optimize = self.optimize();
103
104 alterer.alter(population, optimize, generation);
105 }
106
107 fn filter(&self, population: &mut Population<G, A>, generation: i32) {
108 let max_age = self.params.max_age;
109 let codex = self.codex();
110
111 for i in 0..population.len() {
112 let phenotype = population.get(i);
113
114 if phenotype.age(generation) > max_age {
115 population.set(i, Phenotype::from_genotype(codex.encode(), generation));
116 } else if !phenotype.genotype().is_valid() {
117 population.set(i, Phenotype::from_genotype(codex.encode(), generation));
118 }
119 }
120 }
121
122 fn recombine(&self, handle: &mut EngineContext<G, A, T>, survivors: Population<G, A>, offspring: Population<G, A>) {
123 handle.population = survivors
124 .into_iter()
125 .chain(offspring.into_iter())
126 .collect::<Population<G, A>>();
127 }
128
129 fn audit(&self, output: &mut EngineContext<G, A, T>) {
130 let codex = self.codex();
131 let optimize = self.optimize();
132
133 if !output.population.is_sorted {
134 self.optimize().sort(&mut output.population);
135 }
136
137 if let Some(current_score) = &output.score {
138 if let Some(best_score) = output.population.get(0).score() {
139 if optimize.is_better(best_score, ¤t_score) {
140 output.score = Some(best_score.clone());
141 output.best = codex.decode(&output.population.get(0).genotype());
142 }
143 }
144 } else {
145 output.score = output.population.get(0).score().clone();
146 output.best = codex.decode(&output.population.get(0).genotype());
147 }
148
149 output.index += 1;
150 }
151
152 fn survivor_selector(&self) -> &impl Select<G, A> {
153 &self.params.survivor_selector
154 }
155
156 fn offspring_selector(&self) -> &impl Select<G, A> {
157 &self.params.offspring_selector
158 }
159
160 fn alterer(&self) -> &impl Alter<G, A> {
161 self.params.alterer.as_ref().unwrap()
162 }
163
164 fn codex(&self) -> &Arc<&'a dyn Codex<G, A, T>> {
165 self.params.codex.as_ref().unwrap()
166 }
167
168 fn fitness_fn(&self) -> &Arc<dyn Fn(T) -> Score> {
169 self.params.fitness_fn.as_ref().unwrap()
170 }
171
172 fn population(&self) -> &Population<G, A> {
173 self.params.population.as_ref().unwrap()
174 }
175
176 fn optimize(&self) -> &Optimize {
177 &self.params.optimize
178 }
179
180 fn survivor_count(&self) -> usize {
181 self.params.population_size - self.offspring_count()
182 }
183
184 fn offspring_count(&self) -> usize {
185 (self.params.population_size as f32 * self.params.offspring_fraction) as usize
186 }
187
188 fn start(&self) -> EngineContext<G, A, T> {
189 let population = self.population();
190
191 EngineContext {
192 population: population.clone(),
193 best: self.codex().decode(&population.get(0).genotype()),
194 index: 0,
195 timer: Timer::new(),
196 score: None
197 }
198 }
199
200 fn stop(&self, output: &mut EngineContext<G, A, T>) -> EngineContext<G, A, T> {
201 output.timer.stop();
202 output.clone()
203 }
204}