Skip to main content

radiate_core/codecs/
int.rs

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