radiate_rust/engines/
genetic_engine_params.rs

1use std::sync::Arc;
2
3use crate::engines::alterers::composite_alterer::CompositeAlterer;
4use crate::engines::genetic_engine::GeneticEngine;
5use crate::engines::genome::genes::gene::Gene;
6use crate::engines::genome::phenotype::Phenotype;
7use crate::engines::genome::population::Population;
8use crate::engines::optimize::Optimize;
9use crate::engines::score::Score;
10use crate::engines::selectors::selector::Selector;
11
12use super::alterers::alter::Alterer;
13use super::codexes::Codex;
14
15pub struct GeneticEngineParams<'a, G, A, T>
16where
17    G: Gene<G, A>,
18    T: Clone,
19{
20    pub population_size: usize,
21    pub max_age: i32,
22    pub offspring_fraction: f32,
23    pub optimize: Optimize,
24    pub survivor_selector: Selector,
25    pub offspring_selector: Selector,
26    pub alterer: Option<CompositeAlterer<G, A>>,
27    pub population: Option<Population<G, A>>,
28    pub codex: Option<Arc<&'a dyn Codex<G, A, T>>>,
29    pub fitness_fn: Option<Arc<dyn Fn(T) -> Score>>,
30}
31
32impl<'a, G, A, T> GeneticEngineParams<'a, G, A, T> 
33where
34    G: Gene<G, A>,
35    T: Clone,
36{
37    pub fn new() -> Self {
38        GeneticEngineParams {
39            population_size: 100,
40            max_age: 25,
41            offspring_fraction: 0.8,
42            optimize: Optimize::Maximize,
43            survivor_selector: Selector::Tournament(3),
44            offspring_selector: Selector::Roulette,
45            alterer: None,
46            codex: None,
47            population: None,
48            fitness_fn: None,
49        }
50    }
51
52    pub fn population_size(mut self, population_size: usize) -> Self {
53        self.population_size = population_size;
54        self
55    }
56
57    pub fn max_age(mut self, max_age: i32) -> Self {
58        self.max_age = max_age;
59        self
60    }
61
62    pub fn offspring_fraction(mut self, offspring_fraction: f32) -> Self {
63        self.offspring_fraction = offspring_fraction;
64        self
65    }
66
67    pub fn codex(mut self, codex: &'a impl Codex<G, A, T>) -> Self {
68        self.codex = Some(Arc::new(codex));
69        self
70    }
71
72    pub fn population(mut self, population: Population<G, A>) -> Self {
73        self.population = Some(population);
74        self
75    }
76
77    pub fn fitness_fn(mut self, fitness_func: impl Fn(T) -> Score + 'static) -> Self {
78        self.fitness_fn = Some(Arc::new(fitness_func));
79        self
80    }
81
82    pub fn survivor_selector(mut self, selector: Selector) -> Self {
83        self.survivor_selector = selector;
84        self
85    }
86
87    pub fn offspring_selector(mut self, selector: Selector) -> Self {
88        self.offspring_selector = selector;
89        self
90    }
91
92    pub fn alterer(mut self, alterers: Vec<Alterer<G, A>>) -> Self {
93        self.alterer = Some(CompositeAlterer::new(alterers));
94        self
95    }
96
97    pub fn minimizing(mut self) -> Self {
98        self.optimize = Optimize::Minimize;
99        self
100    }
101
102    pub fn maximizing(mut self) -> Self {
103        self.optimize = Optimize::Maximize;
104        self
105    }
106
107    pub fn build(mut self) -> GeneticEngine<'a, G, A, T> {
108        self.build_population();
109        self.build_alterer();
110
111        if !self.codex.is_some() {
112            panic!("Codex not set");
113        }
114
115        if !self.fitness_fn.is_some() {
116            panic!("Fitness function not set");
117        }
118
119        GeneticEngine::new(self)
120    }
121
122    fn build_population(&mut self) {
123        self.population = match &self.population {
124            None => Some(match self.codex.as_ref() {
125                Some(codex) => Population::from_fn(self.population_size, || {
126                    Phenotype::from_genotype(codex.encode(), 0)
127                }),
128                None => panic!("Codex not set"),
129            }),
130            Some(pop) => Some(pop.clone()),
131        };
132    }
133
134    fn build_alterer(&mut self) {
135        if self.alterer.is_none() {
136            self.alterer = Some(CompositeAlterer::new(vec![
137                Alterer::Mutator(0.001),
138                Alterer::UniformCrossover(0.5),
139            ]));
140        }
141    }
142}