radiate_core/genome/chromosomes/
char.rs

1use super::{
2    Chromosome,
3    gene::{Gene, Valid},
4};
5use crate::random_provider;
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8use std::{char, sync::Arc};
9
10/// This is the default character set used for the `CharGene` and `CharChromosome`.
11/// It includes digits, lowercase and uppercase letters, and a selection of special characters.
12/// The character set is designed to be broad enough for most applications while still being
13/// manageable in size to ensure good performance in genetic algorithms.
14///
15/// If no character set is provided, this default will be used.
16pub(crate) const ALPHABET: &str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"$%&/()=?`{[]}\\+~*#';.:,-_<>|@^' ";
17
18/// A gene that represents a single character. The `allele` is a `char`
19/// that is randomly selected from the [`ALPHABET`] constant.
20///
21/// # Example
22/// ``` rust
23/// use radiate_core::*;
24///
25/// // Create a new CharGene with a random allele from the ALPHABET constant.
26/// let gene = CharGene::default();
27///
28/// // Get the allele of the CharGene.
29/// let allele = gene.allele();
30///
31/// // Create a new CharGene from the allele.
32/// let gene = gene.with_allele(allele);
33/// ```
34#[derive(Clone, PartialEq)]
35pub struct CharGene {
36    allele: char,
37    char_set: Arc<[char]>,
38}
39
40impl CharGene {
41    /// Given a slice of possible alleles, create a new [CharGene] by
42    /// randomly picking a char from the char_set
43    pub fn new(char_set: Arc<[char]>) -> Self {
44        let index = random_provider::range(0..char_set.len());
45        CharGene {
46            allele: char_set[index],
47            char_set,
48        }
49    }
50
51    /// Get this [CharGene]'s set of possible alleles
52    pub fn char_set(&self) -> &[char] {
53        &self.char_set
54    }
55}
56
57/// Implement the [`Gene`] trait for the [`CharGene`]. This allows the [`CharGene`] to be used in
58/// a [`Chromosome`] - specifically the [`CharChromosome`], thus allowing the [`CharGene`] to
59/// be used in the `GeneticEngine`.
60impl Gene for CharGene {
61    type Allele = char;
62
63    fn allele(&self) -> &char {
64        &self.allele
65    }
66
67    fn new_instance(&self) -> CharGene {
68        let index = random_provider::range(0..self.char_set.len());
69        CharGene {
70            allele: self.char_set[index],
71            char_set: Arc::clone(&self.char_set),
72        }
73    }
74
75    fn with_allele(&self, allele: &char) -> CharGene {
76        CharGene {
77            allele: *allele,
78            char_set: Arc::clone(&self.char_set),
79        }
80    }
81}
82
83impl Valid for CharGene {
84    fn is_valid(&self) -> bool {
85        self.char_set.contains(&self.allele)
86    }
87}
88
89impl Default for CharGene {
90    fn default() -> Self {
91        let char_set: Arc<[char]> = ALPHABET.chars().collect::<Vec<char>>().into();
92        let allele = random_provider::range(0..char_set.len());
93        CharGene {
94            allele: char_set[allele],
95            char_set,
96        }
97    }
98}
99
100impl From<CharGene> for char {
101    fn from(gene: CharGene) -> char {
102        gene.allele
103    }
104}
105
106impl From<char> for CharGene {
107    fn from(allele: char) -> Self {
108        CharGene {
109            allele,
110            char_set: ALPHABET.chars().collect::<Vec<char>>().into(),
111        }
112    }
113}
114
115impl From<&str> for CharGene {
116    fn from(str: &str) -> Self {
117        let char_set: Arc<[char]> = str.chars().collect::<Vec<char>>().into();
118        let allele = random_provider::range(0..char_set.len());
119        CharGene {
120            allele: char_set[allele],
121            char_set,
122        }
123    }
124}
125
126impl From<String> for CharGene {
127    fn from(string: String) -> Self {
128        let char_set: Arc<[char]> = string.chars().collect::<Vec<char>>().into();
129        let allele = random_provider::range(0..char_set.len());
130        CharGene {
131            allele: char_set[allele],
132            char_set,
133        }
134    }
135}
136
137impl From<(char, Arc<[char]>)> for CharGene {
138    fn from((allele, char_set): (char, Arc<[char]>)) -> Self {
139        CharGene { allele, char_set }
140    }
141}
142
143impl std::fmt::Debug for CharGene {
144    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145        write!(f, "{}", self.allele)
146    }
147}
148
149/// Manual implementation of seralize and deserialzie for the [CharGene]
150/// needed because of the [Arc] type in the char_set field.
151#[cfg(feature = "serde")]
152impl Serialize for CharGene {
153    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
154    where
155        S: serde::Serializer,
156    {
157        use serde::ser::SerializeStruct;
158        let mut state = serializer.serialize_struct("CharGene", 2)?;
159        state.serialize_field("allele", &self.allele)?;
160        state.serialize_field("char_set", &self.char_set.to_vec())?;
161        state.end()
162    }
163}
164
165#[cfg(feature = "serde")]
166impl<'de> Deserialize<'de> for CharGene {
167    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
168    where
169        D: serde::Deserializer<'de>,
170    {
171        #[derive(Deserialize)]
172        struct CharGeneData {
173            allele: char,
174            char_set: Vec<char>,
175        }
176
177        let data = CharGeneData::deserialize(deserializer)?;
178        Ok(CharGene {
179            allele: data.allele,
180            char_set: data.char_set.into(),
181        })
182    }
183}
184
185/// A [`Chromosome`] that contains [`CharGene`].
186#[derive(Clone, PartialEq, Default, Debug)]
187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
188pub struct CharChromosome {
189    genes: Vec<CharGene>,
190}
191
192impl CharChromosome {
193    pub fn new(genes: Vec<CharGene>) -> Self {
194        CharChromosome { genes }
195    }
196}
197
198impl Chromosome for CharChromosome {
199    type Gene = CharGene;
200
201    fn genes(&self) -> &[Self::Gene] {
202        &self.genes
203    }
204
205    fn genes_mut(&mut self) -> &mut [Self::Gene] {
206        &mut self.genes
207    }
208}
209
210impl Valid for CharChromosome {
211    fn is_valid(&self) -> bool {
212        self.genes.iter().all(|gene| gene.is_valid())
213    }
214}
215
216impl From<Vec<CharGene>> for CharChromosome {
217    fn from(genes: Vec<CharGene>) -> Self {
218        CharChromosome { genes }
219    }
220}
221
222impl From<String> for CharChromosome {
223    fn from(alleles: String) -> Self {
224        let char_set: Arc<[char]> = alleles.chars().collect::<Vec<char>>().into();
225        let genes = char_set
226            .iter()
227            .map(|&allele| CharGene::from((allele, Arc::clone(&char_set))))
228            .collect();
229        CharChromosome { genes }
230    }
231}
232
233impl From<&str> for CharChromosome {
234    fn from(alleles: &str) -> Self {
235        let char_set: Arc<[char]> = alleles.chars().collect::<Vec<char>>().into();
236        let genes = char_set
237            .iter()
238            .map(|&allele| CharGene::from((allele, Arc::clone(&char_set))))
239            .collect();
240        CharChromosome { genes }
241    }
242}
243
244impl<T: Into<String>> From<(usize, Option<T>)> for CharChromosome {
245    fn from((length, alleles): (usize, Option<T>)) -> Self {
246        let char_set: Arc<[char]> = alleles
247            .map(|chars| chars.into().chars().collect::<Vec<char>>())
248            .unwrap_or_else(|| ALPHABET.chars().collect::<Vec<char>>())
249            .into();
250        let genes = (0..length)
251            .map(|_| CharGene::new(Arc::clone(&char_set)))
252            .collect();
253        CharChromosome { genes }
254    }
255}
256
257#[cfg(test)]
258mod tests {
259    use super::*;
260
261    #[test]
262    fn test_new() {
263        let gene = CharGene::default();
264        assert!(ALPHABET.contains(gene.allele));
265    }
266
267    #[test]
268    fn test_into() {
269        let gene = CharGene::default();
270        let copy = gene.clone();
271        let allele: char = gene.into();
272        assert_eq!(allele, copy.allele);
273    }
274
275    #[test]
276    fn test_from() {
277        let allele = 'a';
278        let gene = CharGene::from(allele);
279        assert_eq!(gene.allele, allele);
280    }
281
282    #[test]
283    fn test_from_allele() {
284        let gene_one: CharGene = 'a'.into();
285        let gene_two: CharGene = 'b'.into();
286        let new_gene = gene_one.with_allele(&gene_two.allele);
287
288        assert_eq!(gene_two.allele, new_gene.allele);
289    }
290
291    #[test]
292    fn test_is_valid() {
293        let gene_one = CharGene::default();
294        let gene_two = CharGene::from("hello");
295        let gene_three = gene_two.with_allele(&'a');
296
297        assert!(gene_one.is_valid());
298        assert!(gene_two.is_valid());
299        assert!(!gene_three.is_valid());
300    }
301
302    #[test]
303    fn test_char_from_str() {
304        let gene = CharGene::from("hello");
305        assert_eq!(
306            "hello".chars().collect::<Vec<char>>(),
307            gene.char_set.as_ref()
308        );
309    }
310
311    #[test]
312    fn test_char_chromosome_from_str() {
313        let gene = CharChromosome::from("hello");
314        assert_eq!(
315            "hello".chars().collect::<Vec<char>>(),
316            gene.genes.iter().map(|g| g.allele).collect::<Vec<char>>()
317        );
318    }
319
320    #[test]
321    fn test_char_chromosome_from_string() {
322        let chromosome = CharChromosome::from("hello");
323        let hello: String = chromosome.genes.iter().map(|g| g.allele).collect();
324
325        assert_eq!(hello, "hello");
326    }
327}