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
11#[cfg(feature = "speciation")]
13pub mod speciation;
14
15pub mod prelude;
18
19#[cfg(feature = "rayon")]
20use rayon::prelude::*;
21
22pub trait Eliminator<G> {
24 fn eliminate(&mut self, genomes: Vec<G>) -> Vec<G>;
26}
27
28pub trait Repopulator<G> {
30 fn repopulate(&mut self, genomes: &mut Vec<G>, target_size: usize);
32}
33
34#[doc(hidden)]
35#[cfg(not(feature = "rayon"))]
36pub trait FeatureBoundedEliminator<G>: Eliminator<G> {}
37#[cfg(not(feature = "rayon"))]
38impl<G, T: Eliminator<G>> FeatureBoundedEliminator<G> for T {}
39
40#[doc(hidden)]
41#[cfg(feature = "rayon")]
42pub trait FeatureBoundedEliminator<G>: Eliminator<G> + Send + Sync {}
43#[cfg(feature = "rayon")]
44impl<G, T: Eliminator<G> + Send + Sync> FeatureBoundedEliminator<G> for T {}
45
46#[doc(hidden)]
47#[cfg(not(feature = "rayon"))]
48pub trait FeatureBoundedRepopulator<G>: Repopulator<G> {}
49#[cfg(not(feature = "rayon"))]
50impl<G, T: Repopulator<G>> FeatureBoundedRepopulator<G> for T {}
51
52#[doc(hidden)]
53#[cfg(feature = "rayon")]
54pub trait FeatureBoundedRepopulator<G>: Repopulator<G> + Send + Sync {}
55#[cfg(feature = "rayon")]
56impl<G, T: Repopulator<G> + Send + Sync> FeatureBoundedRepopulator<G> for T {}
57
58#[doc(hidden)]
59#[cfg(not(feature = "rayon"))]
60pub trait FeatureBoundedGenome {}
61#[cfg(not(feature = "rayon"))]
62impl<T> FeatureBoundedGenome for T {}
63
64#[doc(hidden)]
65#[cfg(feature = "rayon")]
66pub trait FeatureBoundedGenome: Sized + Send + Sync {}
67#[cfg(feature = "rayon")]
68impl<T: Sized + Send + Sync> FeatureBoundedGenome for T {}
69
70pub struct GeneticSim<G: Sized, E: FeatureBoundedEliminator<G>, R: FeatureBoundedRepopulator<G>> {
73 pub genomes: Vec<G>,
75
76 pub eliminator: E,
78
79 pub repopulator: R,
81}
82
83impl<G, E, R> GeneticSim<G, E, R>
84where
85 G: Sized,
86 E: FeatureBoundedEliminator<G>,
87 R: FeatureBoundedRepopulator<G>,
88{
89 pub fn new(starting_genomes: Vec<G>, eliminator: E, repopulator: R) -> Self {
92 Self {
93 genomes: starting_genomes,
94 eliminator,
95 repopulator,
96 }
97 }
98
99 pub fn next_generation(&mut self) {
101 let genomes = std::mem::take(&mut self.genomes);
102
103 let target_size = genomes.len();
104 self.genomes = self.eliminator.eliminate(genomes);
105 self.repopulator.repopulate(&mut self.genomes, target_size);
106 }
107
108 pub fn perform_generations(&mut self, count: usize) {
110 for _ in 0..count {
111 self.next_generation();
112 }
113 }
114}
115
116#[cfg(feature = "genrand")]
118pub trait GenerateRandom {
119 fn gen_random(rng: &mut impl rand::Rng) -> Self;
121}
122
123#[cfg(feature = "genrand")]
125pub trait GenerateRandomCollection<T>
126where
127 T: GenerateRandom,
128{
129 fn gen_random(rng: &mut impl rand::Rng, amount: usize) -> Self;
131}
132
133#[cfg(feature = "genrand")]
134impl<C, T> GenerateRandomCollection<T> for C
135where
136 C: FromIterator<T>,
137 T: GenerateRandom,
138{
139 fn gen_random(rng: &mut impl rand::Rng, amount: usize) -> Self {
140 (0..amount).map(|_| T::gen_random(rng)).collect()
141 }
142}
143
144#[cfg(all(feature = "genrand", feature = "rayon"))]
146pub trait GenerateRandomCollectionParallel<T>
147where
148 T: GenerateRandom + Send,
149{
150 fn par_gen_random(amount: usize) -> Self;
152}
153
154#[cfg(feature = "rayon")]
155impl<C, T> GenerateRandomCollectionParallel<T> for C
156where
157 C: FromParallelIterator<T>,
158 T: GenerateRandom + Send,
159{
160 fn par_gen_random(amount: usize) -> Self {
161 (0..amount)
162 .into_par_iter()
163 .map(|_| T::gen_random(&mut rand::rng()))
164 .collect()
165 }
166}