1use crate::{Chromosome, Gene, Genotype, Population, math::indexes, random_provider};
2use crate::{Lineage, LineageUpdate, MetricSet, MetricUpdate, Rate, metric};
3use radiate_utils::{ToSnakeCase, intern};
4use std::sync::Arc;
5
6#[macro_export]
7macro_rules! alters {
8 ($($struct_instance:expr),* $(,)?) => {
9 {
10 let mut vec: Vec<Alterer<_>> = Vec::new();
11 $(
12 vec.push($struct_instance.alterer());
13 )*
14 vec
15 }
16 };
17}
18
19pub struct AlterResult(pub usize);
24
25impl AlterResult {
26 pub fn empty() -> Self {
27 Default::default()
28 }
29
30 pub fn count(&self) -> usize {
31 self.0
32 }
33
34 pub fn merge(&mut self, other: AlterResult) {
35 let AlterResult(other_count) = other;
36 self.0 += other_count;
37 }
38}
39
40impl Default for AlterResult {
41 fn default() -> Self {
42 AlterResult(0)
43 }
44}
45
46impl From<usize> for AlterResult {
47 fn from(value: usize) -> Self {
48 AlterResult(value)
49 }
50}
51
52pub struct AlterContext<'a> {
53 metrics: &'a mut MetricSet,
54 lineage: &'a mut Lineage,
55 operation: &'static str,
56 generation: usize,
57 rate: f32,
58}
59
60impl<'a> AlterContext<'a> {
61 pub fn new(
62 operation: &'static str,
63 metrics: &'a mut MetricSet,
64 lineage: &'a mut Lineage,
65 generation: usize,
66 rate: f32,
67 ) -> Self {
68 Self {
69 metrics,
70 lineage,
71 operation,
72 generation,
73 rate,
74 }
75 }
76
77 pub fn rate(&self) -> f32 {
78 self.rate
79 }
80
81 pub fn generation(&self) -> usize {
82 self.generation
83 }
84
85 pub fn metric(&mut self, name: &'static str, value: impl Into<MetricUpdate<'a>>) {
86 self.metrics.upsert((name, value.into()));
87 }
88
89 pub fn update_lineage(&mut self, update: impl Into<LineageUpdate>) {
90 self.lineage.push(self.operation, update.into());
91 }
92}
93
94#[derive(Clone)]
98pub enum Alterer<C: Chromosome> {
99 Mutate(&'static str, Rate, Arc<dyn Mutate<C>>),
100 Crossover(&'static str, Rate, Arc<dyn Crossover<C>>),
101}
102
103impl<C: Chromosome> Alterer<C> {
104 pub fn name(&self) -> &'static str {
105 match &self {
106 Alterer::Mutate(name, _, _) => name,
107 Alterer::Crossover(name, _, _) => name,
108 }
109 }
110
111 pub fn rate(&mut self) -> &mut Rate {
112 match self {
113 Alterer::Mutate(_, rate, _) => rate,
114 Alterer::Crossover(_, rate, _) => rate,
115 }
116 }
117
118 #[inline]
119 pub fn alter(
120 &mut self,
121 population: &mut Population<C>,
122 lineage: &mut Lineage,
123 metrics: &mut MetricSet,
124 generation: usize,
125 ) {
126 let rate = self.rate().get(generation, metrics);
127 let operation = self.name();
128
129 metrics.upsert(metric!(
130 radiate_utils::intern!(format!("{}.rate", operation)),
131 rate
132 ));
133
134 let mut ctx = AlterContext {
135 metrics,
136 lineage,
137 operation,
138 generation,
139 rate,
140 };
141
142 match &self {
143 Alterer::Mutate(name, _, m) => {
144 let timer = std::time::Instant::now();
145 let AlterResult(count) = m.mutate(population, &mut ctx);
146 metrics.upsert((*name, count));
147 metrics.upsert((
148 radiate_utils::intern!(format!("{}.time", name)),
149 timer.elapsed(),
150 ));
151 }
152 Alterer::Crossover(name, _, c) => {
153 let timer = std::time::Instant::now();
154 let AlterResult(count) = c.crossover(population, &mut ctx);
155 metrics.upsert((*name, count));
156 metrics.upsert((
157 radiate_utils::intern!(format!("{}.time", name)),
158 timer.elapsed(),
159 ));
160 }
161 }
162 }
163}
164
165const MIN_POPULATION_SIZE: usize = 3;
169const MIN_NUM_PARENTS: usize = 2;
172
173pub trait Crossover<C: Chromosome>: Send + Sync {
185 fn name(&self) -> String {
186 let name = std::any::type_name::<Self>()
187 .split("::")
188 .last()
189 .map(|s| s.to_snake_case())
190 .unwrap();
191
192 let path = name.split('_').collect::<Vec<&str>>();
193 let mut new_name = vec!["crossover"];
194 for part in path {
195 if !part.contains("crossov") {
196 new_name.push(part);
197 }
198 }
199
200 new_name.join(".")
201 }
202
203 fn rate(&self) -> Rate {
204 Rate::default()
205 }
206
207 fn alterer(self) -> Alterer<C>
208 where
209 Self: Sized + 'static,
210 {
211 Alterer::Crossover(intern!(self.name()), self.rate(), Arc::new(self))
212 }
213
214 #[inline]
215 fn crossover(&self, population: &mut Population<C>, ctx: &mut AlterContext) -> AlterResult {
216 let mut result = AlterResult::default();
217 let mut parents = [0usize; MIN_NUM_PARENTS];
218
219 for i in 0..population.len() {
220 if random_provider::bool(ctx.rate()) && population.len() > MIN_POPULATION_SIZE {
221 indexes::individual_indexes(i, population.len(), MIN_NUM_PARENTS, &mut parents);
222 let cross_result = self.cross(population, &parents, ctx);
223 result.merge(cross_result);
224 }
225 }
226
227 result
228 }
229
230 #[inline]
231 fn cross(
232 &self,
233 population: &mut Population<C>,
234 parent_indexes: &[usize],
235 ctx: &mut AlterContext,
236 ) -> AlterResult {
237 let mut result = AlterResult::default();
238
239 if let Some((one, two)) = population.get_pair_mut(parent_indexes[0], parent_indexes[1]) {
240 let cross_result = {
241 let geno_one = one.genotype_mut();
242 let geno_two = two.genotype_mut();
243
244 let min_len = std::cmp::min(geno_one.len(), geno_two.len());
245 let chromosome_index = random_provider::range(0..min_len);
246
247 let chrom_one = &mut geno_one[chromosome_index];
248 let chrom_two = &mut geno_two[chromosome_index];
249
250 self.cross_chromosomes(chrom_one, chrom_two, ctx)
251 };
252
253 if cross_result.count() > 0 {
254 let parent_lineage = (one.family(), two.family());
255 let parent_ids = (one.id(), two.id());
256 one.invalidate(ctx.generation());
257 two.invalidate(ctx.generation());
258
259 ctx.update_lineage((parent_lineage, parent_ids, one.id()));
260 ctx.update_lineage((parent_lineage, parent_ids, two.id()));
261 result.merge(cross_result);
262 }
263 }
264
265 result
266 }
267
268 #[inline]
269 fn cross_chromosomes(
270 &self,
271 chrom_one: &mut C,
272 chrom_two: &mut C,
273 ctx: &mut AlterContext,
274 ) -> AlterResult {
275 let mut cross_count = 0;
276
277 for i in 0..std::cmp::min(chrom_one.len(), chrom_two.len()) {
278 if random_provider::bool(ctx.rate()) {
279 let gene_one = chrom_one.get(i);
280 let gene_two = chrom_two.get(i);
281
282 let new_gene_one = gene_one.with_allele(gene_two.allele());
283 let new_gene_two = gene_two.with_allele(gene_one.allele());
284
285 chrom_one.set(i, new_gene_one);
286 chrom_two.set(i, new_gene_two);
287
288 cross_count += 1;
289 }
290 }
291
292 AlterResult::from(cross_count)
293 }
294}
295
296pub trait Mutate<C: Chromosome>: Send + Sync {
297 fn name(&self) -> String {
298 let name = std::any::type_name::<Self>()
299 .split("::")
300 .last()
301 .map(|s| s.to_snake_case())
302 .unwrap();
303
304 let path = name.split('_').collect::<Vec<&str>>();
305 let mut new_name = vec!["mutate"];
306 for part in path {
307 if !part.contains("mutat") {
308 new_name.push(part);
309 }
310 }
311
312 new_name.join(".")
313 }
314
315 fn rate(&self) -> Rate {
316 Rate::default()
317 }
318
319 fn alterer(self) -> Alterer<C>
320 where
321 Self: Sized + 'static,
322 {
323 Alterer::Mutate(intern!(self.name()), self.rate(), Arc::new(self))
324 }
325
326 #[inline]
327 fn mutate(&self, population: &mut Population<C>, ctx: &mut AlterContext) -> AlterResult {
328 let mut result = AlterResult::default();
329
330 for phenotype in population.iter_mut() {
331 let mutate_result = self.mutate_genotype(phenotype.genotype_mut(), ctx);
332
333 if mutate_result.count() > 0 {
334 let parent = (phenotype.family(), phenotype.id());
335 phenotype.invalidate(ctx.generation());
336 ctx.update_lineage((parent, phenotype.id()));
337 }
338
339 result.merge(mutate_result);
340 }
341
342 result
343 }
344
345 #[inline]
346 fn mutate_genotype(&self, genotype: &mut Genotype<C>, ctx: &mut AlterContext) -> AlterResult {
347 let mut result = AlterResult::default();
348
349 for chromosome in genotype.iter_mut() {
350 let mutate_result = self.mutate_chromosome(chromosome, ctx);
351 result.merge(mutate_result);
352 }
353
354 result
355 }
356
357 #[inline]
358 fn mutate_chromosome(&self, chromosome: &mut C, ctx: &mut AlterContext) -> AlterResult {
359 let mut count = 0;
360 for gene in chromosome.iter_mut() {
361 if random_provider::bool(ctx.rate()) {
362 count += self.mutate_gene(gene);
363 }
364 }
365
366 count.into()
367 }
368
369 #[inline]
370 fn mutate_gene(&self, gene: &mut C::Gene) -> usize {
371 *gene = gene.new_instance();
372 1
373 }
374}