Skip to main content

radiate_core/genome/chromosomes/
gene.rs

1use crate::chromosomes::NumericAllele;
2use std::ops::{Add, Div, Mul, Sub};
3
4/// A [`Valid`] type is a type that can be checked for validity. This is used for checking if a gene
5/// or a chromosome is valid. For example, a gene that represents a number between 0 and 1 can be checked
6/// for validity by ensuring that the allele is between 0 and 1.
7///
8/// The `GeneticEngine` will check the validity of the [Chromosome](super::chromosome::Chromosome) and `Phenotype` and remove any
9/// invalid individuals from the population, replacing them with new individuals at the given generation.
10pub trait Valid {
11    fn is_valid(&self) -> bool {
12        true
13    }
14}
15
16/// A [`Gene`] is a single unit of information in a [Chromosome](super::chromosome::Chromosome).
17/// This is the most basic building block of this entire library.
18///
19/// Any type that implements this trait can be used as a gene in a chromosome, as such
20/// it can be used in any genetic algorithm that uses this library.
21///
22/// # Example
23/// ```
24/// use radiate_core::*;
25///
26/// // A simple gene that represents a point.
27/// #[derive(Clone, Debug, PartialEq)]
28/// struct PointGene {
29///    allele: (f32, f32),
30/// }
31///
32/// // Implement the Gene trait for the PointGene.
33/// impl Gene for PointGene {
34///     type Allele = (f32, f32);
35///
36///     fn allele(&self) -> &Self::Allele {
37///         &self.allele
38///     }
39///
40///     fn allele_mut(&mut self) -> &mut Self::Allele {
41///         &mut self.allele
42///     }
43///
44///     fn new_instance(&self) -> Self {
45///        PointGene { allele: (0.0, 0.0) }
46///     }
47///
48///     fn with_allele(&self, allele: &Self::Allele) -> Self {
49///       PointGene { allele: *allele }
50///     }
51/// }
52///
53/// // You must also implement the [`Valid`] trait for the gene.
54/// // The default implementation of the [`Valid`] trait is to return true.
55/// impl Valid for PointGene {
56///    fn is_valid(&self) -> bool {
57///      let (x, y) = self.allele;
58///     // Check if the x and y values are between 0 and 1.
59///     x >= 0.0 && x <= 1.0 && y >= 0.0 && y <= 1.0
60///   }
61/// }
62/// ```
63pub trait Gene: Clone + Valid {
64    type Allele;
65
66    /// Get the `allele` of the [Gene]. This is the value that the [Gene] represents or "expresses".
67    fn allele(&self) -> &Self::Allele;
68
69    /// Get a mutable reference to the `allele` of the [Gene].
70    fn allele_mut(&mut self) -> &mut Self::Allele;
71
72    /// Create a new instance of the [Gene].
73    fn new_instance(&self) -> Self;
74
75    /// Create a new [Gene] with the given `allele`.
76    fn with_allele(&self, allele: &Self::Allele) -> Self;
77}
78
79pub trait BoundedGene: Gene {
80    fn min(&self) -> &Self::Allele;
81    fn max(&self) -> &Self::Allele;
82    fn bounds(&self) -> (&Self::Allele, &Self::Allele);
83}
84
85/// A [Gene] that represents a number. This gene can be used to represent any type of number,
86/// including integers, floats, etc. Essentially, any gene that can `Add`, `Sub`, `Mul`, and `Div`
87/// can be used as a [ArithmeticGene].
88pub trait ArithmeticGene:
89    Gene + Add<Output = Self> + Sub<Output = Self> + Mul<Output = Self> + Div<Output = Self>
90{
91    fn mean(&self, other: &Self) -> Self;
92}
93
94pub trait NumericGene: Gene
95where
96    Self::Allele: NumericAllele,
97{
98}
99
100impl<G, T> NumericGene for G
101where
102    G: Gene<Allele = T>,
103    T: NumericAllele,
104{
105}