1use crate::Chromosome;
2use radiate_core::objectives::Scored;
3use radiate_core::{
4 Ecosystem, Front, MetricSet, Objective, Phenotype, Population, Problem, Score, Species,
5 metric_names,
6};
7use std::fmt::Debug;
8use std::sync::{Arc, RwLock};
9use std::time::Duration;
10
11pub struct Context<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) epoch_metrics: MetricSet,
17 pub(crate) score: Option<Score>,
18 pub(crate) front: Arc<RwLock<Front<Phenotype<C>>>>,
19 pub(crate) objective: Objective,
20 pub(crate) problem: Arc<dyn Problem<C, T>>,
21}
22
23impl<C, T> Clone for Context<C, T>
24where
25 C: Chromosome + Clone,
26 T: Clone,
27{
28 fn clone(&self) -> Self {
29 Context {
30 ecosystem: self.ecosystem.clone(),
31 best: self.best.clone(),
32 index: self.index,
33 metrics: self.metrics.clone(),
34 epoch_metrics: self.epoch_metrics.clone(),
35 score: self.score.clone(),
36 front: self.front.clone(),
37 objective: self.objective.clone(),
38 problem: Arc::clone(&self.problem),
39 }
40 }
41}
42
43pub struct Generation<C, T>
44where
45 C: Chromosome,
46{
47 ecosystem: Ecosystem<C>,
48 value: T,
49 index: usize,
50 metrics: MetricSet,
51 score: Score,
52 objective: Objective,
53 front: Option<Front<Phenotype<C>>>,
54}
55
56impl<C: Chromosome, T> Generation<C, T> {
57 pub fn score(&self) -> &Score {
58 &self.score
59 }
60
61 pub fn front(&self) -> Option<&Front<Phenotype<C>>> {
62 self.front.as_ref()
63 }
64
65 pub fn ecosystem(&self) -> &Ecosystem<C> {
66 &self.ecosystem
67 }
68
69 pub fn value(&self) -> &T {
70 &self.value
71 }
72
73 pub fn index(&self) -> usize {
74 self.index
75 }
76
77 pub fn metrics(&self) -> &MetricSet {
78 &self.metrics
79 }
80
81 pub fn objective(&self) -> &Objective {
82 &self.objective
83 }
84
85 pub fn population(&self) -> &Population<C> {
86 &self.ecosystem().population()
87 }
88
89 pub fn species(&self) -> Option<&[Species<C>]> {
90 self.ecosystem().species().map(|s| s.as_slice())
91 }
92
93 pub fn time(&self) -> Duration {
94 self.metrics()
95 .get(metric_names::TIME)
96 .map(|m| m.time_statistic().map(|t| t.sum()))
97 .flatten()
98 .unwrap_or_default()
99 }
100
101 pub fn seconds(&self) -> f64 {
102 self.time().as_secs_f64()
103 }
104}
105
106impl<C: Chromosome, T> Scored for Generation<C, T> {
107 fn score(&self) -> Option<&Score> {
108 Some(&self.score)
109 }
110}
111
112impl<C: Chromosome + Clone, T: Clone> From<&Context<C, T>> for Generation<C, T> {
113 fn from(context: &Context<C, T>) -> Self {
114 Generation {
115 ecosystem: context.ecosystem.clone(),
116 value: context.best.clone(),
117 index: context.index,
118 metrics: context.metrics.clone(),
119 score: context.score.clone().unwrap(),
120 objective: context.objective.clone(),
121 front: match context.objective {
122 Objective::Multi(_) => Some(context.front.read().unwrap().clone()),
123 _ => None,
124 },
125 }
126 }
127}
128
129impl<C: Chromosome, T: Debug> Debug for Generation<C, T> {
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 write!(f, "Generation {{\n")?;
132 write!(f, " value: {:?},\n", self.value)?;
133 write!(f, " score: {:?},\n", self.score)?;
134 write!(f, " index: {:?},\n", self.index)?;
135 write!(f, " size: {:?},\n", self.ecosystem.population.len())?;
136 write!(f, " duration: {:?},\n", self.time())?;
137
138 if let Some(species) = &self.ecosystem.species {
139 for s in species {
140 write!(f, " species: {:?},\n", s)?;
141 }
142 }
143
144 write!(f, " metrics: {:?},\n", self.metrics)?;
145 write!(f, "}}")
146 }
147}
148
149impl<C, T> FromIterator<Generation<C, T>> for Front<Phenotype<C>>
150where
151 C: Chromosome + Clone,
152{
153 fn from_iter<I: IntoIterator<Item = Generation<C, T>>>(iter: I) -> Self {
154 iter.into_iter()
155 .last()
156 .map(|generation| generation.front().map(|front| front.clone()))
157 .flatten()
158 .unwrap_or_default()
159 }
160}