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}