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