radiate_rust/engines/
genetic_engine_params.rs1use 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}