radiate_engines/steps/
recombine.rs

1use radiate_core::{
2    Alter, Chromosome, Ecosystem, MetricSet, Objective, Optimize, Population, Select,
3    engine::EngineStep,
4};
5use std::sync::Arc;
6
7pub struct RecombineStep<C: Chromosome> {
8    pub(crate) survivor_selector: Arc<dyn Select<C>>,
9    pub(crate) offspring_selector: Arc<dyn Select<C>>,
10    pub(crate) alters: Vec<Arc<dyn Alter<C>>>,
11    pub(crate) survivor_count: usize,
12    pub(crate) offspring_count: usize,
13    pub(crate) objective: Objective,
14}
15
16impl<C: Chromosome> RecombineStep<C> {
17    pub fn select_survivors(
18        &self,
19        population: &Ecosystem<C>,
20        metrics: &mut MetricSet,
21    ) -> Population<C> {
22        Self::select(
23            self.survivor_count,
24            &population.population,
25            &self.objective,
26            metrics,
27            &self.survivor_selector,
28        )
29    }
30
31    pub fn select_offspring(
32        &self,
33        count: usize,
34        population: &Population<C>,
35        metrics: &mut MetricSet,
36    ) -> Population<C> {
37        Self::select(
38            count,
39            &population,
40            &self.objective,
41            metrics,
42            &self.offspring_selector,
43        )
44    }
45
46    pub fn create_offspring(
47        &self,
48        generation: usize,
49        ecosystem: &Ecosystem<C>,
50        metrics: &mut MetricSet,
51    ) -> Population<C> {
52        if let Some(species) = ecosystem.species.as_ref() {
53            let total_offspring = self.offspring_count as f32;
54            let mut species_scores = species
55                .iter()
56                .filter_map(|spec| spec.score())
57                .collect::<Vec<_>>();
58
59            if let Objective::Single(Optimize::Minimize) = &self.objective {
60                species_scores.reverse();
61            }
62
63            let mut offspring = Vec::with_capacity(self.offspring_count);
64            for (species, score) in species.iter().zip(species_scores.iter()) {
65                let count = (score.as_f32() * total_offspring).round() as usize;
66                let mut selected_offspring =
67                    self.select_offspring(count, &species.population, metrics);
68
69                self.objective.sort(&mut selected_offspring);
70
71                self.apply_alterations(generation, &mut selected_offspring, metrics);
72
73                offspring.extend(selected_offspring);
74            }
75
76            Population::new(offspring)
77        } else {
78            let mut offspring =
79                self.select_offspring(self.offspring_count, &ecosystem.population, metrics);
80
81            self.objective.sort(&mut offspring);
82
83            self.apply_alterations(generation, &mut offspring, metrics);
84            offspring
85        }
86    }
87
88    fn select(
89        count: usize,
90        population: &Population<C>,
91        objective: &Objective,
92        metrics: &mut MetricSet,
93        selector: &Arc<dyn Select<C>>,
94    ) -> Population<C> {
95        let timer = std::time::Instant::now();
96        let selected = selector.select(population, objective, count);
97
98        metrics.upsert_operations(selector.name(), selected.len() as f32, timer.elapsed());
99        selected
100    }
101
102    fn apply_alterations(
103        &self,
104        generation: usize,
105        offspring: &mut Population<C>,
106        metrics: &mut MetricSet,
107    ) {
108        self.alters.iter().for_each(|alt| {
109            alt.alter(offspring, generation)
110                .into_iter()
111                .for_each(|metric| {
112                    metrics.upsert(metric);
113                });
114        });
115    }
116}
117
118impl<C> EngineStep<C> for RecombineStep<C>
119where
120    C: Chromosome,
121{
122    fn execute(
123        &mut self,
124        generation: usize,
125        metrics: &mut MetricSet,
126        ecosystem: &mut Ecosystem<C>,
127    ) {
128        let survivors = self.select_survivors(ecosystem, metrics);
129        let offspring = self.create_offspring(generation, ecosystem, metrics);
130
131        ecosystem.population_mut().clear();
132
133        survivors
134            .into_iter()
135            .chain(offspring.into_iter())
136            .for_each(|individual| {
137                ecosystem.population_mut().push(individual);
138            });
139    }
140}