radiate_core/genome/chromosomes/
int.rs

1use super::{
2    Chromosome, Integer,
3    gene::{ArithmeticGene, Gene, Valid},
4};
5use crate::{chromosomes::BoundedGene, random_provider};
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8use std::{
9    fmt::Debug,
10    ops::{Add, Div, Mul, Range, Sub},
11};
12
13#[macro_export]
14macro_rules! impl_integer {
15    ($($t:ty),*) => {
16        $(
17            impl Integer<$t> for $t {
18                const MIN: $t = <$t>::MIN;
19                const MAX: $t = <$t>::MAX;
20                const ZERO: $t = 0;
21                const ONE: $t = 1;
22                const TWO: $t = 2;
23
24                fn sat_add(self, rhs: $t) -> $t {
25                    self.saturating_add(rhs)
26                }
27
28                fn sat_sub(self, rhs: $t) -> $t {
29                    self.saturating_sub(rhs)
30                }
31
32                fn sat_mul(self, rhs: $t) -> $t {
33                    self.saturating_mul(rhs)
34                }
35
36                fn sat_div(self, rhs: $t) -> $t {
37                    if rhs == Self::ZERO {
38                        self.saturating_div(Self::ONE)
39                    } else {
40                        self.saturating_div(rhs)
41                    }
42                }
43
44                fn clamp(self, min: $t, max: $t) -> $t {
45                    if self < min {
46                        min
47                    } else if self > max {
48                        max
49                    } else {
50                        self
51                    }
52                }
53            }
54        )*
55    };
56}
57
58/// A [`Gene`] that represents an integer value. This gene just wraps an integer value and provides
59/// functionality for it to be used in a genetic algorithm. In this [`Gene`] implementation, the
60/// `allele` is the integer value itself, the min and max values are the minimum and maximum values
61/// that the integer can be generated from, and the upper and lower bounds are the upper and lower bounds the gene will
62/// be subject to during crossover and mutation. If the `allele` exceedes the bounds, the [`Gene`] will be considered invalid.
63///
64/// [`IntGene`] is generic over `T` - the type of integer. The `Integer` trait is implemented
65/// for `i8`, `i16`, `i32`, `i64`, `i128`, `u8`, `u16`, `u32`, `u64`, and `u128`.
66///
67/// # Example
68/// ``` rust
69/// use radiate_core::*;
70///
71/// // Create a new IntGene with an allele of 5, the min value will be i32::MIN
72/// // and the max value will be i32::MAX - same for the upper and lower bounds.
73/// let gene: IntGene<i32> = 5.into();
74///
75/// // Create the same gene, but with a different method
76/// let gene = IntGene::from(5);
77///
78/// // Create a gene, but with a min value of 0 and a max value of 10. In this case,
79/// // the allele will be a random value between 0 and 10. The min and max values will
80/// // be set to 0 and 10, and the upper and lower bounds will be set to 0 and 10.
81/// let gene = IntGene::from(0..10);
82///
83/// // Create a gene with a min value of 0 and a max value of 10, but with upper and lower bounds of 10 and 0.
84/// // In this case, the allele will be a random value between 0 and 10, but the lower and upper bounds will be -10 and 10.
85/// let gene = IntGene::from((0..10, -10..10));
86/// ```
87///
88/// # Type Parameters
89/// - `T`: The type of integer used in the gene.
90#[derive(Clone, PartialEq, Default, Debug)]
91#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
92pub struct IntGene<T: Integer<T>> {
93    allele: T,
94    value_range: Range<T>,
95    bounds: Range<T>,
96}
97
98impl<T: Integer<T>> IntGene<T> {
99    /// Create a new [`IntGene`] with the given allele, value range and bounds.
100    pub fn new(allele: T, value_range: Range<T>, bounds: Range<T>) -> Self {
101        IntGene {
102            allele,
103            value_range,
104            bounds,
105        }
106    }
107}
108
109/// Implement the [`Gene`] trait for [`IntGene`]. This allows the [`IntGene`] to be used in a genetic algorithm.
110impl<T: Integer<T>> Gene for IntGene<T> {
111    type Allele = T;
112
113    fn allele(&self) -> &T {
114        &self.allele
115    }
116
117    fn allele_mut(&mut self) -> &mut T {
118        &mut self.allele
119    }
120
121    /// Create a new instance of the [`IntGene`] with a random allele between the min and max values.
122    fn new_instance(&self) -> IntGene<T> {
123        IntGene {
124            allele: random_provider::range(self.value_range.clone()),
125            value_range: self.value_range.clone(),
126            bounds: self.bounds.clone(),
127        }
128    }
129
130    fn with_allele(&self, allele: &T) -> IntGene<T> {
131        IntGene {
132            allele: *allele,
133            value_range: self.value_range.clone(),
134            bounds: self.bounds.clone(),
135        }
136    }
137}
138
139/// Implement the `Valid` trait for [`IntGene`]. This allows the [`IntGene`] to be checked for validity.
140/// An [`IntGene`] is valid if the `allele` is between the `min` and `max` values.
141///
142/// Note: the bounds are used for crossover and mutation.
143impl<T: Integer<T>> Valid for IntGene<T> {
144    fn is_valid(&self) -> bool {
145        self.allele >= self.bounds.start && self.allele <= self.bounds.end
146    }
147}
148
149/// Implement the `BoundedGene` trait for [`IntGene`]. This allows parts of radiate to
150/// access the 'min', 'max', and bounds values of the [`IntGene`].
151impl<T: Integer<T>> BoundedGene for IntGene<T> {
152    fn min(&self) -> &Self::Allele {
153        &self.value_range.start
154    }
155
156    fn max(&self) -> &Self::Allele {
157        &self.value_range.end
158    }
159
160    fn bounds(&self) -> (&Self::Allele, &Self::Allele) {
161        (&self.bounds.start, &self.bounds.end)
162    }
163}
164
165/// Implement the `ArithmeticGene` trait for [`IntGene`]. This allows the [`IntGene`] to be used in numeric
166/// operations. The `ArithmeticGene` trait is a superset of the [`Gene`] trait, and adds functionality
167/// for numeric operations such as addition, subtraction, multiplication, division and mean.
168impl<T: Integer<T>> ArithmeticGene for IntGene<T> {
169    fn mean(&self, other: &IntGene<T>) -> IntGene<T> {
170        IntGene {
171            allele: (self.allele.sat_add(other.allele)).sat_div(T::TWO),
172            value_range: self.value_range.clone(),
173            bounds: self.bounds.clone(),
174        }
175    }
176}
177
178impl<T: Integer<T>> Add for IntGene<T> {
179    type Output = IntGene<T>;
180
181    fn add(self, other: IntGene<T>) -> IntGene<T> {
182        IntGene {
183            allele: self
184                .allele
185                .sat_add(other.allele)
186                .clamp(self.bounds.start, self.bounds.end),
187            value_range: self.value_range.clone(),
188            bounds: self.bounds.clone(),
189        }
190    }
191}
192
193impl<T: Integer<T>> Sub for IntGene<T> {
194    type Output = IntGene<T>;
195
196    fn sub(self, other: IntGene<T>) -> IntGene<T> {
197        IntGene {
198            allele: self
199                .allele
200                .sat_sub(other.allele)
201                .clamp(self.bounds.start, self.bounds.end),
202            value_range: self.value_range.clone(),
203            bounds: self.bounds.clone(),
204        }
205    }
206}
207
208impl<T: Integer<T>> Mul for IntGene<T> {
209    type Output = IntGene<T>;
210
211    fn mul(self, other: IntGene<T>) -> IntGene<T> {
212        IntGene {
213            allele: self
214                .allele
215                .sat_mul(other.allele)
216                .clamp(self.bounds.start, self.bounds.end),
217            value_range: self.value_range.clone(),
218            bounds: self.bounds.clone(),
219        }
220    }
221}
222
223impl<T: Integer<T>> Div for IntGene<T> {
224    type Output = IntGene<T>;
225
226    fn div(self, other: IntGene<T>) -> IntGene<T> {
227        IntGene {
228            allele: self
229                .allele
230                .sat_div(other.allele)
231                .clamp(self.bounds.start, self.bounds.end),
232            value_range: self.value_range.clone(),
233            bounds: self.bounds.clone(),
234        }
235    }
236}
237
238impl<T: Integer<T>> From<T> for IntGene<T> {
239    fn from(allele: T) -> Self {
240        IntGene {
241            allele,
242            value_range: T::MIN..T::MAX,
243            bounds: T::MIN..T::MAX,
244        }
245    }
246}
247
248impl<T: Integer<T>> From<Range<T>> for IntGene<T> {
249    fn from(range: Range<T>) -> Self {
250        let (min, max) = (range.start, range.end);
251
252        IntGene {
253            allele: random_provider::range(range),
254            value_range: min..max,
255            bounds: min..max,
256        }
257    }
258}
259
260impl<T: Integer<T>> From<(Range<T>, Range<T>)> for IntGene<T> {
261    fn from((range, bounds): (Range<T>, Range<T>)) -> Self {
262        IntGene {
263            allele: random_provider::range(range.clone()),
264            value_range: range,
265            bounds,
266        }
267    }
268}
269
270impl<T: Integer<T>> std::fmt::Display for IntGene<T> {
271    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
272        write!(f, "{}", self.allele)
273    }
274}
275
276/// Represents a chromosome composed of integer genes.
277///
278/// An [`IntChromosome`] is generic over the integer type `T` and contains a vector of [`IntGene<T>`]
279/// instances. This structure is suitable for optimization problems where solutions are encoded
280/// as integers.
281///
282/// # Type Parameters
283///
284/// * `T` - The integer type used for genes (e.g., `i32`, `u32`).
285///
286/// # Fields
287///
288/// * `genes` - A vector of [`IntGene<T>`] representing the individual's genetic informationn.
289///
290/// # Example
291/// ``` rust
292/// use radiate_core::*;
293///
294/// // Create a new IntChromosome with a vector of IntGene instances.
295/// let genes = vec![IntGene::from(0..10), IntGene::from(10..20)];
296/// let chromosome = IntChromosome::new(genes);
297///
298/// // Check if the chromosome is valid.
299/// assert!(chromosome.is_valid());
300///
301#[derive(Clone, PartialEq, Default)]
302#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
303pub struct IntChromosome<I: Integer<I>> {
304    genes: Vec<IntGene<I>>,
305}
306
307impl<I: Integer<I>> IntChromosome<I> {
308    /// Given a vec of [IntGene]'s, create a new [IntChromosome].
309    pub fn new(genes: Vec<IntGene<I>>) -> Self {
310        IntChromosome { genes }
311    }
312}
313
314impl<I: Integer<I>> Chromosome for IntChromosome<I> {
315    type Gene = IntGene<I>;
316
317    fn genes(&self) -> &[Self::Gene] {
318        &self.genes
319    }
320
321    fn genes_mut(&mut self) -> &mut [Self::Gene] {
322        &mut self.genes
323    }
324}
325
326impl<T: Integer<T>> Valid for IntChromosome<T> {
327    fn is_valid(&self) -> bool {
328        self.genes.iter().all(|gene| gene.is_valid())
329    }
330}
331
332impl<T: Integer<T>> From<IntGene<T>> for IntChromosome<T> {
333    fn from(gene: IntGene<T>) -> Self {
334        IntChromosome { genes: vec![gene] }
335    }
336}
337
338impl<T: Integer<T>> From<Vec<IntGene<T>>> for IntChromosome<T> {
339    fn from(genes: Vec<IntGene<T>>) -> Self {
340        IntChromosome { genes }
341    }
342}
343
344impl<T: Integer<T>> From<(usize, Range<T>)> for IntChromosome<T> {
345    fn from((size, range): (usize, Range<T>)) -> Self {
346        IntChromosome {
347            genes: (0..size).map(|_| IntGene::from(range.clone())).collect(),
348        }
349    }
350}
351
352impl<T: Integer<T>> From<(usize, Range<T>, Range<T>)> for IntChromosome<T> {
353    fn from((size, range, bounds): (usize, Range<T>, Range<T>)) -> Self {
354        IntChromosome {
355            genes: (0..size)
356                .map(|_| IntGene::from((range.clone(), bounds.clone())))
357                .collect(),
358        }
359    }
360}
361
362impl<T: Integer<T>> From<Vec<T>> for IntChromosome<T> {
363    fn from(alleles: Vec<T>) -> Self {
364        IntChromosome {
365            genes: alleles.into_iter().map(IntGene::from).collect(),
366        }
367    }
368}
369
370impl<T: Integer<T>> FromIterator<IntGene<T>> for IntChromosome<T> {
371    fn from_iter<I: IntoIterator<Item = IntGene<T>>>(iter: I) -> Self {
372        IntChromosome {
373            genes: iter.into_iter().collect(),
374        }
375    }
376}
377
378impl<T: Integer<T>> IntoIterator for IntChromosome<T> {
379    type Item = IntGene<T>;
380    type IntoIter = std::vec::IntoIter<IntGene<T>>;
381
382    fn into_iter(self) -> Self::IntoIter {
383        self.genes.into_iter()
384    }
385}
386
387impl<T: Integer<T>> Debug for IntChromosome<T> {
388    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
389        write!(f, "{:?}", self.genes)
390    }
391}
392
393#[cfg(test)]
394mod tests {
395    use super::*;
396
397    #[test]
398    fn test_new() {
399        let gene = IntGene::from(0..10);
400        assert!(gene.allele >= 0 && gene.allele <= 10);
401    }
402
403    #[test]
404    fn test_new_instance() {
405        let gene = IntGene::from(0..10);
406        let new_gene = gene.new_instance();
407        assert!(new_gene.allele >= 0 && new_gene.allele <= 10);
408    }
409
410    #[test]
411    fn test_from_allele() {
412        let gene = IntGene::from(5);
413        let new_gene = gene.with_allele(&5);
414        assert_eq!(new_gene.allele, 5);
415    }
416
417    #[test]
418    fn test_is_valid() {
419        let gene = IntGene::from(0..10);
420        assert!(gene.is_valid());
421    }
422
423    #[test]
424    fn test_bounds() {
425        let gene_one = IntGene::from((0..10, 0..10));
426        let gene_two = IntGene::from((0..10, -100..100));
427
428        let (one_min, one_max) = gene_one.bounds();
429        let (two_min, two_max) = gene_two.bounds();
430
431        assert_eq!(*one_min, 0);
432        assert_eq!(*one_max, 10);
433        assert_eq!(*two_min, -100);
434        assert_eq!(*two_max, 100);
435        assert_eq!(gene_one.min(), &0);
436        assert_eq!(gene_one.max(), &10);
437        assert_eq!(gene_two.min(), &0);
438        assert_eq!(gene_two.max(), &10);
439        assert!(gene_one.is_valid());
440        assert!(gene_two.is_valid());
441    }
442
443    #[test]
444    fn test_mean() {
445        let gene = IntGene::from(5);
446        let other = IntGene::from(5);
447        let new_gene = gene.mean(&other);
448        assert_eq!(new_gene.allele, 5);
449    }
450
451    #[test]
452    fn test_int_arithmetic_doesnt_overflow() {
453        let gene = IntGene::<u8>::from(8_u8);
454        let other = IntGene::<u8>::from(8_u8);
455        let sixteen = IntGene::<u8>::from(16_u8);
456
457        assert_eq!((gene.clone() + other.clone()).allele, 16);
458        assert_eq!((gene.clone() - sixteen.clone()).allele, 0);
459        assert_eq!((gene.clone() * other.clone()).allele, 64);
460
461        let zero = IntGene::<u8>::from(0_u8);
462        assert_eq!((gene.clone() / zero.clone()).allele, 8);
463        assert_eq!((gene.clone() / other.clone()).allele, 1);
464
465        let max = IntGene::<u8>::from(u8::MAX);
466        assert_eq!((max.clone() + other.clone()).allele, u8::MAX);
467        assert_eq!((zero.clone() - other.clone()).allele, 0);
468
469        let i_eight = IntGene::<i8>::from(8_i8);
470        let i_other = IntGene::<i8>::from(8_i8);
471        let i_sixteen = IntGene::<i8>::from(16_i8);
472
473        assert_eq!((i_eight.clone() + i_other.clone()).allele, 16);
474        assert_eq!((i_eight.clone() - i_sixteen.clone()).allele, -8);
475        assert_eq!((i_eight.clone() * i_other.clone()).allele, 64);
476    }
477
478    #[test]
479    fn test_int_clamp_arithmetic_clamping() {
480        let gene = IntGene::new(5, 5..10, 0..10);
481        let other = IntGene::new(5, 8..10, 0..10);
482        let really_big = IntGene::new(100000, 0..10, 0..10);
483
484        let add = gene.clone() + other.clone();
485        let sub = gene.clone() - other.clone();
486        let mul = gene.clone() * other.clone();
487        let div = gene.clone() / other.clone();
488
489        let really_big_add = gene.clone() + really_big.clone();
490        let really_big_sub = gene.clone() - really_big.clone();
491        let really_big_mul = gene.clone() * really_big.clone();
492        let really_big_div = gene.clone() / really_big.clone();
493
494        assert_eq!(add.allele, 10);
495        assert_eq!(sub.allele, 0);
496        assert_eq!(mul.allele, 10);
497        assert_eq!(div.allele, 1);
498
499        assert_eq!(really_big_add.allele, 10);
500        assert_eq!(really_big_sub.allele, 0);
501        assert_eq!(really_big_mul.allele, 10);
502        assert_eq!(really_big_div.allele, 0);
503    }
504
505    #[test]
506    fn test_into() {
507        let gene: IntGene<i32> = 5.into();
508        assert_eq!(gene.allele, 5);
509    }
510
511    #[test]
512    fn test_chromosome_from_range() {
513        let chromosome = IntChromosome::from((10, 0..10));
514        assert_eq!(chromosome.genes.len(), 10);
515        for gene in &chromosome.genes {
516            assert!(gene.allele >= 0 && gene.allele <= 10);
517        }
518    }
519
520    #[test]
521    fn test_chromosome_from_range_with_bounds() {
522        let chromosome = IntChromosome::from((10, 0..10, -10..10));
523
524        assert_eq!(chromosome.genes.len(), 10);
525        for gene in &chromosome.genes {
526            assert!(gene.allele >= 0 && gene.allele <= 10);
527            assert_eq!(*gene.bounds().0, -10);
528            assert_eq!(*gene.bounds().1, 10);
529        }
530    }
531
532    #[test]
533    fn test_chromosome_from_alleles() {
534        let alleles = vec![1, 2, 3, 4, 5];
535        let chromosome = IntChromosome::from(alleles.clone());
536
537        assert_eq!(chromosome.genes.len(), 5);
538        for (i, gene) in chromosome.genes.iter().enumerate() {
539            assert_eq!(gene.allele, alleles[i]);
540        }
541    }
542
543    #[test]
544    fn test_gene_arithmetic() {
545        let gene_one = IntGene::from(5);
546        let gene_two = IntGene::from(5);
547        let zero_gene = IntGene::from(0);
548
549        let add = gene_one.clone() + gene_two.clone();
550        let sub = gene_one.clone() - gene_two.clone();
551        let mul = gene_one.clone() * gene_two.clone();
552        let div = gene_one.clone() / gene_two.clone();
553        let div_zero = gene_one.clone() / zero_gene.clone();
554        let mean = gene_one.mean(&gene_two);
555
556        assert_eq!(add.allele, 10);
557        assert_eq!(sub.allele, 0);
558        assert_eq!(mul.allele, 25);
559        assert_eq!(div.allele, 1);
560        assert_eq!(div_zero.allele, 5);
561        assert_eq!(mean.allele, 5);
562    }
563
564    #[test]
565    #[cfg(feature = "serde")]
566    fn test_int_gene_serialization() {
567        let gene = IntGene::from(-5_i32..5_i32);
568
569        assert!(gene.is_valid());
570
571        let serialized = serde_json::to_string(&gene).expect("Failed to serialize IntGene");
572        let deserialized: IntGene<i32> =
573            serde_json::from_str(&serialized).expect("Failed to deserialize IntGene");
574
575        let chromosome = IntChromosome::from((10, 0..10, -10..10));
576        let serialized_chromosome =
577            serde_json::to_string(&chromosome).expect("Failed to serialize IntChromosome");
578        let deserialized_chromosome: IntChromosome<i32> =
579            serde_json::from_str(&serialized_chromosome)
580                .expect("Failed to deserialize IntChromosome");
581
582        assert_eq!(gene, deserialized);
583        assert_eq!(chromosome, deserialized_chromosome);
584    }
585}