1use crate::Chromosome;
2use crate::context::Context;
3use radiate_core::objectives::Scored;
4use radiate_core::{Ecosystem, Front, MetricSet, Objective, Phenotype, Population, Score, Species};
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7use std::fmt::Debug;
8use std::time::Duration;
9
10#[derive(Clone)]
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20pub enum EcosystemSnapshot<C: Chromosome> {
21 Owned(Ecosystem<C>),
22 Shared(Ecosystem<C>),
23}
24
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
72pub struct Generation<C, T>
73where
74 C: Chromosome,
75{
76 ecosystem: EcosystemSnapshot<C>,
77 value: T,
78 index: usize,
79 metrics: MetricSet,
80 score: Score,
81 objective: Objective,
82 front: Option<Front<Phenotype<C>>>,
83}
84
85impl<C, T> Generation<C, T>
86where
87 C: Chromosome,
88{
89 pub fn score(&self) -> &Score {
90 &self.score
91 }
92
93 pub fn front(&self) -> Option<&Front<Phenotype<C>>> {
94 self.front.as_ref()
95 }
96
97 pub fn value(&self) -> &T {
98 &self.value
99 }
100
101 pub fn index(&self) -> usize {
102 self.index
103 }
104
105 pub fn metrics(&self) -> &MetricSet {
106 &self.metrics
107 }
108
109 pub fn objective(&self) -> &Objective {
110 &self.objective
111 }
112
113 pub fn ecosystem(&mut self) -> &Ecosystem<C>
119 where
120 C: Clone,
121 {
122 if let EcosystemSnapshot::Owned(ref eco) = self.ecosystem {
123 return eco;
124 } else if let EcosystemSnapshot::Shared(eco) = &self.ecosystem {
125 self.ecosystem = EcosystemSnapshot::Owned(eco.clone());
126 }
127
128 self.ecosystem()
129 }
130
131 pub fn population(&mut self) -> &Population<C>
134 where
135 C: Clone,
136 {
137 &self.ecosystem().population()
138 }
139
140 pub fn species(&mut self) -> Option<&[Species<C>]>
143 where
144 C: Clone,
145 {
146 self.ecosystem().species().map(|s| s.as_slice())
147 }
148
149 pub fn time(&self) -> Duration {
150 self.metrics()
151 .time()
152 .map(|m| m.time_statistic().map(|t| t.sum()))
153 .flatten()
154 .unwrap_or_default()
155 }
156
157 pub fn seconds(&self) -> f64 {
158 self.time().as_secs_f64()
159 }
160}
161
162impl<C: Chromosome, T> Scored for Generation<C, T> {
163 fn score(&self) -> Option<&Score> {
164 Some(&self.score)
165 }
166}
167
168impl<C, T> From<&Context<C, T>> for Generation<C, T>
169where
170 C: Chromosome + Clone,
171 T: Clone,
172{
173 fn from(context: &Context<C, T>) -> Self {
174 Generation {
175 ecosystem: EcosystemSnapshot::Shared(Ecosystem::clone_ref(&context.ecosystem)),
176 value: context.best.clone(),
177 index: context.index,
178 metrics: context.metrics.clone(),
179 score: context.score.clone().unwrap(),
180 objective: context.objective.clone(),
181 front: match context.objective {
182 Objective::Multi(_) => Some(context.front.read().unwrap().clone()),
183 _ => None,
184 },
185 }
186 }
187}
188
189impl<C, T> Clone for Generation<C, T>
190where
191 C: Chromosome + Clone,
192 T: Clone,
193{
194 fn clone(&self) -> Self {
195 Generation {
196 ecosystem: match &self.ecosystem {
197 EcosystemSnapshot::Owned(eco) => EcosystemSnapshot::Owned(eco.clone()),
198 EcosystemSnapshot::Shared(eco) => EcosystemSnapshot::Owned(eco.clone()),
199 },
200 value: self.value.clone(),
201 index: self.index,
202 metrics: self.metrics.clone(),
203 score: self.score.clone(),
204 objective: self.objective.clone(),
205 front: self.front.as_ref().map(|f| f.clone()),
206 }
207 }
208}
209
210impl<C, T> Debug for Generation<C, T>
211where
212 C: Chromosome,
213 T: Debug,
214{
215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216 let ecosystem = match &self.ecosystem {
217 EcosystemSnapshot::Owned(eco) => eco,
218 EcosystemSnapshot::Shared(eco) => eco,
219 };
220
221 write!(f, "Generation {{\n")?;
222 write!(f, " metrics: {:?},\n", self.metrics)?;
223 write!(f, " value: {:?},\n", self.value)?;
224 write!(f, " score: {:?},\n", self.score)?;
225 write!(f, " index: {:?},\n", self.index)?;
226 write!(f, " size: {:?},\n", ecosystem.population().len())?;
227 write!(f, " duration: {:?},\n", self.time())?;
228 write!(f, " objective: {:?},\n", self.objective)?;
229
230 if let Some(species) = &ecosystem.species {
231 for s in species {
232 write!(f, " species: {:?},\n", s)?;
233 }
234 }
235
236 write!(f, "}}")
237 }
238}
239
240impl<C, T> FromIterator<Generation<C, T>> for Front<Phenotype<C>>
241where
242 C: Chromosome + Clone,
243{
244 fn from_iter<I: IntoIterator<Item = Generation<C, T>>>(iter: I) -> Self {
245 iter.into_iter()
246 .last()
247 .map(|generation| generation.front().map(|front| front.clone()))
248 .flatten()
249 .unwrap_or_default()
250 }
251}