Skip to main content

radiate_engines/steps/
front.rs

1use crate::steps::EngineStep;
2use radiate_core::{Chromosome, Ecosystem, Front, MetricSet, Phenotype, metric_names};
3use radiate_error::Result;
4use std::sync::{Arc, RwLock};
5
6pub struct FrontStep<C: Chromosome> {
7    pub(crate) front: Arc<RwLock<Front<Phenotype<C>>>>,
8}
9
10impl<C> EngineStep<C> for FrontStep<C>
11where
12    C: Chromosome + PartialEq + Clone + 'static,
13{
14    #[inline]
15    fn execute(
16        &mut self,
17        generation: usize,
18        ecosystem: &mut Ecosystem<C>,
19        metrics: &mut MetricSet,
20    ) -> Result<()> {
21        let phenotypes = ecosystem
22            .population()
23            .iter()
24            .filter(|ind| ind.age(generation) == 0)
25            .cloned()
26            .collect::<Vec<Phenotype<C>>>();
27
28        let add_result = self.front.write().unwrap().add_all(phenotypes);
29
30        metrics.upsert((metric_names::FRONT_ADDITIONS, add_result.added_count));
31        metrics.upsert((metric_names::FRONT_REMOVALS, add_result.removed_count));
32        metrics.upsert((metric_names::FRONT_COMPARISONS, add_result.comparisons));
33        metrics.upsert((metric_names::FRONT_FILTERS, add_result.filter_count));
34        metrics.upsert((metric_names::FRONT_SIZE, add_result.size));
35
36        if add_result.added_count > 0 {
37            // Update entropy metric every 10 generations - this is an expensive operation so we
38            // don't want to do it every generation.
39            if generation % 10 == 0 {
40                let mut reader = self.front.write().unwrap();
41                if let Some(entropy) = reader.entropy() {
42                    metrics.upsert((metric_names::FRONT_ENTROPY, entropy));
43                }
44            }
45        }
46
47        Ok(())
48    }
49}