Skip to main content

radiate_core/genome/chromosomes/
float.rs

1use super::{
2    Chromosome,
3    gene::{ArithmeticGene, BoundedGene, Gene, Valid},
4};
5use crate::random_provider;
6use radiate_utils::Float;
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9use std::{
10    fmt::{Debug, Display},
11    ops::{Add, Div, Mul, Range, Sub},
12};
13
14/// A [`Gene`] that represents a floating point number.
15/// The `allele` is the in the case of the [`FloatGene`] is of type `F` - which is a floating point type.
16/// The `min` and `max` values default to `F::MIN` and `F::MAX` respectively.
17/// During evolution, the `value_range` is used to generate new allele values, while the `bounds` are used
18/// to ensure that the `allele` remains within a valid range. If no `bounds` are provided, they default to the same values as `value_range`.
19///
20/// # Example
21/// ``` rust
22/// use radiate_core::*;
23///
24/// // Create a new FloatGene with a min value of 0 and a max value of 1 meaning the
25/// // allele will be a random number between 0 and 1.
26/// // The upper_bound and lower_bound are set to 0 and 1 respectively.
27/// let gene = FloatGene::from(0_f32..1_f32);
28///
29/// // Create a new FloatGene with a min of 0 and a max of 1 and set the upper_bound
30/// // and lower_bound to 0 and 100 respectively.
31/// let gene = FloatGene::from((0_f32..1_f32, 0_f32..100_f32));
32/// ```
33#[derive(Clone, PartialEq, Debug)]
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35pub struct FloatGene<F: Float> {
36    allele: F,
37    value_range: Range<F>,
38    bounds: Range<F>,
39}
40
41impl<F: Float> FloatGene<F> {
42    /// Creates a new [`FloatGene`] with the given `allele`, `value_range`, and `bounds`.
43    pub fn new(allele: F, value_range: Range<F>, bounds: Range<F>) -> Self {
44        FloatGene {
45            allele,
46            value_range: value_range.start.max(F::MIN)..value_range.end.min(F::MAX),
47            bounds: bounds.start.max(F::MIN)..bounds.end.min(F::MAX),
48        }
49    }
50}
51
52/// Implement the [`Valid`] trait for the [`FloatGene`].
53///
54/// The `is_valid` method checks if the `allele` of the [`FloatGene`] is between the `min` and `max` values.
55/// The `GeneticEngine` will check the validity of the [`Chromosome`] and `Phenotype` and remove any
56/// invalid individuals from the population, replacing them with new individuals at the given generation.
57impl<F: Float> Valid for FloatGene<F> {
58    fn is_valid(&self) -> bool {
59        self.allele >= self.bounds.start && self.allele <= self.bounds.end
60    }
61}
62
63impl<F: Float> Gene for FloatGene<F> {
64    type Allele = F;
65
66    fn allele(&self) -> &F {
67        &self.allele
68    }
69
70    fn allele_mut(&mut self) -> &mut F {
71        &mut self.allele
72    }
73
74    fn new_instance(&self) -> FloatGene<F> {
75        FloatGene {
76            allele: random_provider::range(self.value_range.clone()),
77            value_range: self.value_range.clone(),
78            bounds: self.bounds.clone(),
79        }
80    }
81
82    fn with_allele(&self, allele: &F) -> FloatGene<F> {
83        FloatGene {
84            allele: *allele,
85            value_range: self.value_range.clone(),
86            bounds: self.bounds.clone(),
87        }
88    }
89}
90
91impl<F: Float> BoundedGene for FloatGene<F> {
92    fn min(&self) -> &Self::Allele {
93        &self.value_range.start
94    }
95
96    fn max(&self) -> &Self::Allele {
97        &self.value_range.end
98    }
99
100    fn bounds(&self) -> (&Self::Allele, &Self::Allele) {
101        (&self.bounds.start, &self.bounds.end)
102    }
103}
104
105impl<F: Float> ArithmeticGene for FloatGene<F> {
106    fn mean(&self, other: &FloatGene<F>) -> FloatGene<F> {
107        FloatGene {
108            allele: F::safe_mul(F::safe_add(*self.allele(), *other.allele()), F::HALF)
109                .safe_clamp(self.bounds.start, self.bounds.end),
110            value_range: self.value_range.clone(),
111            bounds: self.bounds.clone(),
112        }
113    }
114}
115
116impl<F: Float> Add for FloatGene<F> {
117    type Output = FloatGene<F>;
118
119    fn add(self, other: FloatGene<F>) -> FloatGene<F> {
120        FloatGene {
121            allele: F::safe_add(self.allele, other.allele)
122                .safe_clamp(self.bounds.start, self.bounds.end),
123            value_range: self.value_range.clone(),
124            bounds: self.bounds.clone(),
125        }
126    }
127}
128
129impl<F: Float> Sub for FloatGene<F> {
130    type Output = FloatGene<F>;
131
132    fn sub(self, other: FloatGene<F>) -> FloatGene<F> {
133        FloatGene {
134            allele: F::safe_sub(self.allele, other.allele)
135                .safe_clamp(self.bounds.start, self.bounds.end),
136            value_range: self.value_range.clone(),
137            bounds: self.bounds.clone(),
138        }
139    }
140}
141
142impl<F: Float> Mul for FloatGene<F> {
143    type Output = FloatGene<F>;
144
145    fn mul(self, other: FloatGene<F>) -> FloatGene<F> {
146        FloatGene {
147            allele: F::safe_mul(self.allele, other.allele)
148                .safe_clamp(self.bounds.start, self.bounds.end),
149            value_range: self.value_range.clone(),
150            bounds: self.bounds.clone(),
151        }
152    }
153}
154
155impl<F: Float> Div for FloatGene<F> {
156    type Output = FloatGene<F>;
157
158    fn div(self, other: FloatGene<F>) -> FloatGene<F> {
159        FloatGene {
160            allele: F::safe_div(self.allele, other.allele)
161                .safe_clamp(self.bounds.start, self.bounds.end),
162            value_range: self.value_range.clone(),
163            bounds: self.bounds.clone(),
164        }
165    }
166}
167
168impl<F: Float> Default for FloatGene<F> {
169    fn default() -> Self {
170        FloatGene {
171            allele: F::ZERO,
172            value_range: F::MIN..F::MAX,
173            bounds: F::MIN..F::MAX,
174        }
175    }
176}
177
178impl<F: Float> From<F> for FloatGene<F> {
179    fn from(allele: F) -> Self {
180        FloatGene {
181            allele,
182            value_range: F::MIN..F::MAX,
183            bounds: F::MIN..F::MAX,
184        }
185    }
186}
187
188impl<F: Float> From<Range<F>> for FloatGene<F> {
189    fn from(range: Range<F>) -> Self {
190        let (min, max) = (range.start.max(F::MIN), range.end.min(F::MAX));
191
192        FloatGene {
193            allele: random_provider::range(range),
194            value_range: min..max,
195            bounds: min..max,
196        }
197    }
198}
199
200impl<F: Float> From<(Range<F>, Range<F>)> for FloatGene<F> {
201    fn from((value_range, bounds): (Range<F>, Range<F>)) -> Self {
202        let value_range = value_range.start.max(F::MIN)..value_range.end.min(F::MAX);
203        let bounds = bounds.start.max(F::MIN)..bounds.end.min(F::MAX);
204        let allele = random_provider::range(value_range.clone());
205
206        FloatGene {
207            allele,
208            value_range,
209            bounds,
210        }
211    }
212}
213
214impl<F: Float> Display for FloatGene<F> {
215    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216        write!(f, "{}", self.allele)
217    }
218}
219
220/// Represents a chromosome composed of floating-point genes.
221///
222/// A [`FloatChromosome`] contains a vector of [`FloatGene`] instances, each representing
223/// a single floating-point value. This structure is typically used in problems where
224/// solutions are encoded as real numbers.
225///
226/// # Fields
227///
228/// * `genes` - A vector of [`FloatGene`] representing the individual's genetic information.
229///
230/// # Example
231/// ```rust
232/// use radiate_core::*;
233///
234/// // Create a chromosome with 3 genes with alleles 0.0, 1.0, and 2.0 respectively
235/// let chromosome = FloatChromosome::from(vec![0.0, 1.0, 2.0]);
236/// let chromosome_alleles = chromosome
237///     .iter()
238///     .map(|gene| *gene.allele())
239///     .collect::<Vec<f32>>();
240///
241/// assert!(chromosome.is_valid());
242/// assert_eq!(chromosome_alleles.len(), 3);
243/// assert_eq!(chromosome_alleles, vec![0.0, 1.0, 2.0]);
244///
245/// // Create a chromosome with 3 genes all with alleles in the range 0.0 to 10.0
246/// let ranged_chromo = FloatChromosome::from((3, 0.0..10.0));
247/// let ranged_chromo_alleles = ranged_chromo
248///    .iter()
249///    .map(|gene| *gene.allele())
250///    .collect::<Vec<f32>>();
251///
252/// assert!(ranged_chromo.is_valid());
253/// assert_eq!(ranged_chromo_alleles.len(), 3);
254/// for allele in ranged_chromo_alleles {
255///    assert!(allele >= 0.0 && allele <= 10.0);
256/// }
257///```
258#[derive(Clone, PartialEq, Default)]
259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
260pub struct FloatChromosome<F: Float> {
261    genes: Vec<FloatGene<F>>,
262}
263
264impl<F: Float> FloatChromosome<F> {
265    pub fn new(genes: Vec<FloatGene<F>>) -> Self {
266        FloatChromosome { genes }
267    }
268}
269
270impl<F: Float> Chromosome for FloatChromosome<F> {
271    type Gene = FloatGene<F>;
272
273    fn as_slice(&self) -> &[Self::Gene] {
274        &self.genes
275    }
276
277    fn as_mut_slice(&mut self) -> &mut [Self::Gene] {
278        &mut self.genes
279    }
280}
281
282impl<F: Float> Valid for FloatChromosome<F> {
283    fn is_valid(&self) -> bool {
284        self.genes.iter().all(|gene| gene.is_valid())
285    }
286}
287
288impl<F: Float> From<FloatGene<F>> for FloatChromosome<F> {
289    fn from(gene: FloatGene<F>) -> Self {
290        FloatChromosome { genes: vec![gene] }
291    }
292}
293
294impl<F: Float> From<Vec<FloatGene<F>>> for FloatChromosome<F> {
295    fn from(genes: Vec<FloatGene<F>>) -> Self {
296        FloatChromosome { genes }
297    }
298}
299
300impl<F: Float> From<Vec<F>> for FloatChromosome<F> {
301    fn from(alleles: Vec<F>) -> Self {
302        FloatChromosome {
303            genes: alleles.into_iter().map(FloatGene::from).collect(),
304        }
305    }
306}
307
308impl<F: Float> From<(usize, Range<F>)> for FloatChromosome<F> {
309    fn from((size, range): (usize, Range<F>)) -> Self {
310        FloatChromosome {
311            genes: (0..size).map(|_| FloatGene::from(range.clone())).collect(),
312        }
313    }
314}
315
316impl<F: Float> From<(usize, Range<F>, Range<F>)> for FloatChromosome<F> {
317    fn from((size, range, bounds): (usize, Range<F>, Range<F>)) -> Self {
318        FloatChromosome {
319            genes: (0..size)
320                .map(|_| FloatGene::from((range.clone(), bounds.clone())))
321                .collect(),
322        }
323    }
324}
325
326impl<F: Float> FromIterator<FloatGene<F>> for FloatChromosome<F> {
327    fn from_iter<I: IntoIterator<Item = FloatGene<F>>>(iter: I) -> Self {
328        FloatChromosome {
329            genes: iter.into_iter().collect(),
330        }
331    }
332}
333
334impl<F: Float> IntoIterator for FloatChromosome<F> {
335    type Item = FloatGene<F>;
336    type IntoIter = std::vec::IntoIter<FloatGene<F>>;
337
338    fn into_iter(self) -> Self::IntoIter {
339        self.genes.into_iter()
340    }
341}
342
343impl<F: Float> Debug for FloatChromosome<F> {
344    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
345        write!(f, "{:?}", self.genes)
346    }
347}
348
349#[cfg(test)]
350mod tests {
351
352    use super::*;
353
354    const MIN: f32 = -1e18;
355    const MAX: f32 = 1e18;
356
357    #[test]
358    fn test_new() {
359        let gene_one = FloatGene::from(0_f32..1_f32);
360        let gene_two = FloatGene::from((-1.0..1.0, -100.0..100.0));
361        let gene_three = FloatGene::new(10.0, (MIN * 10.0)..(MAX * 10.0), -1000.0..1000.0);
362
363        // assert_eq!(*gene_one.min(), 0_f32);
364        assert_eq!(*gene_one.max(), 1_f32);
365        assert_eq!(gene_one.bounds().0, &0_f32);
366        assert_eq!(gene_one.bounds().1, &1_f32);
367        assert!(gene_one.is_valid());
368
369        // assert_eq!(*gene_two.min(), -1.0);
370        assert_eq!(*gene_two.max(), 1.0);
371        assert_eq!(gene_two.bounds().0, &-100.0);
372        assert_eq!(gene_two.bounds().1, &100.0);
373        assert!(gene_two.is_valid());
374
375        assert_eq!(*gene_three.allele(), 10.0);
376        // assert_eq!(*gene_three.min(), MIN);
377        assert_eq!(*gene_three.max(), MAX * 10.0);
378        assert_eq!(gene_three.bounds().0, &-1000.0);
379        assert_eq!(gene_three.bounds().1, &1000.0);
380    }
381
382    #[test]
383    fn test_from() {
384        let gene = FloatGene::from(0_f32..1_f32);
385        let copy = gene.clone();
386        assert_eq!(gene, copy);
387    }
388
389    #[test]
390    fn test_is_valid() {
391        let gene = FloatGene::from(0_f32..1_f32);
392        assert!(gene.is_valid());
393        assert!(gene.allele >= 0_f32 && gene.allele <= 1_f32);
394    }
395
396    #[test]
397    fn test_gene_clamping() {
398        let one = FloatGene::new(5.0, 0.0..10.0, 0.0..10.0);
399        let two = FloatGene::new(5.0, 0.0..10.0, 0.0..10.0);
400        let really_big = FloatGene::new(100000.0, 0.0..10.0, 0.0..10.0);
401
402        let add = one.clone() + two.clone();
403        let sub = one.clone() - two.clone();
404        let mul = one.clone() * two.clone();
405        let div = one.clone() / two.clone();
406
407        assert_eq!(add.allele, 10.0);
408        assert_eq!(sub.allele, 0.0);
409        assert_eq!(mul.allele, 10.0);
410        assert_eq!(div.allele, 1.0);
411
412        let big_add = one.clone() + really_big.clone();
413        let big_sub = one.clone() - really_big.clone();
414        let big_mul = one.clone() * really_big.clone();
415        let big_div = really_big.clone() / one.clone();
416
417        assert_eq!(big_add.allele, 10.0);
418        assert_eq!(big_sub.allele, 0.0);
419        assert_eq!(big_mul.allele, 10.0);
420        assert_eq!(big_div.allele, 10.0);
421    }
422
423    #[test]
424    fn test_chromosome() {
425        let chromosome = FloatChromosome::from((10, -1.0..1.0));
426
427        assert_eq!(chromosome.len(), 10);
428        assert!(chromosome.is_valid());
429        for gene in chromosome.iter() {
430            assert!(gene.is_valid());
431            assert!(gene.allele >= -1.0 && gene.allele <= 1.0);
432        }
433    }
434
435    #[test]
436    fn test_chromosome_from_vec() {
437        let chromosome = FloatChromosome::from(vec![0.0, 1.0, 2.0]);
438
439        assert_eq!(chromosome.len(), 3);
440        assert!(chromosome.is_valid());
441        for (gene, allele) in chromosome.iter().zip(vec![0.0, 1.0, 2.0]) {
442            assert!(gene.is_valid());
443            assert_eq!(gene.allele, allele);
444        }
445    }
446
447    #[test]
448    fn test_chromosome_from_range_with_bounds() {
449        let chromosome = FloatChromosome::from((3, 0.0..10.0, -10.0..10.0));
450
451        assert_eq!(chromosome.len(), 3);
452        assert!(chromosome.is_valid());
453        for gene in chromosome.iter() {
454            assert!(gene.is_valid());
455            assert!(gene.allele >= 0.0 && gene.allele <= 10.0);
456            assert!(gene.bounds.start >= -10.0 && gene.bounds.end <= 10.0);
457        }
458    }
459
460    #[test]
461    fn test_gene_arithmetic() {
462        let gene_one = FloatGene::from(5_f32);
463        let gene_two = FloatGene::from(10_f32);
464        let zero_gene = FloatGene::from(0_f32);
465
466        let add = gene_one.clone() + gene_two.clone();
467        let sub = gene_one.clone() - gene_two.clone();
468        let mul = gene_one.clone() * gene_two.clone();
469        let div = gene_one.clone() / gene_two.clone();
470        let mean = gene_one.clone().mean(&gene_two.clone());
471        let div_zero = gene_one.clone() / zero_gene.clone();
472
473        assert_eq!(add.allele, 15_f32);
474        assert_eq!(sub.allele, -5_f32);
475        assert_eq!(mul.allele, 50_f32);
476        assert_eq!(div.allele, 0.5_f32);
477        assert_eq!(mean.allele, 7.5_f32);
478        assert_eq!(div_zero.allele, 5_f32);
479    }
480
481    #[test]
482    #[cfg(feature = "serde")]
483    fn test_float_gene_serialization() {
484        let gene = FloatGene::from(0.5_f32..1.5_f32);
485
486        assert!(gene.is_valid());
487
488        let serialized = serde_json::to_string(&gene).expect("Failed to serialize FloatGene");
489        let deserialized: FloatGene<f32> =
490            serde_json::from_str(&serialized).expect("Failed to deserialize FloatGene");
491
492        let chromosome = FloatChromosome::from((10, 0.0..1.0, -1.0..1.0));
493        let serialized_chromosome =
494            serde_json::to_string(&chromosome).expect("Failed to serialize FloatChromosome");
495        let deserialized_chromosome: FloatChromosome<f32> =
496            serde_json::from_str(&serialized_chromosome)
497                .expect("Failed to deserialize FloatChromosome");
498
499        assert_eq!(gene, deserialized);
500        assert_eq!(chromosome, deserialized_chromosome);
501    }
502}