1use crate::{
2 Chromosome, Ecosystem, Front, MetricSet, Objective, Phenotype, Population, Problem, Score,
3 Species, metric_names,
4};
5use std::{
6 sync::{Arc, RwLock},
7 time::Duration,
8};
9
10pub trait Engine {
11 type Chromosome: Chromosome;
12 type Epoch: Epoch<Chromosome = Self::Chromosome>;
13
14 fn next(&mut self) -> Self::Epoch;
15}
16
17pub trait EngineExt<E: Engine> {
18 fn run<F>(&mut self, limit: F) -> E::Epoch
19 where
20 F: Fn(&E::Epoch) -> bool,
21 Self: Sized;
22}
23
24impl<E> EngineExt<E> for E
25where
26 E: Engine,
27{
28 fn run<F>(&mut self, limit: F) -> E::Epoch
29 where
30 F: Fn(&E::Epoch) -> bool,
31 Self: Sized,
32 {
33 loop {
34 let epoch = self.next();
35
36 if limit(&epoch) {
37 break epoch;
38 }
39 }
40 }
41}
42
43pub trait Epoch {
44 type Chromosome: Chromosome;
45 type Value;
46
47 fn value(&self) -> &Self::Value;
48 fn ecosystem(&self) -> &Ecosystem<Self::Chromosome>;
49 fn index(&self) -> usize;
50 fn metrics(&self) -> &MetricSet;
51 fn objective(&self) -> &Objective;
52
53 fn population(&self) -> &Population<Self::Chromosome> {
54 &self.ecosystem().population()
55 }
56
57 fn species(&self) -> Option<&[Species<Self::Chromosome>]> {
58 self.ecosystem().species().map(|s| s.as_slice())
59 }
60
61 fn time(&self) -> Duration {
62 self.metrics()
63 .get(metric_names::EVOLUTION_TIME)
64 .map(|m| m.time_sum())
65 .flatten()
66 .unwrap_or_default()
67 }
68
69 fn seconds(&self) -> f64 {
70 self.time().as_secs_f64()
71 }
72}
73
74pub trait EngineStep<C>: Send + Sync
75where
76 C: Chromosome,
77{
78 fn name(&self) -> &'static str {
79 std::any::type_name::<Self>()
80 .split("<")
81 .next()
82 .unwrap_or(std::any::type_name::<Self>())
83 .split("::")
84 .last()
85 .unwrap_or("Unknown Step")
86 }
87
88 fn execute(&mut self, generation: usize, metrics: &mut MetricSet, ecosystem: &mut Ecosystem<C>);
89}
90
91pub struct Context<C, T>
92where
93 C: Chromosome,
94{
95 pub ecosystem: Ecosystem<C>,
96 pub best: T,
97 pub index: usize,
98 pub metrics: MetricSet,
99 pub score: Option<Score>,
100 pub front: Arc<RwLock<Front<Phenotype<C>>>>,
101 pub objective: Objective,
102 pub problem: Arc<dyn Problem<C, T>>,
103}
104
105impl<C, T> Clone for Context<C, T>
106where
107 C: Chromosome + Clone,
108 T: Clone,
109{
110 fn clone(&self) -> Self {
111 Context {
112 ecosystem: self.ecosystem.clone(),
113 best: self.best.clone(),
114 index: self.index,
115 metrics: self.metrics.clone(),
116 score: self.score.clone(),
117 front: self.front.clone(),
118 objective: self.objective.clone(),
119 problem: Arc::clone(&self.problem),
120 }
121 }
122}