radiate_core/
problem.rs

1use super::{Chromosome, Codec, Genotype, Score};
2use std::sync::Arc;
3
4/// [Problem] represents the interface for the fitness function or evaluation and encoding/decoding
5/// of a genotype to a phenotype within the genetic algorithm framework.
6///
7/// To run the genetic algorithm the three things that must be supplied are the encoding & decoding of
8/// the [Genotype] and the fitness function. [Problem] wraps all three into a
9/// single trait that can be supplied to the engine builder.
10pub trait Problem<C: Chromosome, T>: Send + Sync {
11    fn encode(&self) -> Genotype<C>;
12    fn decode(&self, genotype: &Genotype<C>) -> T;
13    fn eval(&self, individual: &Genotype<C>) -> Score;
14}
15
16/// [EngineProblem] is a generic, base level concrete implementation of the [Problem] trait that is the
17/// default problem used by the engine if none other is specified during building. We take the
18/// [Codec] and the fitness function from the user and simply wrap them into this struct.
19pub struct EngineProblem<C, T>
20where
21    C: Chromosome,
22{
23    pub codec: Arc<dyn Codec<C, T>>,
24    pub fitness_fn: Arc<dyn Fn(T) -> Score + Send + Sync>,
25}
26
27impl<C: Chromosome, T> Problem<C, T> for EngineProblem<C, T> {
28    fn encode(&self) -> Genotype<C> {
29        self.codec.encode()
30    }
31
32    fn decode(&self, genotype: &Genotype<C>) -> T {
33        self.codec.decode(genotype)
34    }
35
36    fn eval(&self, individual: &Genotype<C>) -> Score {
37        let phenotype = self.decode(individual);
38        (self.fitness_fn)(phenotype)
39    }
40}
41
42unsafe impl<C: Chromosome, T> Send for EngineProblem<C, T> {}
43unsafe impl<C: Chromosome, T> Sync for EngineProblem<C, T> {}