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
132#[cfg(test)]
133mod tests {
134    use super::*;
135    use crate::Codec;
136
137    #[test]
138    fn test_bit_codec() {
139        let codec = BitCodec::matrix(2, 3);
140        let genotype = codec.encode();
141        assert_eq!(genotype.len(), 2);
142        assert_eq!(genotype[0].len(), 3);
143        assert_eq!(genotype[1].len(), 3);
144
145        let decoded = codec.decode(&genotype);
146        assert_eq!(decoded.len(), 2);
147        assert_eq!(decoded[0].len(), 3);
148        assert_eq!(decoded[1].len(), 3);
149    }
150
151    #[test]
152    fn test_bit_codec_vector() {
153        let codec = BitCodec::vector(5);
154        let genotype = codec.encode();
155        assert_eq!(genotype.len(), 1);
156        assert_eq!(genotype[0].len(), 5);
157
158        let decoded = codec.decode(&genotype);
159        assert_eq!(decoded.len(), 5);
160    }
161
162    #[test]
163    fn test_bit_codec_scalar() {
164        let codec = BitCodec::scalar();
165        let genotype = codec.encode();
166        assert_eq!(genotype.len(), 1);
167        assert_eq!(genotype[0].len(), 1);
168
169        let decoded = codec.decode(&genotype);
170
171        assert!(vec![true, false].contains(&decoded));
172    }
173}