1use crate::{Chromosome, Gene, MetricSet, math::indexes, random_provider, stats::metric_tags};
2use crate::{GetPairMut, Phenotype};
3use crate::{RateSet, error::RadiateResult};
4pub use radiate_expr::*;
5use radiate_utils::{SmallStr, generate_metric_key};
6use std::collections::HashMap;
7use std::sync::Arc;
8
9#[macro_export]
10macro_rules! alters {
11 ($($struct_instance:expr),* $(,)?) => {
12 {
13 let mut vec: Vec<Alterer<_>> = Vec::new();
14 $(
15 vec.push($struct_instance.into_alterer());
16 )*
17 vec
18 }
19 };
20}
21
22#[derive(Clone, Default)]
23pub struct AlterUpdates(pub HashMap<SmallStr, usize>);
24
25impl AlterUpdates {
26 pub fn new() -> Self {
27 AlterUpdates(HashMap::new())
28 }
29
30 pub fn clear(&mut self) {
31 for value in self.0.values_mut() {
32 *value = 0;
33 }
34 }
35
36 pub fn iter(&self) -> impl Iterator<Item = (&SmallStr, &usize)> {
37 self.0.iter().filter(|(_, count)| **count > 0)
38 }
39
40 pub fn upsert(&mut self, name: impl AsRef<str>, value: usize) {
41 if let Some(existing) = self.0.get_mut(name.as_ref()) {
42 *existing += value;
43 } else {
44 self.0
45 .insert(SmallStr::from_string(name.as_ref().into()), value);
46 }
47 }
48}
49
50pub struct AlterContext<'a> {
51 alter_counts: &'a mut AlterUpdates,
52 generation: usize,
53 control_rate: f32,
54 internal_rates: &'a [f32],
55}
56
57impl<'a> AlterContext<'a> {
58 pub fn new(
59 alter_counts: &'a mut AlterUpdates,
60 generation: usize,
61 control_rate: f32,
62 internal_rates: &'a [f32],
63 ) -> Self {
64 AlterContext {
65 alter_counts,
66 generation,
67 control_rate,
68 internal_rates,
69 }
70 }
71
72 pub fn rate(&self) -> f32 {
73 self.control_rate
74 }
75
76 pub fn internal_rate(&self, index: usize) -> f32 {
77 self.internal_rates.get(index).copied().unwrap_or(0.0)
78 }
79
80 pub fn generation(&self) -> usize {
81 self.generation
82 }
83
84 pub fn upsert(&mut self, name: impl AsRef<str>, value: usize) {
85 self.alter_counts.upsert(name, value);
86 }
87}
88
89#[derive(Clone)]
90pub enum AlterInner<C: Chromosome> {
91 Mutate(Arc<dyn Mutate<C>>),
92 Crossover(Arc<dyn Crossover<C>>),
93}
94
95#[derive(Clone)]
99pub struct Alterer<C: Chromosome> {
100 time_name: SmallStr,
101 name: SmallStr,
102 inner: AlterInner<C>,
103 alter_counts: AlterUpdates,
104 rate_set: RateSet,
105}
106
107impl<C: Chromosome> Alterer<C> {
108 pub fn mutation(name: impl Into<SmallStr>, m: Arc<dyn Mutate<C>>) -> Self {
109 Self::build_internal(name, AlterInner::Mutate(m))
110 }
111
112 pub fn crossover(name: impl Into<SmallStr>, c: Arc<dyn Crossover<C>>) -> Self {
113 Self::build_internal(name, AlterInner::Crossover(c))
114 }
115
116 fn build_internal(name: impl Into<SmallStr>, inner: AlterInner<C>) -> Self {
117 let name = name.into();
118
119 let time_name = SmallStr::from_string(format!("{}.time", name));
120 let control_rate_name = SmallStr::from_string(format!("{}.rate", name));
121
122 let rate_set = match &inner {
123 AlterInner::Mutate(m) => m.rates().alias(control_rate_name.clone()),
124 AlterInner::Crossover(c) => c.rates().alias(control_rate_name.clone()),
125 };
126
127 Self {
128 time_name,
129 name,
130 inner,
131 alter_counts: AlterUpdates::new(),
132 rate_set,
133 }
134 }
135
136 pub fn rates(&self) -> &RateSet {
137 &self.rate_set
138 }
139
140 pub fn name(&self) -> &str {
141 &self.name
142 }
143
144 pub fn alter(
145 &mut self,
146 population: &mut [Phenotype<C>],
147 metrics: &mut MetricSet,
148 generation: usize,
149 ) -> RadiateResult<()> {
150 let rates = self.rate_set.calculate_rates(generation, metrics)?;
151
152 self.alter_counts.clear();
153
154 let mut ctx = AlterContext {
155 alter_counts: &mut self.alter_counts,
156 generation,
157 control_rate: rates[0],
158 internal_rates: &rates[1..],
159 };
160
161 match &mut self.inner {
162 AlterInner::Mutate(m) => {
163 let mutator = Arc::get_mut(&mut (*m)).unwrap();
164
165 let timer = std::time::Instant::now();
166 let result = mutator.mutate(population, &mut ctx);
167 metrics.upsert(&self.time_name, timer.elapsed());
168 metrics.upsert(&self.name, result);
169
170 for (name, count) in ctx.alter_counts.iter() {
171 metrics.upsert(name, *count);
172 }
173 }
174 AlterInner::Crossover(c) => {
175 let timer = std::time::Instant::now();
176 let result = c.crossover(population, &mut ctx);
177 metrics.upsert(&self.time_name, timer.elapsed());
178 metrics.upsert(&self.name, result);
179
180 for (name, count) in ctx.alter_counts.iter() {
181 metrics.upsert(name, *count);
182 }
183 }
184 }
185
186 Ok(())
187 }
188}
189
190const MIN_POPULATION_SIZE: usize = 3;
194const MIN_NUM_PARENTS: usize = 2;
197
198pub trait Crossover<C: Chromosome>: Send + Sync {
210 fn name(&self) -> String {
211 generate_metric_key::<Self>(metric_tags::CROSSOVER)
212 }
213
214 fn into_alterer(self) -> Alterer<C>
215 where
216 Self: Sized + 'static,
217 {
218 Alterer::crossover(self.name(), Arc::new(self))
219 }
220
221 fn rates(&self) -> RateSet {
222 RateSet::default()
223 }
224
225 #[inline]
226 fn crossover(&self, mut population: &mut [Phenotype<C>], ctx: &mut AlterContext) -> usize {
227 let mut result = 0;
228 let mut parents = [0; MIN_NUM_PARENTS];
229 let pop_size = population.len();
230
231 for i in 0..pop_size {
232 if random_provider::bool(ctx.rate()) && pop_size > MIN_POPULATION_SIZE {
233 indexes::fill_subset_inclusive(i, pop_size, &mut parents);
234
235 result += population
236 .get_pair_mut(parents[0], parents[1])
237 .map(|(one, two)| self.cross(one, two, ctx))
238 .unwrap_or(0);
239 }
240 }
241
242 result
243 }
244
245 #[inline]
246 fn cross(
247 &self,
248 parent_one: &mut Phenotype<C>,
249 parent_two: &mut Phenotype<C>,
250 ctx: &mut AlterContext,
251 ) -> usize {
252 let geno_one = parent_one.genotype_mut();
253 let geno_two = parent_two.genotype_mut();
254
255 let min_len = std::cmp::min(geno_one.len(), geno_two.len());
256 let chromosome_index = random_provider::range(0..min_len);
257
258 let chrom_one = &mut geno_one[chromosome_index];
259 let chrom_two = &mut geno_two[chromosome_index];
260
261 let cross_result = self.cross_chromosomes(chrom_one, chrom_two, ctx);
262
263 if cross_result > 0 {
264 parent_one.invalidate(ctx.generation());
265 parent_two.invalidate(ctx.generation());
266 }
267
268 cross_result
269 }
270
271 #[inline]
272 fn cross_chromosomes(
273 &self,
274 chrom_one: &mut C,
275 chrom_two: &mut C,
276 ctx: &mut AlterContext,
277 ) -> usize {
278 let mut cross_count = 0;
279
280 for i in 0..std::cmp::min(chrom_one.len(), chrom_two.len()) {
281 if random_provider::bool(ctx.rate()) {
282 let gene_one = chrom_one.get_mut(i);
283 let gene_two = chrom_two.get_mut(i);
284
285 if let Some((gene_one, gene_two)) = gene_one.zip(gene_two) {
286 std::mem::swap(gene_one, gene_two);
287 cross_count += 1;
288 }
289 }
290 }
291
292 cross_count
293 }
294}
295
296pub trait Mutate<C: Chromosome>: Send + Sync {
297 fn name(&self) -> String {
298 generate_metric_key::<Self>(metric_tags::MUTATOR)
299 }
300
301 fn into_alterer(self) -> Alterer<C>
302 where
303 Self: Sized + 'static,
304 {
305 Alterer::mutation(self.name(), Arc::new(self))
306 }
307
308 fn rates(&self) -> RateSet {
309 RateSet::default()
310 }
311
312 #[inline]
313 fn mutate(&mut self, population: &mut [Phenotype<C>], ctx: &mut AlterContext) -> usize {
314 population
315 .iter_mut()
316 .map(|phenotype| {
317 let mutate_result = phenotype
318 .genotype_mut()
319 .iter_mut()
320 .fold(0, |acc, chromosome| {
321 acc + self.mutate_chromosome(chromosome, ctx)
322 });
323
324 if mutate_result > 0 {
325 phenotype.invalidate(ctx.generation());
326 }
327
328 mutate_result
329 })
330 .sum()
331 }
332
333 #[inline]
334 fn mutate_chromosome(&mut self, chromosome: &mut C, ctx: &mut AlterContext) -> usize {
335 chromosome
336 .iter_mut()
337 .filter(|_| random_provider::bool(ctx.rate()))
338 .fold(0, |acc, gene| {
339 *gene = gene.new_instance();
340 acc + 1
341 })
342 }
343}