genetic_algorithm/fitness/
placeholders.rs1use crate::allele::RangeAllele;
3use crate::chromosome::GenesOwner;
4use crate::fitness::{Fitness, FitnessChromosome, FitnessPopulation, FitnessValue};
5use crate::genotype::{
6 BinaryGenotype, BitGenotype, DynamicMatrixGenotype, Genotype, StaticMatrixGenotype,
7};
8use rand::distributions::uniform::SampleUniform;
9use rand::distributions::{Distribution, Uniform};
10use rand::rngs::SmallRng;
11use rand::SeedableRng;
12use std::marker::PhantomData;
13use std::ops::Range;
14use std::{thread, time};
15
16#[derive(Clone, Debug)]
18pub struct Zero<G: Genotype>(PhantomData<G>);
19impl<G: Genotype> Zero<G> {
20 pub fn new() -> Self {
21 Self(PhantomData)
22 }
23}
24impl<G: Genotype> Default for Zero<G> {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29impl<G: Genotype> Fitness for Zero<G> {
30 type Genotype = G;
31 fn calculate_for_chromosome(
32 &mut self,
33 _chromosome: &FitnessChromosome<Self>,
34 _genotype: &Self::Genotype,
35 ) -> Option<FitnessValue> {
36 Some(0)
37 }
38}
39
40#[derive(Clone, Debug)]
42pub struct CountTrue;
43impl Fitness for CountTrue {
44 type Genotype = BinaryGenotype;
45 fn calculate_for_chromosome(
46 &mut self,
47 chromosome: &FitnessChromosome<Self>,
48 _genotype: &Self::Genotype,
49 ) -> Option<FitnessValue> {
50 Some(chromosome.genes.iter().filter(|&value| *value).count() as FitnessValue)
51 }
52}
53
54#[derive(Clone, Debug)]
56pub struct CountOnes;
57impl Fitness for CountOnes {
58 type Genotype = BitGenotype;
59 fn calculate_for_chromosome(
60 &mut self,
61 chromosome: &FitnessChromosome<Self>,
62 _genotype: &Self::Genotype,
63 ) -> Option<FitnessValue> {
64 Some(chromosome.genes.count_ones(..) as FitnessValue)
65 }
66}
67
68#[derive(Clone, Debug)]
74pub struct SumGenes<G: Genotype> {
75 precision: f64,
76 _phantom: PhantomData<G>,
77}
78impl<G: Genotype> SumGenes<G> {
79 pub fn new() -> Self {
80 Self::default()
81 }
82 pub fn new_with_precision(precision: f64) -> Self {
83 Self {
84 precision,
85 ..Default::default()
86 }
87 }
88}
89impl<G: Genotype> Default for SumGenes<G> {
90 fn default() -> Self {
91 Self {
92 precision: 1.0_f64,
93 _phantom: PhantomData,
94 }
95 }
96}
97impl<G: Genotype> Fitness for SumGenes<G>
98where
99 G::Allele: Into<f64>,
100 G::Genes: IntoIterator<Item = G::Allele>,
101 G::Chromosome: GenesOwner<Genes = G::Genes>,
102{
103 type Genotype = G;
104 fn calculate_for_chromosome(
105 &mut self,
106 chromosome: &FitnessChromosome<Self>,
107 _genotype: &Self::Genotype,
108 ) -> Option<FitnessValue> {
109 let sum: f64 = chromosome
110 .genes()
111 .clone()
112 .into_iter()
113 .fold(0.0_f64, |acc, e| acc + e.into());
114 Some((sum / self.precision) as FitnessValue)
115 }
116}
117
118#[derive(Clone, Debug)]
124pub struct SumDynamicMatrix<T: RangeAllele + Into<f64>>
125where
126 T: SampleUniform,
127 Uniform<T>: Send + Sync,
128{
129 precision: f64,
130 _phantom: PhantomData<T>,
131}
132impl<T: RangeAllele + Into<f64>> SumDynamicMatrix<T>
133where
134 T: SampleUniform,
135 Uniform<T>: Send + Sync,
136{
137 pub fn new() -> Self {
138 Self::default()
139 }
140 pub fn new_with_precision(precision: f64) -> Self {
141 Self {
142 precision,
143 ..Default::default()
144 }
145 }
146}
147impl<T: RangeAllele + Into<f64>> Default for SumDynamicMatrix<T>
148where
149 T: SampleUniform,
150 Uniform<T>: Send + Sync,
151{
152 fn default() -> Self {
153 Self {
154 precision: 1.0_f64,
155 _phantom: PhantomData,
156 }
157 }
158}
159impl<T: RangeAllele + Into<f64>> Fitness for SumDynamicMatrix<T>
160where
161 T: SampleUniform,
162 Uniform<T>: Send + Sync,
163{
164 type Genotype = DynamicMatrixGenotype<T>;
165 fn calculate_for_population(
166 &mut self,
167 _population: &FitnessPopulation<Self>,
168 genotype: &Self::Genotype,
169 ) -> Vec<Option<FitnessValue>> {
170 genotype
171 .data
172 .chunks(genotype.genes_size())
173 .map(|genes| {
174 (genes.iter().copied().fold(0.0_f64, |acc, e| acc + e.into()) / self.precision)
175 as FitnessValue
176 })
177 .map(Some)
178 .collect()
179 }
180}
181
182#[derive(Clone, Debug)]
188pub struct SumStaticMatrix<T: RangeAllele + Into<f64>, const N: usize, const M: usize>
189where
190 T: SampleUniform,
191 Uniform<T>: Send + Sync,
192{
193 precision: f64,
194 _phantom: PhantomData<T>,
195}
196impl<T: RangeAllele + Into<f64>, const N: usize, const M: usize> SumStaticMatrix<T, N, M>
197where
198 T: SampleUniform,
199 Uniform<T>: Send + Sync,
200{
201 pub fn new() -> Self {
202 Self::default()
203 }
204 pub fn new_with_precision(precision: f64) -> Self {
205 Self {
206 precision,
207 ..Default::default()
208 }
209 }
210}
211impl<T: RangeAllele + Into<f64>, const N: usize, const M: usize> Default
212 for SumStaticMatrix<T, N, M>
213where
214 T: SampleUniform,
215 Uniform<T>: Send + Sync,
216{
217 fn default() -> Self {
218 Self {
219 precision: 1.0_f64,
220 _phantom: PhantomData,
221 }
222 }
223}
224
225impl<T: RangeAllele + Into<f64>, const N: usize, const M: usize> Fitness
226 for SumStaticMatrix<T, N, M>
227where
228 T: SampleUniform,
229 Uniform<T>: Send + Sync,
230{
231 type Genotype = StaticMatrixGenotype<T, N, M>;
232 fn calculate_for_population(
233 &mut self,
234 _population: &FitnessPopulation<Self>,
235 genotype: &Self::Genotype,
236 ) -> Vec<Option<FitnessValue>> {
237 genotype
238 .data
239 .iter()
240 .map(|genes| {
241 (genes.iter().copied().fold(0.0_f64, |acc, e| acc + e.into()) / self.precision)
242 as FitnessValue
243 })
244 .map(Some)
245 .collect()
246 }
247}
248
249#[derive(Debug)]
251pub struct CountTrueWithSleep {
252 pub micro_seconds: u64,
253 pub print_on_clone: bool,
254}
255impl CountTrueWithSleep {
256 pub fn new(micro_seconds: u64, print_on_clone: bool) -> Self {
257 Self {
258 micro_seconds,
259 print_on_clone,
260 }
261 }
262}
263impl Fitness for CountTrueWithSleep {
264 type Genotype = BinaryGenotype;
265 fn calculate_for_chromosome(
266 &mut self,
267 chromosome: &FitnessChromosome<Self>,
268 _genotype: &Self::Genotype,
269 ) -> Option<FitnessValue> {
270 thread::sleep(time::Duration::from_micros(self.micro_seconds));
271 Some(chromosome.genes.iter().filter(|&value| *value).count() as FitnessValue)
272 }
273}
274impl Clone for CountTrueWithSleep {
275 fn clone(&self) -> Self {
276 if self.print_on_clone {
277 println!("Cloned CountTrueWithSleep: {:?}", thread::current().id());
278 }
279 Self {
280 micro_seconds: self.micro_seconds,
281 print_on_clone: self.print_on_clone,
282 }
283 }
284}
285
286#[derive(Clone, Debug)]
288pub struct Countdown<G: Genotype>(usize, PhantomData<G>);
289impl<G: Genotype> Countdown<G> {
290 pub fn new(start: usize) -> Self {
291 Self(start, PhantomData)
292 }
293}
294impl<G: Genotype> Fitness for Countdown<G> {
295 type Genotype = G;
296 fn calculate_for_chromosome(
297 &mut self,
298 _chromosome: &FitnessChromosome<Self>,
299 _genotype: &Self::Genotype,
300 ) -> Option<FitnessValue> {
301 if self.0 == 0 {
302 Some(0)
303 } else {
304 self.0 -= 1;
305 Some(self.0 as FitnessValue)
306 }
307 }
308}
309
310#[derive(Clone, Debug)]
312pub struct CountdownNoisy<G: Genotype> {
313 start: usize,
314 step: usize,
315 noise_sampler: Uniform<usize>,
316 rng: SmallRng,
317 _phantom: PhantomData<G>,
318}
319impl<G: Genotype> CountdownNoisy<G> {
320 pub fn new(start: usize, step: usize, noise_range: Range<usize>) -> Self {
321 Self {
322 start,
323 step,
324 noise_sampler: Uniform::from(noise_range),
325 rng: SmallRng::seed_from_u64(0),
326 _phantom: PhantomData,
327 }
328 }
329}
330impl<G: Genotype> Fitness for CountdownNoisy<G> {
331 type Genotype = G;
332 fn calculate_for_chromosome(
333 &mut self,
334 _chromosome: &FitnessChromosome<Self>,
335 _genotype: &Self::Genotype,
336 ) -> Option<FitnessValue> {
337 if self.start == 0 {
338 Some(0)
339 } else {
340 self.start -= 1;
341 let base = (self.start / self.step + 1) * self.step;
342 let result = base + self.noise_sampler.sample(&mut self.rng);
343 Some(result as FitnessValue)
344 }
345 }
346}