Skip to main content

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 allele_mut(&mut self) -> &mut char {
68        &mut self.allele
69    }
70
71    fn new_instance(&self) -> CharGene {
72        let index = random_provider::range(0..self.char_set.len());
73        CharGene {
74            allele: self.char_set[index],
75            char_set: Arc::clone(&self.char_set),
76        }
77    }
78
79    fn with_allele(&self, allele: &char) -> CharGene {
80        CharGene {
81            allele: *allele,
82            char_set: Arc::clone(&self.char_set),
83        }
84    }
85}
86
87impl Valid for CharGene {
88    fn is_valid(&self) -> bool {
89        self.char_set.contains(&self.allele)
90    }
91}
92
93impl Default for CharGene {
94    fn default() -> Self {
95        let char_set: Arc<[char]> = ALPHABET.chars().collect::<Vec<char>>().into();
96        let allele = random_provider::range(0..char_set.len());
97        CharGene {
98            allele: char_set[allele],
99            char_set,
100        }
101    }
102}
103
104impl From<CharGene> for char {
105    fn from(gene: CharGene) -> char {
106        gene.allele
107    }
108}
109
110impl From<char> for CharGene {
111    fn from(allele: char) -> Self {
112        CharGene {
113            allele,
114            char_set: ALPHABET.chars().collect::<Vec<char>>().into(),
115        }
116    }
117}
118
119impl From<&str> for CharGene {
120    fn from(str: &str) -> Self {
121        let char_set: Arc<[char]> = str.chars().collect::<Vec<char>>().into();
122        let allele = random_provider::range(0..char_set.len());
123        CharGene {
124            allele: char_set[allele],
125            char_set,
126        }
127    }
128}
129
130impl From<String> for CharGene {
131    fn from(string: String) -> Self {
132        let char_set: Arc<[char]> = string.chars().collect::<Vec<char>>().into();
133        let allele = random_provider::range(0..char_set.len());
134        CharGene {
135            allele: char_set[allele],
136            char_set,
137        }
138    }
139}
140
141impl From<(char, Arc<[char]>)> for CharGene {
142    fn from((allele, char_set): (char, Arc<[char]>)) -> Self {
143        CharGene { allele, char_set }
144    }
145}
146
147impl std::fmt::Debug for CharGene {
148    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149        write!(f, "{}", self.allele)
150    }
151}
152
153/// Manual implementation of serialize and deserialize for the [CharGene]
154/// needed because of the [Arc] type in the char_set field.
155#[cfg(feature = "serde")]
156impl Serialize for CharGene {
157    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
158    where
159        S: serde::Serializer,
160    {
161        use serde::ser::SerializeStruct;
162        let mut state = serializer.serialize_struct("CharGene", 2)?;
163        state.serialize_field("allele", &self.allele)?;
164        state.serialize_field("char_set", &self.char_set.to_vec())?;
165        state.end()
166    }
167}
168
169#[cfg(feature = "serde")]
170impl<'de> Deserialize<'de> for CharGene {
171    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
172    where
173        D: serde::Deserializer<'de>,
174    {
175        #[derive(Deserialize)]
176        struct CharGeneData {
177            allele: char,
178            char_set: Vec<char>,
179        }
180
181        let data = CharGeneData::deserialize(deserializer)?;
182        Ok(CharGene {
183            allele: data.allele,
184            char_set: data.char_set.into(),
185        })
186    }
187}
188
189/// A [`Chromosome`] that contains [`CharGene`].
190#[derive(Clone, PartialEq, Default, Debug)]
191#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
192pub struct CharChromosome {
193    genes: Vec<CharGene>,
194}
195
196impl CharChromosome {
197    pub fn new(genes: Vec<CharGene>) -> Self {
198        CharChromosome { genes }
199    }
200}
201
202impl Chromosome for CharChromosome {
203    type Gene = CharGene;
204
205    fn as_slice(&self) -> &[Self::Gene] {
206        &self.genes
207    }
208
209    fn as_mut_slice(&mut self) -> &mut [Self::Gene] {
210        &mut self.genes
211    }
212}
213
214impl Valid for CharChromosome {
215    fn is_valid(&self) -> bool {
216        self.genes.iter().all(|gene| gene.is_valid())
217    }
218}
219
220impl From<CharGene> for CharChromosome {
221    fn from(gene: CharGene) -> Self {
222        CharChromosome { genes: vec![gene] }
223    }
224}
225
226impl From<Vec<CharGene>> for CharChromosome {
227    fn from(genes: Vec<CharGene>) -> Self {
228        CharChromosome { genes }
229    }
230}
231
232impl From<String> for CharChromosome {
233    fn from(alleles: String) -> Self {
234        let char_set: Arc<[char]> = alleles.chars().collect::<Vec<char>>().into();
235        let genes = char_set
236            .iter()
237            .map(|&allele| CharGene::from((allele, Arc::clone(&char_set))))
238            .collect();
239        CharChromosome { genes }
240    }
241}
242
243impl From<&str> for CharChromosome {
244    fn from(alleles: &str) -> Self {
245        let char_set: Arc<[char]> = alleles.chars().collect::<Vec<char>>().into();
246        let genes = char_set
247            .iter()
248            .map(|&allele| CharGene::from((allele, Arc::clone(&char_set))))
249            .collect();
250        CharChromosome { genes }
251    }
252}
253
254impl<T: Into<String>> From<(usize, Option<T>)> for CharChromosome {
255    fn from((length, alleles): (usize, Option<T>)) -> Self {
256        let char_set: Arc<[char]> = alleles
257            .map(|chars| chars.into().chars().collect::<Vec<char>>())
258            .unwrap_or_else(|| ALPHABET.chars().collect::<Vec<char>>())
259            .into();
260        let genes = (0..length)
261            .map(|_| CharGene::new(Arc::clone(&char_set)))
262            .collect();
263        CharChromosome { genes }
264    }
265}
266
267impl FromIterator<CharGene> for CharChromosome {
268    fn from_iter<I: IntoIterator<Item = CharGene>>(iter: I) -> Self {
269        CharChromosome {
270            genes: iter.into_iter().collect(),
271        }
272    }
273}
274
275impl IntoIterator for CharChromosome {
276    type Item = CharGene;
277    type IntoIter = std::vec::IntoIter<CharGene>;
278
279    fn into_iter(self) -> Self::IntoIter {
280        self.genes.into_iter()
281    }
282}
283
284#[cfg(test)]
285mod tests {
286    use super::*;
287
288    #[test]
289    fn test_new() {
290        let gene = CharGene::default();
291        assert!(ALPHABET.contains(gene.allele));
292    }
293
294    #[test]
295    fn test_into() {
296        let gene = CharGene::default();
297        let copy = gene.clone();
298        let allele: char = gene.into();
299        assert_eq!(allele, copy.allele);
300    }
301
302    #[test]
303    fn test_from() {
304        let allele = 'a';
305        let gene = CharGene::from(allele);
306        assert_eq!(gene.allele, allele);
307    }
308
309    #[test]
310    fn test_from_allele() {
311        let gene_one: CharGene = 'a'.into();
312        let gene_two: CharGene = 'b'.into();
313        let new_gene = gene_one.with_allele(&gene_two.allele);
314
315        assert_eq!(gene_two.allele, new_gene.allele);
316    }
317
318    #[test]
319    fn test_is_valid() {
320        let gene_one = CharGene::default();
321        let gene_two = CharGene::from("hello");
322        let gene_three = gene_two.with_allele(&'a');
323
324        assert!(gene_one.is_valid());
325        assert!(gene_two.is_valid());
326        assert!(!gene_three.is_valid());
327    }
328
329    #[test]
330    fn test_char_from_str() {
331        let gene = CharGene::from("hello");
332        assert_eq!(
333            "hello".chars().collect::<Vec<char>>(),
334            gene.char_set.as_ref()
335        );
336    }
337
338    #[test]
339    fn test_char_chromosome_from_str() {
340        let gene = CharChromosome::from("hello");
341        assert_eq!(
342            "hello".chars().collect::<Vec<char>>(),
343            gene.genes.iter().map(|g| g.allele).collect::<Vec<char>>()
344        );
345    }
346
347    #[test]
348    fn test_char_chromosome_from_string() {
349        let chromosome = CharChromosome::from("hello");
350        let hello: String = chromosome.genes.iter().map(|g| g.allele).collect();
351
352        assert_eq!(hello, "hello");
353    }
354}