use crate::GeneticEngineBuilder;
use radiate_core::{
Chromosome, Codec, Genotype, Problem, Score,
fitness::{BatchFitnessFunction, FitnessFunction},
};
use std::sync::Arc;
type FitnessFn<T> = dyn Fn(T) -> Score + Send + Sync;
type BatchFitnessFn<T> = dyn Fn(Vec<T>) -> Vec<Score> + Send + Sync;
type RawFitnessFn<C> = dyn Fn(&Genotype<C>) -> Score + Send + Sync;
type RawBatchFitnessFn<C> = dyn Fn(Vec<&Genotype<C>>) -> Vec<Score> + Send + Sync;
#[derive(Clone)]
pub struct ProblemParams<C, T>
where
C: Chromosome,
T: Clone,
{
pub codec: Option<Arc<dyn Codec<C, T>>>,
pub problem: Option<Arc<dyn Problem<C, T>>>,
pub fitness_fn: Option<Arc<FitnessFn<T>>>,
pub batch_fitness_fn: Option<Arc<BatchFitnessFn<T>>>,
pub raw_fitness_fn: Option<Arc<RawFitnessFn<C>>>,
pub raw_batch_fitness_fn: Option<Arc<RawBatchFitnessFn<C>>>,
}
impl<C, T> GeneticEngineBuilder<C, T>
where
C: Chromosome + PartialEq + Clone,
T: Clone + Send,
{
pub fn codec<D: Codec<C, T> + 'static>(mut self, codec: D) -> Self {
self.params.problem_params.codec = Some(Arc::new(codec));
self
}
pub fn problem<P: Problem<C, T> + 'static>(mut self, problem: P) -> Self {
self.params.problem_params.problem = Some(Arc::new(problem));
self
}
pub fn fitness_fn<S: Into<Score>>(
mut self,
fitness_func: impl FitnessFunction<T, S> + 'static,
) -> Self {
let other = move |x| fitness_func.evaluate(x).into();
self.params.problem_params.fitness_fn = Some(Arc::new(other));
self
}
pub fn batch_fitness_fn<S: Into<Score>>(
mut self,
batch_fitness_func: impl BatchFitnessFunction<T, S> + 'static,
) -> Self {
let other = move |x: Vec<T>| {
batch_fitness_func
.evaluate(x)
.into_iter()
.map(|s| s.into())
.collect()
};
self.params.problem_params.batch_fitness_fn = Some(Arc::new(other));
self
}
pub fn raw_fitness_fn<S: Into<Score>>(
mut self,
raw_fitness_func: impl for<'a> FitnessFunction<&'a Genotype<C>, S> + 'static,
) -> Self {
let other = move |x: &Genotype<C>| raw_fitness_func.evaluate(x).into();
self.params.problem_params.raw_fitness_fn = Some(Arc::new(other));
self
}
pub fn raw_batch_fitness_fn<S: Into<Score>>(
mut self,
raw_batch_fitness_func: impl for<'a> BatchFitnessFunction<&'a Genotype<C>, S> + 'static,
) -> Self {
let other = move |x: Vec<&Genotype<C>>| {
raw_batch_fitness_func
.evaluate(x)
.into_iter()
.map(|s| s.into())
.collect()
};
self.params.problem_params.raw_batch_fitness_fn = Some(Arc::new(other));
self
}
}