radiate_engines/
context.rs1use crate::{Chromosome, ThreadSync, events::EngineStateChange};
2use crate::{builder::config::EngineConfig, events::EventStream};
3use radiate_core::ExprSet;
4use radiate_core::error::RadiateResult;
5use radiate_core::{
6 Ecosystem, EngineState, Front, MetricSet, Objective, Phenotype, Problem, Score, metric,
7 metric_names,
8};
9use std::sync::{Arc, Mutex, RwLock};
10
11pub struct EvolutionContext<C: Chromosome, T> {
12 pub(crate) ecosystem: Ecosystem<C>,
13 pub(crate) best: T,
14 pub(crate) index: usize,
15 pub(crate) metrics: MetricSet,
16 pub(crate) objective: Objective,
17 pub(crate) sync: ThreadSync,
18 pub(crate) score: Option<Score>,
19 pub(crate) front: Arc<RwLock<Front<Phenotype<C>>>>,
20 pub(crate) problem: Arc<dyn Problem<C, T>>,
21 pub(crate) exprs: Option<Arc<Mutex<ExprSet>>>,
22 pub(crate) events: EventStream,
23 pub(crate) state: EngineState,
24}
25
26impl<C: Chromosome, T> EvolutionContext<C, T> {
27 pub fn index(&self) -> usize {
28 self.index
29 }
30
31 pub fn metrics(&self) -> &MetricSet {
32 &self.metrics
33 }
34
35 pub fn score(&self) -> Option<&Score> {
36 self.score.as_ref()
37 }
38
39 pub fn ecosystem(&self) -> &Ecosystem<C> {
40 &self.ecosystem
41 }
42
43 pub fn front(&self) -> Arc<RwLock<Front<Phenotype<C>>>> {
44 Arc::clone(&self.front)
45 }
46
47 pub fn event_stream(&self) -> &EventStream {
48 &self.events
49 }
50
51 pub fn wait(&self) {
52 self.sync.wait()
53 }
54
55 pub fn get_or_create_sync(&mut self) -> ThreadSync {
56 self.sync.clone()
57 }
58
59 pub fn request_stop(&self) {
60 self.sync.stop();
61 }
62
63 pub fn stop_requested(&self) -> bool {
64 self.sync.is_stopped()
65 }
66
67 pub fn pause_requested(&self) -> bool {
68 self.sync.is_paused()
69 }
70
71 pub fn state(&self) -> EngineState {
72 self.state
73 }
74
75 pub(crate) fn set_running(&mut self) {
76 self.change_state(EngineState::Running);
77 }
78
79 pub(crate) fn set_paused(&mut self) {
80 self.change_state(EngineState::Paused);
81 }
82
83 pub(crate) fn set_stopped(&mut self) {
84 self.change_state(EngineState::Stopped);
85 }
86
87 pub(crate) fn try_advance_one(&mut self) -> RadiateResult<bool> {
88 self.index += 1;
89
90 let best = self.ecosystem.get_phenotype(0);
91 let best_improved = self
92 .metrics
93 .improvements()
94 .map(|m| m.last_value() > 0.0)
95 .unwrap_or(false);
96
97 if best_improved && let Some(best) = best {
98 self.score = best.score().cloned();
99 self.best = self.problem.decode(best.genotype());
100 }
101
102 self.metrics
103 .replace(metric!(metric_names::INDEX, self.index));
104 self.metrics.bump(self.index);
105
106 Ok(best_improved)
107 }
108
109 fn change_state(&mut self, state: EngineState) {
110 if self.state == state {
111 return;
112 }
113
114 self.events.publish(EngineStateChange {
115 from: self.state,
116 to: state,
117 index: self.index,
118 });
119
120 self.state = state;
121 }
122}
123
124impl<C, T> From<EngineConfig<C, T>> for EvolutionContext<C, T>
125where
126 C: Chromosome + Clone,
127 T: Clone,
128{
129 fn from(config: EngineConfig<C, T>) -> Self {
130 if let Some(generation) = config.generation() {
131 return EvolutionContext {
132 ecosystem: generation.ecosystem().clone(),
133 best: generation.value().clone(),
134 index: generation.index(),
135 metrics: generation.metrics().clone(),
136 score: Some(generation.score().clone()),
137 front: config.front(),
138 objective: config.objective().clone(),
139 problem: config.problem().clone(),
140 sync: config.sync(),
141 exprs: generation.exprs(),
142 events: config.event_stream(),
143 state: EngineState::PreStart,
144 };
145 }
146
147 let initial_genotype = config
148 .ecosystem()
149 .get_genotype(0)
150 .map(|geno| config.problem().decode(geno));
151
152 EvolutionContext {
153 ecosystem: config.ecosystem().clone(),
154 best: initial_genotype.unwrap(),
155 index: 0,
156 metrics: MetricSet::default(),
157 score: None,
158 front: config.front(),
159 objective: config.objective().clone(),
160 problem: config.problem().clone(),
161 sync: config.sync(),
162 exprs: config.exprs(),
163 events: config.event_stream(),
164 state: EngineState::PreStart,
165 }
166 }
167}