radiate_core/codecs/
bit.rs

1use super::Codec;
2use crate::genome::Gene;
3use crate::genome::genotype::Genotype;
4use crate::{BitChromosome, Chromosome};
5
6/// A [Codec] for a `Genotype` of `BitGenes`. The `encode` function creates a `Genotype` with `num_chromosomes` chromosomes
7/// and `num_genes` genes per chromosome. The `decode` function creates a `Vec<Vec<bool>>` from the `Genotype` where the inner `Vec`
8/// contains the alleles of the `BitGenes` in the chromosome - the `bool` values.
9///
10/// # Example
11/// ``` rust
12/// // In traditional genetic algorithms, a `BitCodec` would be used to create a `Genotype` of `BitGenes`, or a bit string.
13/// // This would simply be created by the following:
14/// use radiate_core::*;
15///
16/// // The number of bits (`BitGenes`) in the bit string
17/// let length = 10;
18///
19/// // Create a new matrix `BitCodec` with a single chromosome and `length` genes
20/// let codec = BitCodec::matrix(1, length);
21///
22/// // Create a new `Genotype` of `BitGenes` with a single chromosome and `length` genes
23/// let genotype = codec.encode();
24///
25/// // Decode the `Genotype` to a `Vec<Vec<bool>>`, then get the first chromosome
26/// let bit_string: Vec<bool> = codec.decode(&genotype)[0].clone();
27/// ```
28#[derive(Clone)]
29pub struct BitCodec<T = ()> {
30    num_chromosomes: usize,
31    num_genes: usize,
32    _marker: std::marker::PhantomData<T>,
33}
34
35impl BitCodec<Vec<Vec<bool>>> {
36    pub fn matrix(num_chromosomes: usize, num_genes: usize) -> Self {
37        BitCodec {
38            num_chromosomes,
39            num_genes,
40            _marker: std::marker::PhantomData,
41        }
42    }
43}
44
45impl BitCodec<Vec<bool>> {
46    pub fn vector(num_genes: usize) -> Self {
47        BitCodec {
48            num_chromosomes: 1,
49            num_genes,
50            _marker: std::marker::PhantomData,
51        }
52    }
53}
54
55impl BitCodec<bool> {
56    pub fn scalar() -> Self {
57        BitCodec {
58            num_chromosomes: 1,
59            num_genes: 1,
60            _marker: std::marker::PhantomData,
61        }
62    }
63}
64
65impl Codec<BitChromosome, Vec<Vec<bool>>> for BitCodec<Vec<Vec<bool>>> {
66    fn encode(&self) -> Genotype<BitChromosome> {
67        Genotype::new(
68            (0..self.num_chromosomes)
69                .map(|_| BitChromosome::new(self.num_genes))
70                .collect::<Vec<BitChromosome>>(),
71        )
72    }
73
74    fn decode(&self, genotype: &Genotype<BitChromosome>) -> Vec<Vec<bool>> {
75        genotype
76            .iter()
77            .map(|chromosome| {
78                chromosome
79                    .iter()
80                    .map(|gene| *gene.allele())
81                    .collect::<Vec<bool>>()
82            })
83            .collect::<Vec<Vec<bool>>>()
84    }
85}
86
87impl Codec<BitChromosome, Vec<bool>> for BitCodec<Vec<bool>> {
88    fn encode(&self) -> Genotype<BitChromosome> {
89        Genotype::new(
90            (0..self.num_chromosomes)
91                .map(|_| BitChromosome::new(self.num_genes))
92                .collect::<Vec<BitChromosome>>(),
93        )
94    }
95
96    fn decode(&self, genotype: &Genotype<BitChromosome>) -> Vec<bool> {
97        genotype
98            .iter()
99            .flat_map(|chromosome| {
100                chromosome
101                    .iter()
102                    .map(|gene| *gene.allele())
103                    .collect::<Vec<bool>>()
104            })
105            .collect::<Vec<bool>>()
106    }
107}
108
109impl Codec<BitChromosome, bool> for BitCodec<bool> {
110    fn encode(&self) -> Genotype<BitChromosome> {
111        Genotype::new(
112            (0..self.num_chromosomes)
113                .map(|_| BitChromosome::new(self.num_genes))
114                .collect::<Vec<BitChromosome>>(),
115        )
116    }
117
118    fn decode(&self, genotype: &Genotype<BitChromosome>) -> bool {
119        genotype
120            .iter()
121            .flat_map(|chromosome| {
122                chromosome
123                    .iter()
124                    .map(|gene| *gene.allele())
125                    .collect::<Vec<bool>>()
126            })
127            .next()
128            .unwrap_or(false)
129    }
130}
131
132impl Codec<BitChromosome, Vec<Vec<bool>>> for Vec<BitChromosome> {
133    fn encode(&self) -> Genotype<BitChromosome> {
134        Genotype::from(
135            self.iter()
136                .map(|chromosome| {
137                    chromosome
138                        .iter()
139                        .map(|gene| gene.new_instance())
140                        .collect::<BitChromosome>()
141                })
142                .collect::<Vec<BitChromosome>>(),
143        )
144    }
145
146    fn decode(&self, genotype: &Genotype<BitChromosome>) -> Vec<Vec<bool>> {
147        genotype
148            .iter()
149            .map(|chromosome| {
150                chromosome
151                    .iter()
152                    .map(|gene| *gene.allele())
153                    .collect::<Vec<bool>>()
154            })
155            .collect::<Vec<Vec<bool>>>()
156    }
157}
158
159impl Codec<BitChromosome, Vec<bool>> for BitChromosome {
160    fn encode(&self) -> Genotype<BitChromosome> {
161        Genotype::from(
162            self.iter()
163                .map(|gene| gene.new_instance())
164                .collect::<BitChromosome>(),
165        )
166    }
167
168    fn decode(&self, genotype: &Genotype<BitChromosome>) -> Vec<bool> {
169        genotype
170            .iter()
171            .flat_map(|chromosome| {
172                chromosome
173                    .iter()
174                    .map(|gene| *gene.allele())
175                    .collect::<Vec<bool>>()
176            })
177            .collect::<Vec<bool>>()
178    }
179}
180
181#[cfg(test)]
182mod tests {
183    use super::*;
184    use crate::Codec;
185
186    #[test]
187    fn test_bit_codec() {
188        let codec = BitCodec::matrix(2, 3);
189        let genotype = codec.encode();
190        assert_eq!(genotype.len(), 2);
191        assert_eq!(genotype[0].len(), 3);
192        assert_eq!(genotype[1].len(), 3);
193
194        let decoded = codec.decode(&genotype);
195        assert_eq!(decoded.len(), 2);
196        assert_eq!(decoded[0].len(), 3);
197        assert_eq!(decoded[1].len(), 3);
198    }
199
200    #[test]
201    fn test_bit_codec_vector() {
202        let codec = BitCodec::vector(5);
203        let genotype = codec.encode();
204        assert_eq!(genotype.len(), 1);
205        assert_eq!(genotype[0].len(), 5);
206
207        let decoded = codec.decode(&genotype);
208        assert_eq!(decoded.len(), 5);
209    }
210
211    #[test]
212    fn test_bit_codec_scalar() {
213        let codec = BitCodec::scalar();
214        let genotype = codec.encode();
215        assert_eq!(genotype.len(), 1);
216        assert_eq!(genotype[0].len(), 1);
217
218        let decoded = codec.decode(&genotype);
219
220        assert!(vec![true, false].contains(&decoded));
221    }
222}