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}