radiate_core/codecs/
char.rs

1use super::Codec;
2use crate::chromosomes::char;
3use crate::genome::CharGene;
4use crate::genome::Gene;
5use crate::genome::genotype::Genotype;
6use crate::{CharChromosome, Chromosome};
7use std::sync::Arc;
8
9/// A `Codec` for a `Genotype` of `CharGenes`. The `encode` function creates a `Genotype` with `num_chromosomes` chromosomes
10/// and `num_genes` genes per chromosome. The `decode` function creates a `String` from the `Genotype` where the `String`
11/// contains the alleles of the `CharGenes` in the chromosome.
12#[derive(Clone)]
13pub struct CharCodec<T = ()> {
14    num_chromosomes: usize,
15    num_genes: usize,
16    char_set: Arc<[char]>,
17    _marker: std::marker::PhantomData<T>,
18}
19
20impl<T> CharCodec<T> {
21    pub fn with_char_set(mut self, char_set: impl Into<Arc<[char]>>) -> Self {
22        self.char_set = char_set.into();
23        self
24    }
25}
26
27impl CharCodec<Vec<Vec<char>>> {
28    pub fn matrix(num_chromosomes: usize, num_genes: usize) -> Self {
29        CharCodec {
30            num_chromosomes,
31            num_genes,
32            char_set: char::ALPHABET.chars().collect::<Vec<char>>().into(),
33            _marker: std::marker::PhantomData,
34        }
35    }
36}
37
38impl CharCodec<Vec<char>> {
39    pub fn vector(num_genes: usize) -> Self {
40        CharCodec {
41            num_chromosomes: 1,
42            num_genes,
43            char_set: char::ALPHABET.chars().collect::<Vec<char>>().into(),
44            _marker: std::marker::PhantomData,
45        }
46    }
47}
48
49impl Codec<CharChromosome, Vec<Vec<char>>> for CharCodec<Vec<Vec<char>>> {
50    fn encode(&self) -> Genotype<CharChromosome> {
51        Genotype::new(
52            (0..self.num_chromosomes)
53                .map(|_| {
54                    CharChromosome::new(
55                        (0..self.num_genes)
56                            .map(|_| CharGene::new(Arc::clone(&self.char_set)))
57                            .collect::<Vec<CharGene>>(),
58                    )
59                })
60                .collect::<Vec<CharChromosome>>(),
61        )
62    }
63
64    fn decode(&self, genotype: &Genotype<CharChromosome>) -> Vec<Vec<char>> {
65        genotype
66            .iter()
67            .map(|chromosome| {
68                chromosome
69                    .iter()
70                    .map(|gene| *gene.allele())
71                    .collect::<Vec<char>>()
72            })
73            .collect::<Vec<Vec<char>>>()
74    }
75}
76
77impl Codec<CharChromosome, Vec<char>> for CharCodec<Vec<char>> {
78    fn encode(&self) -> Genotype<CharChromosome> {
79        Genotype::new(
80            (0..self.num_chromosomes)
81                .map(|_| {
82                    CharChromosome::new(
83                        (0..self.num_genes)
84                            .map(|_| CharGene::new(Arc::clone(&self.char_set)))
85                            .collect::<Vec<CharGene>>(),
86                    )
87                })
88                .collect::<Vec<CharChromosome>>(),
89        )
90    }
91
92    fn decode(&self, genotype: &Genotype<CharChromosome>) -> Vec<char> {
93        genotype
94            .iter()
95            .flat_map(|chromosome| {
96                chromosome
97                    .iter()
98                    .map(|gene| *gene.allele())
99                    .collect::<Vec<char>>()
100            })
101            .collect::<Vec<char>>()
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108    use crate::Codec;
109    use crate::genome::Gene;
110
111    #[test]
112    fn test_char_codec_matrix() {
113        let char_set = "abcde".chars().collect::<Vec<char>>();
114        let codec = CharCodec::matrix(3, 5).with_char_set(char_set.clone());
115        let genotype = codec.encode();
116        assert_eq!(genotype.len(), 3);
117        assert_eq!(genotype[0].len(), 5);
118        for gene in genotype[0].iter() {
119            assert!(gene.char_set().eq(&char_set));
120            assert!(char_set.contains(gene.allele()));
121        }
122    }
123
124    #[test]
125    fn test_char_codec_vector() {
126        let codec = CharCodec::vector(5);
127        let genotype = codec.encode();
128        assert_eq!(genotype.len(), 1);
129        assert_eq!(genotype[0].len(), 5);
130        for gene in genotype[0].iter() {
131            assert!(codec.char_set.contains(gene.allele()));
132        }
133    }
134}