Skip to main content

radiate_core/codecs/
function.rs

1use crate::{Chromosome, Codec, Genotype};
2use std::sync::Arc;
3
4type DecoderFn<C, T> = Arc<dyn Fn(&Genotype<C>) -> T>;
5
6/// A `Codec` that uses functions to encode and decode a `Genotype` to and from a type `T`.
7/// Most of the other codecs in this module are more specialized and are used to create `Genotypes` of specific types of `Chromosomes`.
8/// This one, however, is more general and can be used to create `Genotypes` of any type of `Chromosome`.
9///
10/// # Example
11/// ``` rust
12/// use radiate_core::*;
13///
14/// const N_QUEENS: usize = 8;
15///
16/// fn main() {
17///     // this is a simple example of the NQueens problem.
18///     // The resulting codec type will be FnCodec<IntChromosome<i8>, Vec<i8>>.
19///     let codec = FnCodec::new()
20///         .with_encoder(|| {
21///             Genotype::from(IntChromosome::new((0..N_QUEENS)
22///                     .map(|_| IntGene::from(0..N_QUEENS as i8))
23///                     .collect(),
24///             ))
25///         })
26///         .with_decoder(|genotype| {
27///             genotype[0]
28///                 .as_slice()
29///                 .iter()
30///                 .map(|g| *g.allele())
31///                 .collect::<Vec<i8>>()
32///         });
33///
34///     // encode and decode
35///     let genotype: Genotype<IntChromosome<i8>> = codec.encode();
36///     let decoded: Vec<i8> = codec.decode(&genotype);
37/// }
38/// ```
39/// # Type Parameters
40/// - `C`: The type of chromosome used in the genotype, which must implement the `Chromosome` trait.
41/// - `T`: The type that the genotype will be decoded to.
42#[derive(Default, Clone)]
43pub struct FnCodec<C: Chromosome, T> {
44    encoder: Option<Arc<dyn Fn() -> Genotype<C>>>,
45    decoder: Option<DecoderFn<C, T>>,
46}
47
48impl<C: Chromosome, T> FnCodec<C, T> {
49    pub fn new() -> Self {
50        FnCodec {
51            encoder: None,
52            decoder: None,
53        }
54    }
55
56    pub fn with_encoder<F>(mut self, encoder: F) -> Self
57    where
58        F: Fn() -> Genotype<C> + 'static,
59    {
60        self.encoder = Some(Arc::new(encoder));
61        self
62    }
63
64    pub fn with_decoder<F>(mut self, decoder: F) -> Self
65    where
66        F: Fn(&Genotype<C>) -> T + 'static,
67    {
68        self.decoder = Some(Arc::new(decoder));
69        self
70    }
71}
72
73impl<C: Chromosome, T> Codec<C, T> for FnCodec<C, T> {
74    fn encode(&self) -> Genotype<C> {
75        match &self.encoder {
76            Some(encoder) => encoder(),
77            None => panic!("Encoder function is not set"),
78        }
79    }
80
81    fn decode(&self, genotype: &Genotype<C>) -> T {
82        match &self.decoder {
83            Some(decoder) => decoder(genotype),
84            None => panic!("Decoder function is not set"),
85        }
86    }
87}