1use crate::Chromosome;
2use crate::context::EvolutionContext;
3use radiate_core::ExprSet;
4use radiate_core::objectives::Scored;
5use radiate_core::{Ecosystem, Front, MetricSet, Objective, Phenotype, Population, Score, Species};
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8use std::fmt::Debug;
9use std::sync::{Arc, Mutex};
10use std::time::Duration;
11
12#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
46pub struct Generation<C: Chromosome, T> {
47 ecosystem: Arc<Ecosystem<C>>,
48 value: T,
49 index: usize,
50 metrics: Arc<MetricSet>,
51 score: Score,
52 objective: Objective,
53 front: Option<Arc<Front<Phenotype<C>>>>,
54 exprs: Option<Arc<Mutex<ExprSet>>>,
55}
56
57impl<C: Chromosome, T> Generation<C, T> {
58 pub fn score(&self) -> &Score {
59 &self.score
60 }
61
62 pub fn front(&self) -> Option<&Front<Phenotype<C>>> {
63 self.front.as_deref()
64 }
65
66 pub fn value(&self) -> &T {
67 &self.value
68 }
69
70 pub fn index(&self) -> usize {
71 self.index
72 }
73
74 pub fn metrics(&self) -> &MetricSet {
75 &self.metrics
76 }
77
78 pub fn objective(&self) -> &Objective {
79 &self.objective
80 }
81
82 pub fn ecosystem(&self) -> &Ecosystem<C> {
83 &self.ecosystem
84 }
85
86 pub fn population(&self) -> &Population<C> {
87 self.ecosystem().population()
88 }
89
90 pub fn species(&self) -> Option<&[Species<C>]> {
91 self.ecosystem().species().map(|s| s.as_slice())
92 }
93
94 pub fn time(&self) -> Duration {
95 self.metrics()
96 .time()
97 .and_then(|m| m.times().map(|t| t.sum()))
98 .unwrap_or_default()
99 }
100
101 pub fn seconds(&self) -> f64 {
102 self.time().as_secs_f64()
103 }
104
105 pub fn exprs(&self) -> Option<Arc<Mutex<ExprSet>>> {
106 self.exprs.clone()
107 }
108
109 pub fn arc_ecosystem(&self) -> Arc<Ecosystem<C>> {
110 Arc::clone(&self.ecosystem)
111 }
112
113 pub fn arc_metrics(&self) -> Arc<MetricSet> {
114 Arc::clone(&self.metrics)
115 }
116}
117
118impl<C: Chromosome, T> Scored for Generation<C, T> {
119 fn score(&self) -> Option<&Score> {
120 Some(&self.score)
121 }
122}
123
124impl<C, T> From<&EvolutionContext<C, T>> for Generation<C, T>
125where
126 C: Chromosome + Clone,
127 T: Clone,
128{
129 fn from(context: &EvolutionContext<C, T>) -> Self {
130 Generation {
131 ecosystem: Arc::new(context.ecosystem.clone()),
132 value: context.best.clone(),
133 index: context.index,
134 metrics: Arc::new(context.metrics.clone()),
135 score: context.score.clone().unwrap(),
136 objective: context.objective.clone(),
137 front: match context.objective {
138 Objective::Multi(_) => Some(Arc::new(context.front.read().unwrap().clone())),
139 _ => None,
140 },
141 exprs: context.exprs.clone(),
142 }
143 }
144}
145
146impl<C, T> Clone for Generation<C, T>
147where
148 C: Chromosome + Clone,
149 T: Clone,
150{
151 fn clone(&self) -> Self {
152 Generation {
153 ecosystem: Arc::clone(&self.ecosystem),
154 value: self.value.clone(),
155 index: self.index,
156 metrics: Arc::clone(&self.metrics),
157 score: self.score.clone(),
158 objective: self.objective.clone(),
159 front: self.front.clone(),
160 exprs: self.exprs.clone(),
161 }
162 }
163}
164
165impl<C, T> Debug for Generation<C, T>
166where
167 C: Chromosome,
168 T: Debug,
169{
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171 let ecosystem = &self.ecosystem;
172
173 writeln!(f, "Generation {{")?;
174 writeln!(f, " metrics: {:?},", self.metrics)?;
175 writeln!(f, " score: {:?},", self.score)?;
176 writeln!(f, " index: {:?},", self.index)?;
177 writeln!(f, " size: {:?},", ecosystem.population().len())?;
178 writeln!(f, " duration: {:?},", self.time())?;
179 writeln!(f, " objective: {:?},", self.objective)?;
180 if let Some(species) = &ecosystem.species {
181 writeln!(f, " species [")?;
182 for s in species {
183 writeln!(
184 f,
185 " \t{:?} age={}",
186 s,
187 self.index.saturating_sub(s.generation()),
188 )?;
189 }
190 writeln!(f, " ],")?;
191 }
192 writeln!(f, " value: {:?},", self.value)?;
193
194 write!(f, "}}")
195 }
196}
197
198impl<C, T> Default for Generation<C, T>
199where
200 C: Chromosome + Default,
201 T: Default,
202{
203 fn default() -> Self {
204 Generation {
205 ecosystem: Arc::new(Ecosystem::default()),
206 value: T::default(),
207 index: 0,
208 metrics: Arc::new(MetricSet::default()),
209 score: Score::default(),
210 objective: Objective::default(),
211 front: None,
212 exprs: None,
213 }
214 }
215}
216
217impl<C, T> FromIterator<Generation<C, T>> for Front<Phenotype<C>>
218where
219 C: Chromosome + Clone,
220{
221 fn from_iter<I: IntoIterator<Item = Generation<C, T>>>(iter: I) -> Self {
222 iter.into_iter()
223 .last()
224 .and_then(|generation| generation.front().cloned())
225 .unwrap_or_default()
226 }
227}
228
229enum ViewInner<'a, C, T>
230where
231 C: Chromosome,
232{
233 Context(&'a EvolutionContext<C, T>),
234 Generation(&'a Generation<C, T>),
235}
236
237pub struct GenerationView<'a, C, T>
238where
239 C: Chromosome,
240{
241 inner: ViewInner<'a, C, T>,
242}
243
244impl<'a, C, T> GenerationView<'a, C, T>
245where
246 C: Chromosome,
247{
248 pub fn new(context: &'a EvolutionContext<C, T>) -> Self {
249 Self {
250 inner: ViewInner::Context(context),
251 }
252 }
253
254 pub fn score(&self) -> &Score {
255 match &self.inner {
256 ViewInner::Context(ctx) => ctx.score.as_ref().unwrap(),
257 ViewInner::Generation(epoch) => &epoch.score,
258 }
259 }
260
261 pub fn front(&self) -> Arc<Front<Phenotype<C>>>
262 where
263 C: Clone,
264 {
265 match &self.inner {
266 ViewInner::Context(ctx) => match ctx.objective {
267 Objective::Multi(_) => Arc::new(ctx.front.read().unwrap().clone()),
268 _ => Arc::default(),
269 },
270 ViewInner::Generation(epoch) => match &epoch.front {
271 Some(front) => Arc::clone(front),
272 None => Arc::default(),
273 },
274 }
275 }
276
277 pub fn value(&self) -> &T {
278 match &self.inner {
279 ViewInner::Context(ctx) => &ctx.best,
280 ViewInner::Generation(epoch) => &epoch.value,
281 }
282 }
283
284 pub fn phenotype(&self) -> &Phenotype<C> {
285 match &self.inner {
286 ViewInner::Context(ctx) => ctx.ecosystem().get_phenotype(0).as_ref().unwrap(),
287 ViewInner::Generation(epoch) => epoch.ecosystem().get_phenotype(0).as_ref().unwrap(),
288 }
289 }
290
291 pub fn index(&self) -> usize {
292 match &self.inner {
293 ViewInner::Context(ctx) => ctx.index,
294 ViewInner::Generation(epoch) => epoch.index,
295 }
296 }
297
298 pub fn metrics(&self) -> &MetricSet {
299 match &self.inner {
300 ViewInner::Context(ctx) => &ctx.metrics,
301 ViewInner::Generation(epoch) => &epoch.metrics,
302 }
303 }
304
305 pub fn objective(&self) -> &Objective {
306 match &self.inner {
307 ViewInner::Context(ctx) => &ctx.objective,
308 ViewInner::Generation(epoch) => &epoch.objective,
309 }
310 }
311
312 pub fn ecosystem(&self) -> &Ecosystem<C> {
313 match &self.inner {
314 ViewInner::Context(ctx) => &ctx.ecosystem,
315 ViewInner::Generation(epoch) => &epoch.ecosystem,
316 }
317 }
318
319 pub fn population(&self) -> &Population<C> {
320 self.ecosystem().population()
321 }
322
323 pub fn species(&self) -> Option<&[Species<C>]> {
324 self.ecosystem().species().map(|s| s.as_slice())
325 }
326
327 pub fn time(&self) -> Duration {
328 self.metrics()
329 .time()
330 .and_then(|m| m.times().map(|t| t.sum()))
331 .unwrap_or_default()
332 }
333
334 pub fn seconds(&self) -> f64 {
335 self.time().as_secs_f64()
336 }
337}
338
339impl<'a, C, T> From<GenerationView<'a, C, T>> for Generation<C, T>
340where
341 C: Chromosome + Clone,
342 T: Clone,
343{
344 fn from(val: GenerationView<'a, C, T>) -> Self {
345 match val.inner {
346 ViewInner::Context(ctx) => Generation::from(ctx),
347 ViewInner::Generation(epoch) => epoch.clone(),
348 }
349 }
350}
351
352impl<'a, C, T> From<&'a Generation<C, T>> for GenerationView<'a, C, T>
353where
354 C: Chromosome,
355{
356 fn from(epoch: &'a Generation<C, T>) -> Self {
357 Self {
358 inner: ViewInner::Generation(epoch),
359 }
360 }
361}
362
363impl<'a, C, T> From<&'a EvolutionContext<C, T>> for GenerationView<'a, C, T>
364where
365 C: Chromosome,
366{
367 fn from(ctx: &'a EvolutionContext<C, T>) -> Self {
368 Self {
369 inner: ViewInner::Context(ctx),
370 }
371 }
372}