1use crate::{Chromosome, Gene, Genotype, Metric, Population, indexes, random_provider};
2
3pub trait Alter<C: Chromosome>: Send + Sync {
24 fn alter(&self, population: &mut Population<C>, generation: usize) -> Vec<Metric>;
25}
26
27#[derive(Default)]
32pub struct AlterResult(pub usize, pub Option<Vec<Metric>>);
33
34impl AlterResult {
35 pub fn count(&self) -> usize {
36 self.0
37 }
38
39 pub fn metrics(&self) -> Option<&Vec<Metric>> {
40 self.1.as_ref()
41 }
42
43 pub fn merge(&mut self, other: AlterResult) {
44 let AlterResult(other_count, other_metrics) = other;
45
46 self.0 += other_count;
47 if let Some(metrics) = other_metrics {
48 if let Some(self_metrics) = &mut self.1 {
49 self_metrics.extend(metrics);
50 } else {
51 self.1 = Some(metrics);
52 }
53 }
54 }
55}
56
57impl Into<AlterResult> for usize {
58 fn into(self) -> AlterResult {
59 AlterResult(self, None)
60 }
61}
62
63impl Into<AlterResult> for (usize, Vec<Metric>) {
64 fn into(self) -> AlterResult {
65 AlterResult(self.0, Some(self.1))
66 }
67}
68
69impl Into<AlterResult> for (usize, Metric) {
70 fn into(self) -> AlterResult {
71 AlterResult(self.0, Some(vec![self.1]))
72 }
73}
74
75pub enum AlterAction<C: Chromosome> {
79 Mutate(&'static str, f32, Box<dyn Mutate<C>>),
80 Crossover(&'static str, f32, Box<dyn Crossover<C>>),
81}
82
83impl<C: Chromosome> Alter<C> for AlterAction<C> {
84 fn alter(&self, population: &mut Population<C>, generation: usize) -> Vec<Metric> {
85 match &self {
86 AlterAction::Mutate(name, rate, m) => {
87 let timer = std::time::Instant::now();
88 let AlterResult(count, metrics) = m.mutate(population, generation, *rate);
89 let metric = Metric::new_operations(name, count, timer.elapsed());
90
91 match metrics {
92 Some(metrics) => metrics.into_iter().chain(std::iter::once(metric)).collect(),
93 None => vec![metric],
94 }
95 }
96 AlterAction::Crossover(name, rate, c) => {
97 let timer = std::time::Instant::now();
98 let AlterResult(count, metrics) = c.crossover(population, generation, *rate);
99 let metric = Metric::new_operations(name, count, timer.elapsed());
100
101 match metrics {
102 Some(metrics) => metrics.into_iter().chain(std::iter::once(metric)).collect(),
103 None => vec![metric],
104 }
105 }
106 }
107 }
108}
109
110pub trait Crossover<C: Chromosome>: Send + Sync {
122 fn name(&self) -> &'static str {
123 std::any::type_name::<Self>().split("::").last().unwrap()
124 }
125
126 fn rate(&self) -> f32 {
127 1.0
128 }
129
130 fn alterer(self) -> AlterAction<C>
131 where
132 Self: Sized + 'static,
133 {
134 AlterAction::Crossover(self.name(), self.rate(), Box::new(self))
135 }
136
137 #[inline]
138 fn crossover(
139 &self,
140 population: &mut Population<C>,
141 generation: usize,
142 rate: f32,
143 ) -> AlterResult {
144 let mut result = AlterResult::default();
145
146 for i in 0..population.len() {
147 if random_provider::random::<f32>() < rate && population.len() > 3 {
148 let parent_indexes = indexes::individual_indexes(i, population.len(), 2);
149 let cross_result = self.cross(population, &parent_indexes, generation, rate);
150 result.merge(cross_result);
151 }
152 }
153
154 result
155 }
156
157 #[inline]
158 fn cross(
159 &self,
160 population: &mut Population<C>,
161 parent_indexes: &[usize],
162 generation: usize,
163 rate: f32,
164 ) -> AlterResult {
165 let mut result = AlterResult::default();
166
167 if let Some((one, two)) = population.get_pair_mut(parent_indexes[0], parent_indexes[1]) {
168 let cross_result = {
169 let geno_one = one.genotype_mut();
170 let geno_two = two.genotype_mut();
171
172 let min_len = std::cmp::min(geno_one.len(), geno_two.len());
173 let chromosome_index = random_provider::range(0..min_len);
174
175 let chrom_one = &mut geno_one[chromosome_index];
176 let chrom_two = &mut geno_two[chromosome_index];
177
178 self.cross_chromosomes(chrom_one, chrom_two, rate)
179 };
180
181 if cross_result.count() > 0 {
182 one.invalidate(generation);
183 two.invalidate(generation);
184 result.merge(cross_result);
185 }
186 }
187
188 result
189 }
190
191 #[inline]
192 fn cross_chromosomes(&self, chrom_one: &mut C, chrom_two: &mut C, rate: f32) -> AlterResult {
193 let mut cross_count = 0;
194
195 for i in 0..std::cmp::min(chrom_one.len(), chrom_two.len()) {
196 if random_provider::random::<f32>() < rate {
197 let gene_one = chrom_one.get(i);
198 let gene_two = chrom_two.get(i);
199
200 let new_gene_one = gene_one.with_allele(gene_two.allele());
201 let new_gene_two = gene_two.with_allele(gene_one.allele());
202
203 chrom_one.set(i, new_gene_one);
204 chrom_two.set(i, new_gene_two);
205
206 cross_count += 1;
207 }
208 }
209
210 cross_count.into()
211 }
212}
213
214pub trait Mutate<C: Chromosome>: Send + Sync {
215 fn name(&self) -> &'static str {
216 std::any::type_name::<Self>().split("::").last().unwrap()
217 }
218
219 fn rate(&self) -> f32 {
220 1.0
221 }
222
223 fn alterer(self) -> AlterAction<C>
224 where
225 Self: Sized + 'static,
226 {
227 AlterAction::Mutate(self.name(), self.rate(), Box::new(self))
228 }
229
230 #[inline]
231 fn mutate(&self, population: &mut Population<C>, generation: usize, rate: f32) -> AlterResult {
232 let mut result = AlterResult::default();
233
234 for phenotype in population.iter_mut() {
235 let mutate_result = self.mutate_genotype(&mut phenotype.genotype_mut(), rate);
236
237 if mutate_result.count() > 0 {
238 phenotype.invalidate(generation);
239 }
240
241 result.merge(mutate_result);
242 }
243
244 result
245 }
246
247 #[inline]
248 fn mutate_genotype(&self, genotype: &mut Genotype<C>, rate: f32) -> AlterResult {
249 let mut result = AlterResult::default();
250
251 for chromosome in genotype.iter_mut() {
252 let mutate_result = self.mutate_chromosome(chromosome, rate);
253 result.merge(mutate_result);
254 }
255
256 result
257 }
258
259 #[inline]
260 fn mutate_chromosome(&self, chromosome: &mut C, rate: f32) -> AlterResult {
261 let mut count = 0;
262 for gene in chromosome.iter_mut() {
263 if random_provider::random::<f32>() < rate {
264 *gene = self.mutate_gene(gene);
265 count += 1;
266 }
267 }
268
269 count.into()
270 }
271
272 #[inline]
273 fn mutate_gene(&self, gene: &C::Gene) -> C::Gene {
274 gene.new_instance()
275 }
276}