1#![warn(missing_docs)]
2#![allow(clippy::needless_doctest_main)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5#[cfg(feature = "builtin")]
9pub mod builtin;
10
11pub mod prelude;
14
15#[cfg(feature = "rayon")]
16use rayon::prelude::*;
17
18pub trait Eliminator<G> {
20 fn eliminate(&mut self, genomes: Vec<G>) -> Vec<G>;
22}
23
24pub trait Repopulator<G> {
26 fn repopulate(&mut self, genomes: &mut Vec<G>, target_size: usize);
28}
29
30#[doc(hidden)]
31#[cfg(not(feature = "rayon"))]
32pub trait FeatureBoundedEliminator<G>: Eliminator<G> {}
33#[cfg(not(feature = "rayon"))]
34impl<G, T: Eliminator<G>> FeatureBoundedEliminator<G> for T {}
35
36#[doc(hidden)]
37#[cfg(feature = "rayon")]
38pub trait FeatureBoundedEliminator<G>: Eliminator<G> + Send + Sync {}
39#[cfg(feature = "rayon")]
40impl<G, T: Eliminator<G> + Send + Sync> FeatureBoundedEliminator<G> for T {}
41
42#[doc(hidden)]
43#[cfg(not(feature = "rayon"))]
44pub trait FeatureBoundedRepopulator<G>: Repopulator<G> {}
45#[cfg(not(feature = "rayon"))]
46impl<G, T: Repopulator<G>> FeatureBoundedRepopulator<G> for T {}
47
48#[doc(hidden)]
49#[cfg(feature = "rayon")]
50pub trait FeatureBoundedRepopulator<G>: Repopulator<G> + Send + Sync {}
51#[cfg(feature = "rayon")]
52impl<G, T: Repopulator<G> + Send + Sync> FeatureBoundedRepopulator<G> for T {}
53
54#[doc(hidden)]
55#[cfg(not(feature = "rayon"))]
56pub trait FeatureBoundedGenome {}
57#[cfg(not(feature = "rayon"))]
58impl<T> FeatureBoundedGenome for T {}
59
60#[doc(hidden)]
61#[cfg(feature = "rayon")]
62pub trait FeatureBoundedGenome: Sized + Send + Sync {}
63#[cfg(feature = "rayon")]
64impl<T: Sized + Send + Sync> FeatureBoundedGenome for T {}
65
66pub struct GeneticSim<G: Sized, E: FeatureBoundedEliminator<G>, R: FeatureBoundedRepopulator<G>> {
69 pub genomes: Vec<G>,
71
72 pub eliminator: E,
74
75 pub repopulator: R,
77}
78
79impl<G, E, R> GeneticSim<G, E, R>
80where
81 G: Sized,
82 E: FeatureBoundedEliminator<G>,
83 R: FeatureBoundedRepopulator<G>,
84{
85 pub fn new(starting_genomes: Vec<G>, eliminator: E, repopulator: R) -> Self {
88 Self {
89 genomes: starting_genomes,
90 eliminator,
91 repopulator,
92 }
93 }
94
95 pub fn next_generation(&mut self) {
97 let genomes = std::mem::take(&mut self.genomes);
98
99 let target_size = genomes.len();
100 self.genomes = self.eliminator.eliminate(genomes);
101 self.repopulator.repopulate(&mut self.genomes, target_size);
102 }
103
104 pub fn perform_generations(&mut self, count: usize) {
106 for _ in 0..count {
107 self.next_generation();
108 }
109 }
110}
111
112#[cfg(feature = "genrand")]
114pub trait GenerateRandom {
115 fn gen_random(rng: &mut impl rand::Rng) -> Self;
117}
118
119#[cfg(feature = "genrand")]
121pub trait GenerateRandomCollection<T>
122where
123 T: GenerateRandom,
124{
125 fn gen_random(rng: &mut impl rand::Rng, amount: usize) -> Self;
127}
128
129#[cfg(all(feature = "genrand", feature = "rayon"))]
131pub trait GenerateRandomCollectionParallel<T>
132where
133 T: GenerateRandom + Send,
134{
135 fn par_gen_random(amount: usize) -> Self;
137}
138
139impl<C, T> GenerateRandomCollection<T> for C
140where
141 C: FromIterator<T>,
142 T: GenerateRandom,
143{
144 fn gen_random(rng: &mut impl rand::Rng, amount: usize) -> Self {
145 (0..amount).map(|_| T::gen_random(rng)).collect()
146 }
147}
148
149#[cfg(feature = "rayon")]
150impl<C, T> GenerateRandomCollectionParallel<T> for C
151where
152 C: FromParallelIterator<T>,
153 T: GenerateRandom + Send,
154{
155 fn par_gen_random(amount: usize) -> Self {
156 (0..amount)
157 .into_par_iter()
158 .map(|_| T::gen_random(&mut rand::rng()))
159 .collect()
160 }
161}