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