1use crate::archive::Archive;
4use crate::fitness::Fitness;
5use crate::genome::Genome;
6use crate::population::{Individual, Population, PopulationConfig};
7use crate::selection::Selection;
8use crate::variation::{vary, VariationConfig};
9use rand::SeedableRng;
10use rand_chacha::ChaCha8Rng;
11
12#[derive(Debug, Clone)]
14pub struct EvolutionConfig {
15 pub population: PopulationConfig,
17 pub variation: VariationConfig,
19 pub seed: Option<u64>,
21}
22
23impl Default for EvolutionConfig {
24 fn default() -> Self {
25 Self {
26 population: PopulationConfig::default(),
27 variation: VariationConfig::default(),
28 seed: None,
29 }
30 }
31}
32
33#[derive(Debug)]
35pub struct EvolutionResult<G: Genome> {
36 pub population: Population<G>,
38 pub best: Individual<G>,
40 pub generations: usize,
42}
43
44pub struct Evolution<G, F, S>
46where
47 G: Genome,
48 F: Fitness<G>,
49 S: Selection<G>,
50{
51 population: Population<G>,
52 fitness: F,
53 selection: S,
54 archive: Option<Box<dyn Archive<G>>>,
55 config: EvolutionConfig,
56 rng: ChaCha8Rng,
57}
58
59impl<G, F, S> Evolution<G, F, S>
60where
61 G: Genome,
62 F: Fitness<G>,
63 S: Selection<G>,
64{
65 pub fn new(fitness: F, selection: S, config: EvolutionConfig) -> Self {
67 let seed = config.seed.unwrap_or_else(rand::random);
68 let mut rng = ChaCha8Rng::seed_from_u64(seed);
69 let population = Population::random(config.population.clone(), &mut rng);
70
71 Self {
72 population,
73 fitness,
74 selection,
75 archive: None,
76 config,
77 rng,
78 }
79 }
80
81 pub fn with_archive(mut self, archive: Box<dyn Archive<G>>) -> Self {
83 self.archive = Some(archive);
84 self
85 }
86
87 pub fn run(&mut self, generations: usize) -> EvolutionResult<G> {
89 self.evaluate_population();
91
92 for _gen in 0..generations {
93 let offspring = self.create_offspring();
95
96 let evaluated = self.evaluate_batch(offspring);
98
99 if let Some(archive) = &mut self.archive {
101 for ind in &evaluated {
102 archive.add(ind.clone());
103 }
104 }
105
106 self.select_survivors(evaluated);
108
109 self.population.generation += 1;
110 }
111
112 let best = self.population.best().cloned().unwrap_or_else(|| {
113 Individual::new(G::random(&mut self.rng))
114 });
115
116 EvolutionResult {
117 population: self.population.clone(),
118 best,
119 generations,
120 }
121 }
122
123 fn evaluate_population(&mut self) {
124 let unevaluated: Vec<_> = self
126 .population
127 .individuals
128 .iter()
129 .enumerate()
130 .filter(|(_, ind)| ind.fitness.is_none())
131 .map(|(i, ind)| (i, ind.genome.clone()))
132 .collect();
133
134 if unevaluated.is_empty() {
135 return;
136 }
137
138 let genomes: Vec<_> = unevaluated.iter().map(|(_, g)| g.clone()).collect();
140 let results = self.fitness.evaluate_batch(&genomes);
141
142 for ((idx, _), result) in unevaluated.into_iter().zip(results) {
144 self.population.individuals[idx].fitness = Some(result.value);
145 self.population.individuals[idx].behavior = result.behavior;
146 }
147 }
148
149 fn evaluate_batch(&self, mut individuals: Vec<Individual<G>>) -> Vec<Individual<G>> {
150 if individuals.is_empty() {
151 return individuals;
152 }
153
154 let genomes: Vec<_> = individuals.iter().map(|ind| ind.genome.clone()).collect();
156 let results = self.fitness.evaluate_batch(&genomes);
157
158 for (ind, result) in individuals.iter_mut().zip(results) {
160 ind.fitness = Some(result.value);
161 ind.behavior = result.behavior;
162 }
163
164 individuals
165 }
166
167 fn create_offspring(&mut self) -> Vec<Individual<G>> {
168 let count = self.config.population.size - self.config.population.elitism;
169
170 (0..count)
171 .map(|_| {
172 let parent1 = self.selection.select(&self.population, &mut self.rng);
173 let parent2 = self.selection.select(&self.population, &mut self.rng);
174
175 let genome = vary(
176 &parent1.genome,
177 &parent2.genome,
178 &self.config.variation,
179 &mut self.rng,
180 );
181
182 Individual {
183 genome,
184 fitness: None,
185 behavior: None,
186 birth_generation: self.population.generation + 1,
187 }
188 })
189 .collect()
190 }
191
192 fn select_survivors(&mut self, offspring: Vec<Individual<G>>) {
193 let elites: Vec<_> = self
195 .population
196 .top_n(self.config.population.elitism)
197 .into_iter()
198 .cloned()
199 .collect();
200
201 let mut new_pop = elites;
203 new_pop.extend(offspring);
204
205 new_pop.truncate(self.config.population.size);
207
208 self.population.individuals = new_pop;
209 }
210}
211
212use rand_chacha;
214
215use crate::archive::MapElitesArchive;
216
217#[derive(Debug, Clone)]
219pub struct MapElitesConfig {
220 pub batch_size: usize,
222 pub variation: VariationConfig,
224 pub seed: Option<u64>,
226 pub initial_population: usize,
228}
229
230impl Default for MapElitesConfig {
231 fn default() -> Self {
232 Self {
233 batch_size: 100,
234 variation: VariationConfig::default(),
235 seed: None,
236 initial_population: 100,
237 }
238 }
239}
240
241#[derive(Debug)]
243pub struct MapElitesResult<G: Genome> {
244 pub archive: MapElitesArchive<G>,
246 pub best: Option<Individual<G>>,
248 pub generations: usize,
250 pub total_evaluations: usize,
252}
253
254pub struct MapElitesEvolution<G, F>
261where
262 G: Genome,
263 F: Fitness<G>,
264{
265 archive: MapElitesArchive<G>,
266 fitness: F,
267 config: MapElitesConfig,
268 rng: ChaCha8Rng,
269 total_evaluations: usize,
270}
271
272impl<G, F> MapElitesEvolution<G, F>
273where
274 G: Genome,
275 F: Fitness<G>,
276{
277 pub fn new(archive: MapElitesArchive<G>, fitness: F, config: MapElitesConfig) -> Self {
279 let seed = config.seed.unwrap_or_else(rand::random);
280 let rng = ChaCha8Rng::seed_from_u64(seed);
281
282 Self {
283 archive,
284 fitness,
285 config,
286 rng,
287 total_evaluations: 0,
288 }
289 }
290
291 pub fn initialize(&mut self) {
293 let genomes: Vec<G> = (0..self.config.initial_population)
295 .map(|_| G::random(&mut self.rng))
296 .collect();
297
298 let results = self.fitness.evaluate_batch(&genomes);
300
301 for (genome, result) in genomes.into_iter().zip(results) {
303 let mut individual = Individual::new(genome);
304 individual.fitness = Some(result.value);
305 individual.behavior = result.behavior;
306 self.archive.add(individual);
307 self.total_evaluations += 1;
308 }
309 }
310
311 pub fn run(&mut self, generations: usize) -> MapElitesResult<G> {
313 if self.archive.is_empty() {
315 self.initialize();
316 }
317
318 for _gen in 0..generations {
319 self.step();
320 }
321
322 let best = self.archive.best().cloned();
323 let dimensions = self.archive.dimensions().to_vec();
324 let archive = std::mem::replace(&mut self.archive, MapElitesArchive::new(dimensions));
325
326 MapElitesResult {
327 archive,
328 best,
329 generations,
330 total_evaluations: self.total_evaluations,
331 }
332 }
333
334 pub fn step(&mut self) {
336 let offspring = self.create_offspring();
337
338 let genomes: Vec<_> = offspring.iter().map(|ind| ind.genome.clone()).collect();
340 let results = self.fitness.evaluate_batch(&genomes);
341
342 for (mut ind, result) in offspring.into_iter().zip(results) {
344 ind.fitness = Some(result.value);
345 ind.behavior = result.behavior;
346 self.archive.add(ind);
347 self.total_evaluations += 1;
348 }
349 }
350
351 fn create_offspring(&mut self) -> Vec<Individual<G>> {
352 let mut offspring = Vec::with_capacity(self.config.batch_size);
353
354 for _ in 0..self.config.batch_size {
355 let child_genome = if self.archive.len() < 2 {
356 G::random(&mut self.rng)
358 } else {
359 let parent1 = self.archive.select_random(&mut self.rng);
361 let parent2 = self.archive.select_random(&mut self.rng);
362
363 match (parent1, parent2) {
364 (Some(p1), Some(p2)) => {
365 vary(
366 &p1.genome,
367 &p2.genome,
368 &self.config.variation,
369 &mut self.rng,
370 )
371 }
372 _ => G::random(&mut self.rng),
373 }
374 };
375
376 offspring.push(Individual::new(child_genome));
377 }
378
379 offspring
380 }
381
382 pub fn archive(&self) -> &MapElitesArchive<G> {
384 &self.archive
385 }
386
387 pub fn total_evaluations(&self) -> usize {
389 self.total_evaluations
390 }
391
392 pub fn coverage(&self) -> crate::archive::ArchiveCoverage {
394 self.archive.coverage()
395 }
396}