use crate::ga::builder::FitnessFn;
use crate::ga::individual::IndividualTrait;
use crate::ga::operators::fitness::{Fitness, FnBasedFitness};
use crate::ga::operators::replacement::ReplacementOperator;
use crate::ga::{
operators::{crossover::CrossoverOperator, mutation::MutationOperator, selection::SelectionOperator},
population::PopulationGenerator,
GeneticSolver, Probe,
};
use super::{DefaultParams, GAConfigOpt};
pub struct GenericBuilder<IndividualT, MutOpT, CrossOpT, SelOpT, ReplOpT, PopGenT, FitnessT, ProbeT>
where
IndividualT: IndividualTrait,
MutOpT: MutationOperator<IndividualT>,
CrossOpT: CrossoverOperator<IndividualT>,
SelOpT: SelectionOperator<IndividualT>,
ReplOpT: ReplacementOperator<IndividualT>,
PopGenT: PopulationGenerator<IndividualT>,
FitnessT: Fitness<IndividualT>,
ProbeT: Probe<IndividualT>,
{
config: GAConfigOpt<IndividualT, MutOpT, CrossOpT, SelOpT, ReplOpT, PopGenT, FitnessT, ProbeT>,
}
impl<IndividualT, MutOpT, CrossOpT, SelOpT, ReplOpT, PopGenT, ProbeT>
GenericBuilder<
IndividualT,
MutOpT,
CrossOpT,
SelOpT,
ReplOpT,
PopGenT,
FnBasedFitness<IndividualT>,
ProbeT,
>
where
IndividualT: IndividualTrait,
MutOpT: MutationOperator<IndividualT>,
CrossOpT: CrossoverOperator<IndividualT>,
SelOpT: SelectionOperator<IndividualT>,
ReplOpT: ReplacementOperator<IndividualT>,
PopGenT: PopulationGenerator<IndividualT>,
ProbeT: Probe<IndividualT>,
{
pub fn set_fitness_fn(
self,
fitness_fn: FitnessFn<IndividualT::ChromosomeT, IndividualT::FitnessValueT>,
) -> Self {
self.set_fitness(FnBasedFitness::new(fitness_fn))
}
}
impl<IndividualT, MutOpT, CrossOpT, SelOpT, ReplOpT, PopGenT, FitnessT, ProbeT>
GenericBuilder<IndividualT, MutOpT, CrossOpT, SelOpT, ReplOpT, PopGenT, FitnessT, ProbeT>
where
IndividualT: IndividualTrait,
MutOpT: MutationOperator<IndividualT>,
CrossOpT: CrossoverOperator<IndividualT>,
SelOpT: SelectionOperator<IndividualT>,
PopGenT: PopulationGenerator<IndividualT>,
ReplOpT: ReplacementOperator<IndividualT>,
FitnessT: Fitness<IndividualT>,
ProbeT: Probe<IndividualT>,
{
pub fn new() -> Self {
GenericBuilder {
config: GAConfigOpt::new(),
}
}
pub fn set_selection_rate(mut self, selection_rate: f64) -> Self {
assert!((0f64..=1f64).contains(&selection_rate));
self.config.params.selection_rate = Some(selection_rate);
self
}
pub fn set_mutation_rate(mut self, mutation_rate: f64) -> Self {
assert!((0.0..=1.0).contains(&mutation_rate));
self.config.params.mutation_rate = Some(mutation_rate);
self
}
pub fn set_max_duration(mut self, max_duration: std::time::Duration) -> Self {
self.config.params.max_duration = Some(max_duration);
self
}
pub fn set_max_generation_count(mut self, max_gen_count: usize) -> Self {
assert!(max_gen_count >= 1);
self.config.params.generation_limit = Some(max_gen_count);
self
}
pub fn set_population_size(mut self, size: usize) -> Self {
assert!(size > 0);
self.config.params.population_size = Some(size);
self
}
pub fn set_fitness(mut self, fitness: FitnessT) -> Self {
self.config.fitness_fn = Some(fitness);
self
}
pub fn set_mutation_operator(mut self, mutation_op: MutOpT) -> Self {
self.config.mutation_operator = Some(mutation_op);
self
}
pub fn set_crossover_operator(mut self, crossover_op: CrossOpT) -> Self {
self.config.crossover_operator = Some(crossover_op);
self
}
pub fn set_selection_operator(mut self, selection_op: SelOpT) -> Self {
self.config.selection_operator = Some(selection_op);
self
}
pub fn set_replacement_operator(mut self, replacement_op: ReplOpT) -> Self {
self.config.replacement_operator = Some(replacement_op);
self
}
pub fn set_population_generator(mut self, generator: PopGenT) -> Self {
self.config.population_factory = Some(generator);
self
}
pub fn set_probe(mut self, probe: ProbeT) -> Self {
self.config.probe = Some(probe);
self
}
pub fn build(
mut self,
) -> GeneticSolver<IndividualT, MutOpT, CrossOpT, SelOpT, ReplOpT, PopGenT, FitnessT, ProbeT> {
self.config.params.fill_from(&Self::DEFAULT_PARAMS);
let config = match self.config.try_into() {
Ok(config) => config,
Err(err) => panic!("Builder panicked with error: {err}"),
};
GeneticSolver::new(config)
}
}
impl<IndividualT, MutOpT, CrossOpT, SelOpT, ReplOpT, PopGenT, FitnessT, ProbeT> DefaultParams
for GenericBuilder<IndividualT, MutOpT, CrossOpT, SelOpT, ReplOpT, PopGenT, FitnessT, ProbeT>
where
IndividualT: IndividualTrait,
MutOpT: MutationOperator<IndividualT>,
CrossOpT: CrossoverOperator<IndividualT>,
SelOpT: SelectionOperator<IndividualT>,
PopGenT: PopulationGenerator<IndividualT>,
ReplOpT: ReplacementOperator<IndividualT>,
FitnessT: Fitness<IndividualT>,
ProbeT: Probe<IndividualT>,
{
}