radiate_engines/builder/
problem.rs

1use crate::GeneticEngineBuilder;
2use radiate_core::{
3    Chromosome, Codec, Genotype, Problem, Score,
4    fitness::{BatchFitnessFunction, FitnessFunction},
5};
6use std::sync::Arc;
7
8type FitnessFn<T> = dyn Fn(T) -> Score + Send + Sync;
9type BatchFitnessFn<T> = dyn Fn(Vec<T>) -> Vec<Score> + Send + Sync;
10type RawFitnessFn<C> = dyn Fn(&Genotype<C>) -> Score + Send + Sync;
11type RawBatchFitnessFn<C> = dyn Fn(Vec<&Genotype<C>>) -> Vec<Score> + Send + Sync;
12
13#[derive(Clone)]
14pub struct ProblemParams<C, T>
15where
16    C: Chromosome,
17    T: Clone,
18{
19    pub codec: Option<Arc<dyn Codec<C, T>>>,
20    pub problem: Option<Arc<dyn Problem<C, T>>>,
21    pub fitness_fn: Option<Arc<FitnessFn<T>>>,
22    pub batch_fitness_fn: Option<Arc<BatchFitnessFn<T>>>,
23    pub raw_fitness_fn: Option<Arc<RawFitnessFn<C>>>,
24    pub raw_batch_fitness_fn: Option<Arc<RawBatchFitnessFn<C>>>,
25}
26
27impl<C, T> GeneticEngineBuilder<C, T>
28where
29    C: Chromosome + PartialEq + Clone,
30    T: Clone + Send,
31{
32    /// Set the codec that will be used to encode and decode the genotype of the population.
33    pub fn codec<D: Codec<C, T> + 'static>(mut self, codec: D) -> Self {
34        self.params.problem_params.codec = Some(Arc::new(codec));
35        self
36    }
37
38    /// Set the problem of the genetic engine. This is useful if you want to provide a custom problem.
39    pub fn problem<P: Problem<C, T> + 'static>(mut self, problem: P) -> Self {
40        self.params.problem_params.problem = Some(Arc::new(problem));
41        self
42    }
43
44    /// Set the fitness function of the genetic engine. This is the function that will be
45    /// used to evaluate the fitness of each individual in the population. This function should
46    /// take a single argument of type T and return a [Score]. The [Score] is used to
47    /// evaluate or rank the fitness of the individual.
48    ///
49    /// This method is required and must be set before calling the `build` method.
50    pub fn fitness_fn<S: Into<Score>>(
51        mut self,
52        fitness_func: impl FitnessFunction<T, S> + 'static,
53    ) -> Self {
54        let other = move |x| fitness_func.evaluate(x).into();
55        self.params.problem_params.fitness_fn = Some(Arc::new(other));
56        self
57    }
58
59    /// Set the batch fitness function of the genetic engine. This function will be used to
60    /// evaluate the fitness of a batch of individuals in the population. This function should
61    /// take a slice of type `&[T]` and return a `Vec<Score>`. The Score is used to
62    /// evaluate or rank the fitness of the individuals.
63    ///
64    /// This method is optional and can be set after calling the `build` method.
65    pub fn batch_fitness_fn<S: Into<Score>>(
66        mut self,
67        batch_fitness_func: impl BatchFitnessFunction<T, S> + 'static,
68    ) -> Self {
69        let other = move |x: Vec<T>| {
70            batch_fitness_func
71                .evaluate(x)
72                .into_iter()
73                .map(|s| s.into())
74                .collect()
75        };
76        self.params.problem_params.batch_fitness_fn = Some(Arc::new(other));
77        self
78    }
79
80    pub fn raw_fitness_fn<S: Into<Score>>(
81        mut self,
82        raw_fitness_func: impl for<'a> FitnessFunction<&'a Genotype<C>, S> + 'static,
83    ) -> Self {
84        let other = move |x: &Genotype<C>| raw_fitness_func.evaluate(x).into();
85        self.params.problem_params.raw_fitness_fn = Some(Arc::new(other));
86        self
87    }
88
89    pub fn raw_batch_fitness_fn<S: Into<Score>>(
90        mut self,
91        raw_batch_fitness_func: impl for<'a> BatchFitnessFunction<&'a Genotype<C>, S> + 'static,
92    ) -> Self {
93        let other = move |x: Vec<&Genotype<C>>| {
94            raw_batch_fitness_func
95                .evaluate(x)
96                .into_iter()
97                .map(|s| s.into())
98                .collect()
99        };
100        self.params.problem_params.raw_batch_fitness_fn = Some(Arc::new(other));
101        self
102    }
103}