radiate_core/codecs/
int.rs

1use super::Codec;
2use crate::genome::Gene;
3use crate::genome::genotype::Genotype;
4use crate::{Chromosome, IntChromosome, Integer};
5use std::ops::Range;
6
7/// A [Codec] for a [Genotype] of `IntGenes`. The `encode` function creates a [Genotype] with `num_chromosomes` chromosomes
8/// and `num_genes` genes per chromosome. The `decode` function creates a `Vec<Vec<T>>` from the [Genotype] where the inner `Vec`
9/// contains the alleles of the `IntGenes` in the chromosome. `T` must implement the `Integer` trait, meaning it must be one of
10/// `i8`, `i16`, `i32`, `i64`, `i128`, `u8`, `u16`, `u32`, `u64`, or `u128`.
11///
12/// The lower and upper bounds of the `IntGenes` can be set with the `with_bounds` function.
13/// The default bounds are equal to `min` and `max`.
14#[derive(Clone)]
15pub struct IntCodec<T: Integer<T>, D = T> {
16    num_chromosomes: usize,
17    num_genes: usize,
18    value_range: Range<T>,
19    bounds: Range<T>,
20    _marker: std::marker::PhantomData<D>,
21}
22
23impl<T: Integer<T>, D> IntCodec<T, D> {
24    pub fn with_bounds(mut self, bounds: Range<T>) -> Self {
25        self.bounds = bounds;
26        self
27    }
28
29    /// The different variants of `IntCodec` are all the same, so this function is used to create
30    /// a new `Genotype` with the given number of chromosomes and genes. The only difference between
31    /// them is the type `D`, which is either a `Vec<Vec<T>>`, `Vec<T>`, or `T`.
32    fn encode_common(&self) -> Genotype<IntChromosome<T>> {
33        Genotype::from(
34            (0..self.num_chromosomes)
35                .map(|_| {
36                    IntChromosome::from((
37                        self.num_genes,
38                        self.value_range.clone(),
39                        self.bounds.clone(),
40                    ))
41                })
42                .collect::<Vec<IntChromosome<T>>>(),
43        )
44    }
45}
46
47impl<T: Integer<T>> IntCodec<T, Vec<Vec<T>>> {
48    /// Create a new `IntCodec` with the given number of chromosomes, genes, min, and max values.
49    /// The f_32 values for each `IntGene` will be randomly generated between the min and max values.
50    pub fn matrix(rows: usize, cols: usize, range: Range<T>) -> Self {
51        IntCodec {
52            num_chromosomes: rows,
53            num_genes: cols,
54            value_range: range.clone(),
55            bounds: range,
56            _marker: std::marker::PhantomData,
57        }
58    }
59}
60
61impl<T: Integer<T>> IntCodec<T, Vec<T>> {
62    /// Create a new `IntCodec` with the given number of chromosomes, genes, min, and max values.
63    /// The f_32 values for each `IntGene` will be randomly generated between the min and max values.
64    pub fn vector(count: usize, range: Range<T>) -> Self {
65        IntCodec {
66            num_chromosomes: 1,
67            num_genes: count,
68            value_range: range.clone(),
69            bounds: range,
70            _marker: std::marker::PhantomData,
71        }
72    }
73}
74
75impl<T: Integer<T>> IntCodec<T, T> {
76    /// Create a new `IntCodec` with the given number of chromosomes, genes, min, and max values.
77    /// The f_32 values for each `IntGene` will be randomly generated between the min and max values.
78    pub fn scalar(range: Range<T>) -> Self {
79        IntCodec {
80            num_chromosomes: 1,
81            num_genes: 1,
82            value_range: range.clone(),
83            bounds: range,
84            _marker: std::marker::PhantomData,
85        }
86    }
87}
88
89/// Implement the [Codec] trait for a [Genotype] of `IntGenes`. This will produce a [Genotype] with the
90/// given number of chromosomes and genes. The `decode` function will create a `Vec<Vec<T>>` or a matrix.
91///
92/// # Example
93/// ``` rust
94/// use radiate_core::*;
95///
96/// // Create a new IntCodec with 10 chromosomes with 10 genes
97/// // per chromosome - a matrix of i32 values.
98/// let codec = IntCodec::matrix(10, 10, 0..100);
99/// let genotype: Genotype<IntChromosome<i32>> = codec.encode();
100/// let decoded: Vec<Vec<i32>> = codec.decode(&genotype);
101/// ```
102impl<T: Integer<T>> Codec<IntChromosome<T>, Vec<Vec<T>>> for IntCodec<T, Vec<Vec<T>>> {
103    fn encode(&self) -> Genotype<IntChromosome<T>> {
104        self.encode_common()
105    }
106
107    fn decode(&self, genotype: &Genotype<IntChromosome<T>>) -> Vec<Vec<T>> {
108        genotype
109            .iter()
110            .map(|chromosome| {
111                chromosome
112                    .iter()
113                    .map(|gene| *gene.allele())
114                    .collect::<Vec<T>>()
115            })
116            .collect::<Vec<Vec<T>>>()
117    }
118}
119
120/// Implement the [Codec] trait for a [Genotype] of `IntGenes`. This will produce a [Genotype] with a single
121/// chromosome and `num_genes` genes. The `decode` function will create a `Vec<T>` or a vector.
122///
123/// # Example
124/// ``` rust
125/// use radiate_core::*;
126///
127/// // Create a new IntCodec with 10 genes
128/// // per chromosome - a  vector of i32 values.
129/// let codec = IntCodec::vector(10, 0..100);
130/// let genotype: Genotype<IntChromosome<i32>> = codec.encode();
131/// let decoded: Vec<i32> = codec.decode(&genotype);
132/// ```
133impl<T: Integer<T>> Codec<IntChromosome<T>, Vec<T>> for IntCodec<T, Vec<T>> {
134    fn encode(&self) -> Genotype<IntChromosome<T>> {
135        self.encode_common()
136    }
137
138    fn decode(&self, genotype: &Genotype<IntChromosome<T>>) -> Vec<T> {
139        genotype
140            .iter()
141            .flat_map(|chromosome| {
142                chromosome
143                    .iter()
144                    .map(|gene| *gene.allele())
145                    .collect::<Vec<T>>()
146            })
147            .collect::<Vec<T>>()
148    }
149}
150
151/// Implement the [Codec] trait for a [Genotype] of `IntGenes`. This will produce a [Genotype] with a single
152/// chromosome and a single gene. The `decode` function will create a `T` or a single value.
153/// The `encode` function creates a [Genotype] with a single chromosomes
154/// and a single gene per chromosome.
155///
156/// # Example
157/// ``` rust
158/// use radiate_core::*;
159///
160/// // Create a new IntCodec with a single gene
161/// // per chromosome - a single i32 value.
162/// let codec = IntCodec::scalar(0..100);
163/// let genotype: Genotype<IntChromosome<i32>> = codec.encode();
164/// let decoded: i32 = codec.decode(&genotype);
165/// ```
166impl<T: Integer<T>> Codec<IntChromosome<T>, T> for IntCodec<T, T> {
167    fn encode(&self) -> Genotype<IntChromosome<T>> {
168        self.encode_common()
169    }
170
171    fn decode(&self, genotype: &Genotype<IntChromosome<T>>) -> T {
172        genotype
173            .iter()
174            .flat_map(|chromosome| {
175                chromosome
176                    .iter()
177                    .map(|gene| *gene.allele())
178                    .collect::<Vec<T>>()
179            })
180            .next()
181            .unwrap_or_default()
182    }
183}
184
185impl<T: Integer<T>> Codec<IntChromosome<T>, Vec<Vec<T>>> for Vec<IntChromosome<T>> {
186    fn encode(&self) -> Genotype<IntChromosome<T>> {
187        Genotype::from(
188            self.iter()
189                .map(|chromosome| {
190                    chromosome
191                        .iter()
192                        .map(|gene| gene.new_instance())
193                        .collect::<IntChromosome<T>>()
194                })
195                .collect::<Vec<IntChromosome<T>>>(),
196        )
197    }
198
199    fn decode(&self, genotype: &Genotype<IntChromosome<T>>) -> Vec<Vec<T>> {
200        genotype
201            .iter()
202            .map(|chromosome| {
203                chromosome
204                    .iter()
205                    .map(|gene| *gene.allele())
206                    .collect::<Vec<T>>()
207            })
208            .collect::<Vec<Vec<T>>>()
209    }
210}
211
212impl<T: Integer<T>> Codec<IntChromosome<T>, Vec<T>> for IntChromosome<T> {
213    fn encode(&self) -> Genotype<IntChromosome<T>> {
214        Genotype::from(
215            self.iter()
216                .map(|gene| gene.new_instance())
217                .collect::<IntChromosome<T>>(),
218        )
219    }
220
221    fn decode(&self, genotype: &Genotype<IntChromosome<T>>) -> Vec<T> {
222        genotype
223            .iter()
224            .flat_map(|chromosome| {
225                chromosome
226                    .iter()
227                    .map(|gene| *gene.allele())
228                    .collect::<Vec<T>>()
229            })
230            .collect::<Vec<T>>()
231    }
232}