radiate_engines/
generation.rs1use 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#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
44pub struct Generation<C, T>
45where
46 C: Chromosome,
47{
48 ecosystem: Ecosystem<C>,
49 value: T,
50 index: usize,
51 metrics: MetricSet,
52 score: Score,
53 objective: Objective,
54 front: Option<Front<Phenotype<C>>>,
55}
56
57impl<C, T> Generation<C, T>
58where
59 C: Chromosome,
60{
61 pub fn score(&self) -> &Score {
62 &self.score
63 }
64
65 pub fn front(&self) -> Option<&Front<Phenotype<C>>> {
66 self.front.as_ref()
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 ecosystem(&self) -> &Ecosystem<C> {
86 &self.ecosystem
87 }
88
89 pub fn population(&self) -> &Population<C> {
90 &self.ecosystem().population()
91 }
92
93 pub fn species(&self) -> Option<&[Species<C>]> {
94 self.ecosystem().species().map(|s| s.as_slice())
95 }
96
97 pub fn time(&self) -> Duration {
98 self.metrics()
99 .time()
100 .map(|m| m.time_statistic().map(|t| t.sum()))
101 .flatten()
102 .unwrap_or_default()
103 }
104
105 pub fn seconds(&self) -> f64 {
106 self.time().as_secs_f64()
107 }
108}
109
110impl<C: Chromosome, T> Scored for Generation<C, T> {
111 fn score(&self) -> Option<&Score> {
112 Some(&self.score)
113 }
114}
115
116impl<C, T> From<&Context<C, T>> for Generation<C, T>
117where
118 C: Chromosome + Clone,
119 T: Clone,
120{
121 fn from(context: &Context<C, T>) -> Self {
122 Generation {
123 ecosystem: context.ecosystem.clone(),
124 value: context.best.clone(),
125 index: context.index,
126 metrics: context.metrics.clone(),
127 score: context.score.clone().unwrap(),
128 objective: context.objective.clone(),
129 front: match context.objective {
130 Objective::Multi(_) => Some(context.front.read().unwrap().clone()),
131 _ => None,
132 },
133 }
134 }
135}
136
137impl<C, T> Clone for Generation<C, T>
138where
139 C: Chromosome + Clone,
140 T: Clone,
141{
142 fn clone(&self) -> Self {
143 Generation {
144 ecosystem: self.ecosystem.clone(),
145 value: self.value.clone(),
146 index: self.index,
147 metrics: self.metrics.clone(),
148 score: self.score.clone(),
149 objective: self.objective.clone(),
150 front: self.front.as_ref().map(|f| f.clone()),
151 }
152 }
153}
154
155impl<C, T> Debug for Generation<C, T>
156where
157 C: Chromosome,
158 T: Debug,
159{
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 let ecosystem = &self.ecosystem;
162
163 write!(f, "Generation {{\n")?;
164 write!(f, " metrics: {:?},\n", self.metrics)?;
165 write!(f, " value: {:?},\n", self.value)?;
166 write!(f, " score: {:?},\n", self.score)?;
167 write!(f, " index: {:?},\n", self.index)?;
168 write!(f, " size: {:?},\n", ecosystem.population().len())?;
169 write!(f, " duration: {:?},\n", self.time())?;
170 write!(f, " objective: {:?},\n", self.objective)?;
171
172 if let Some(species) = &ecosystem.species {
173 for s in species {
174 write!(f, " species: {:?},\n", s)?;
175 }
176 }
177
178 write!(f, "}}")
179 }
180}
181
182impl<C, T> FromIterator<Generation<C, T>> for Front<Phenotype<C>>
183where
184 C: Chromosome + Clone,
185{
186 fn from_iter<I: IntoIterator<Item = Generation<C, T>>>(iter: I) -> Self {
187 iter.into_iter()
188 .last()
189 .map(|generation| generation.front().map(|front| front.clone()))
190 .flatten()
191 .unwrap_or_default()
192 }
193}