1use core::fmt;
5use rand::Rng;
6use std::error::Error;
7
8use crate::logger;
9use crate::selection::*;
10use crate::Gene;
11
12const POPULATION_SIZE_DEFAULT: usize = 100;
14const MAX_ITERATIONS_DEFAULT: u32 = 1000;
16const MUTATION_RATE_DEFAULT: f32 = 0.05;
18const SELECTION_RATE_DEFAULT: f32 = 0.90;
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
23pub enum StopCriteria {
24 MaxIterations,
25 FitnessAchieved,
26 Unknown,
27}
28
29pub struct GeneticAlgorithm<T: Gene + Copy> {
31 population_size: usize,
33 iterations: u32,
35 current_iteration: u32,
37 generation: Vec<T>,
39 generation_historic: Vec<Vec<T>>,
41 mutation_rate: f32,
43 selection_rate: f32,
48 selection_algorithm: Box<dyn Selection>,
50 fitness_goal: f64,
52 running: bool,
54 best_gene: T,
56 stop_criteria: StopCriteria,
58}
59
60impl<T: Gene + Copy> GeneticAlgorithm<T> {
61 pub fn new() -> Self {
69 let generation = (0..POPULATION_SIZE_DEFAULT).map(|_| T::init()).collect();
70 let generation_historic = vec![Vec::clone(&generation)];
71 let return_value = GeneticAlgorithm {
72 population_size: POPULATION_SIZE_DEFAULT,
73 iterations: MAX_ITERATIONS_DEFAULT,
74 current_iteration: 0,
75 generation,
76 generation_historic,
77 mutation_rate: MUTATION_RATE_DEFAULT,
78 selection_rate: SELECTION_RATE_DEFAULT,
79 selection_algorithm: Box::new(SelectionAlgorithms::Tournament(2)),
80 fitness_goal: f64::MAX,
81 running: false,
82 best_gene: T::init(),
83 stop_criteria: StopCriteria::Unknown,
84 };
85
86 logger::LOG(
87 logger::VerbosityLevel::LOW,
88 format!(
89 "GeneticAlgorithm created with default values:\n{}",
90 return_value
91 )
92 .as_str(),
93 );
94
95 return_value
96 }
97
98 pub fn new_with_values(
109 population_size: usize,
110 iterations: u32,
111 mutation_rate: f32,
112 selection_rate: f32,
113 selection_algorithm: Box<dyn Selection>,
114 fitness_goal: f64,
115 ) -> Self {
116 if mutation_rate > 1.0 || mutation_rate < 0.0 {
117 panic!("Mutation rate not in rage between 0.0 and 1.0");
118 }
119
120 if selection_rate > 1.0 || selection_rate < 0.0 {
121 panic!("Selection rate not in rage between 0.0 and 1.0");
122 }
123
124 let generation = (0..population_size).map(|_| T::init()).collect();
125 let generation_historic = vec![vec![]];
126 let return_value = GeneticAlgorithm {
127 population_size,
128 iterations,
129 current_iteration: 0,
130 generation,
131 generation_historic,
132 mutation_rate,
133 selection_rate,
134 selection_algorithm,
135 fitness_goal,
136 running: false,
137 best_gene: T::init(),
138 stop_criteria: StopCriteria::Unknown,
139 };
140
141 logger::LOG(
142 logger::VerbosityLevel::LOW,
143 format!("GeneticAlgorithm created with values:\n{}", return_value).as_str(),
144 );
145
146 return_value
147 }
148
149 pub fn init(mut self) -> Result<Self, Box<dyn Error>> {
152 self.running = true;
153 self.save_generation();
154 logger::LOG(
155 logger::VerbosityLevel::HIGH,
156 "Algorithm initiated properlly.",
157 );
158 Ok(self)
159 }
160
161 pub fn run(mut self) -> (T, StopCriteria) {
163 if !self.is_running() {
164 self = self.init().unwrap();
165 }
166
167 logger::LOG(logger::VerbosityLevel::HIGH, "Algorithm run started.");
168
169 while self.running {
170 self.next_iteration();
171 }
172
173 (self.best_gene, self.stop_criteria)
174 }
175
176 pub fn next_iteration(&mut self) -> &Vec<T> {
182 logger::LOG(
183 logger::VerbosityLevel::LOW,
184 format!(
185 ">>>>>>> Started iteration {} <<<<<<<",
186 self.current_iteration
187 )
188 .as_str(),
189 );
190
191 logger::LOG(
192 logger::VerbosityLevel::HIGH,
193 ">> Fitness calculation phase.",
194 );
195 for (i, gene) in self.generation.iter_mut().enumerate() {
197 gene.calculate_fitness();
198 logger::LOG(
199 logger::VerbosityLevel::MID,
200 format!("Gene {i} = {:?}", gene.get_fitness()).as_str(),
201 );
202 }
203
204 logger::LOG(logger::VerbosityLevel::HIGH, ">> Selection phase.");
205 let mut new_generation: Vec<T> = Vec::with_capacity(self.population_size);
207 let num_survivors: usize = (self.generation.len() as f32 * self.selection_rate) as usize;
208 let mut new_genes_num: usize = 0;
209
210 logger::LOG(
211 logger::VerbosityLevel::MID,
212 format!("Number of survivors = {:?}", num_survivors).as_str(),
213 );
214 while new_genes_num < num_survivors {
215 let gene_idx: usize = self.selection_algorithm.select(
216 &self
217 .generation
218 .iter()
219 .map(|gene| gene.get_fitness())
220 .collect(),
221 );
222 new_generation.push(self.generation[gene_idx]);
223 self.generation.remove(gene_idx);
224 new_genes_num += 1;
225 }
226
227 logger::LOG(logger::VerbosityLevel::HIGH, ">> Crossover phase.");
228 let mut rng = rand::thread_rng();
230 while new_genes_num < self.population_size {
231 let gen1_idx = rng.gen_range(0..new_generation.len());
232 let mut gen2_idx = gen1_idx;
233 while gen2_idx == gen1_idx {
234 gen2_idx = rng.gen_range(0..new_generation.len());
235 }
236 let gen1 = new_generation[gen1_idx];
237 let crossover_gen = gen1.crossover(&new_generation[gen2_idx]);
238 new_generation.push(crossover_gen);
239 new_genes_num += 1;
240 logger::LOG(
241 logger::VerbosityLevel::MID,
242 format!(
243 "Crossover between gen1({:?}) and gen2({:?})",
244 gen1.get_fitness(),
245 new_generation[gen2_idx].get_fitness()
246 )
247 .as_str(),
248 );
249 }
250
251 logger::LOG(logger::VerbosityLevel::HIGH, ">> Mutation phase.");
252 let mut num_of_mutations = 0;
254 for gen in new_generation.iter_mut() {
255 if rng.gen_range(0.0..1.0) < self.mutation_rate {
256 gen.mutate();
257 num_of_mutations += 1;
258 }
259 }
260 logger::LOG(
261 logger::VerbosityLevel::MID,
262 format!("{} mutations performed.", num_of_mutations).as_str(),
263 );
264
265 self.generation = new_generation;
267 self.save_generation();
268
269 self.current_iteration += 1;
270
271 self.check_stop_criteria();
273
274 &self.generation
275 }
276
277 fn save_generation(&mut self) {
279 logger::LOG(logger::VerbosityLevel::HIGH, ">> Saving generation data.");
280 self.generation_historic.push(Vec::clone(&self.generation));
281
282 let mut best_fitness: f64 = self.best_gene.get_fitness();
283
284 for gene in self.generation.iter() {
285 if gene.get_fitness() > best_fitness {
286 self.best_gene = *gene;
287 best_fitness = gene.get_fitness();
288 }
289 }
290 logger::LOG(
291 logger::VerbosityLevel::LOW,
292 format!("Best gene with fitness = {:?}", best_fitness).as_str(),
293 );
294 }
295
296 fn check_stop_criteria(&mut self) {
298 if self.best_gene.get_fitness() >= self.fitness_goal {
299 self.running = false;
300 self.stop_criteria = StopCriteria::FitnessAchieved;
301 logger::LOG(
302 logger::VerbosityLevel::LOW,
303 format!("Algorithm must stop because of {:?}", self.stop_criteria).as_str(),
304 );
305 }
306
307 if self.current_iteration >= self.iterations {
308 self.running = false;
309 self.stop_criteria = StopCriteria::MaxIterations;
310 logger::LOG(
311 logger::VerbosityLevel::LOW,
312 format!("Algorithm must stop because of {:?}", self.stop_criteria).as_str(),
313 );
314 }
315 }
316
317 pub fn population_size(mut self, population_size: usize) -> Self {
323 if population_size >= self.population_size {
324 self.generation
325 .extend((0..population_size - self.generation.len()).map(|_| T::init()));
326 } else {
327 self.generation.resize(population_size, T::init());
328 }
329 self.population_size = population_size;
330 self
331 }
332
333 pub fn iterations(mut self, iterations: u32) -> Self {
339 if iterations <= self.current_iteration {
340 panic!("Number of iterations is not greater than the actual iteration.");
341 }
342
343 self.iterations = iterations;
344 self
345 }
346
347 pub fn mutation_rate(mut self, mutation_rate: f32) -> Self {
349 if mutation_rate > 1.0 || mutation_rate < 0.0 {
350 panic!("Mutation rate not in rage between 0.0 and 1.0");
351 }
352
353 self.mutation_rate = mutation_rate;
354 self
355 }
356
357 pub fn selection_rate(mut self, selection_rate: f32) -> Self {
359 if selection_rate > 1.0 || selection_rate < 0.0 {
360 panic!("Selection rate not in rage between 0.0 and 1.0");
361 }
362
363 self.selection_rate = selection_rate;
364 self
365 }
366
367 pub fn selection_algorithm(mut self, selection_algorithm: Box<dyn Selection>) -> Self {
369 self.selection_algorithm = selection_algorithm;
370 self
371 }
372
373 pub fn fitness_goal(mut self, fitness_goal: f64) -> Self {
375 self.fitness_goal = fitness_goal;
376 self
377 }
378
379 pub fn get_population_size(&self) -> usize {
381 self.population_size
382 }
383
384 pub fn get_iterations(&self) -> u32 {
386 self.iterations
387 }
388
389 pub fn get_current_iteration(&self) -> u32 {
391 self.current_iteration
392 }
393
394 pub fn get_generation(&self) -> Vec<T> {
396 self.generation.clone()
397 }
398
399 pub fn get_generation_historic(&self) -> Vec<Vec<T>> {
401 self.generation_historic.clone()
402 }
403
404 pub fn get_mutation_rate(&self) -> f32 {
406 self.mutation_rate
407 }
408
409 pub fn get_selection_rate(&self) -> f32 {
411 self.selection_rate
412 }
413
414 pub fn get_fitness_goal(&self) -> f64 {
415 self.fitness_goal
416 }
417
418 pub fn get_best_gene(&self) -> T {
420 self.best_gene
421 }
422
423 pub fn is_running(&self) -> bool {
425 self.running
426 }
427
428 pub fn get_stop_criteria(&self) -> StopCriteria {
429 self.stop_criteria
430 }
431}
432
433impl<T: Gene + Copy> Default for GeneticAlgorithm<T> {
435 fn default() -> Self {
436 Self::new()
437 }
438}
439
440impl<T: Gene + Copy> fmt::Display for GeneticAlgorithm<T> {
442 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
443 write!(
444 f,
445 "{{\n\tpopulation_size: {},\n\titerations: {},\n\tcurrent_iteration: {},\n\tselection_rate: {},\n\tmutation_rate: {},\n\tfitness_goal: {:?},\n\tstop_criteria: {:?},\n\tbest_gene_fitness: {}\n}}",
446 self.population_size,
447 self.iterations,
448 self.current_iteration,
449 self.selection_rate,
450 self.mutation_rate,
451 self.fitness_goal,
452 self.stop_criteria,
453 self.best_gene.get_fitness()
454 )
455 }
456}