use super::*;
use object_pool::Pool;
use std::cell::RefCell;
pub struct Evolution<A, M>
where
A: EvolutionAlgorithm<M>,
M: EvolutionModel,
{
algorithm: RefCell<A>,
_marker: std::marker::PhantomData<M>,
}
impl<A, M> Evolution<A, M>
where
A: EvolutionAlgorithm<M>,
M: EvolutionModel,
{
pub fn run<T, F>(&self, args: &T, parameters: &A::Parameters, progress: F) -> M::Individual
where
T: Sync,
M::Individual: RandomIndividual<T>,
F: FnMut(&Population<M::Individual>) -> bool,
{
let mut individuals = Vec::with_capacity(parameters.max_population_size());
self.algorithm.borrow().model().extend_population(
&mut individuals,
parameters.initial_population_size(),
args,
);
self.evolve_population(individuals, parameters, progress)
.take_fittest()
}
pub fn evolve_individual<F>(
&self,
individual: M::Individual,
parameters: &A::Parameters,
progress: F,
) -> M::Individual
where
F: FnMut(&Population<M::Individual>) -> bool,
{
let mut individuals = Vec::with_capacity(parameters.max_population_size());
self.algorithm.borrow().model().extend_population_with(
&mut individuals,
parameters.initial_population_size(),
individual,
);
self.evolve_population(individuals, parameters, progress)
.take_fittest()
}
pub fn evolve_population<F>(
&self,
initial_population: Vec<M::Individual>,
parameters: &A::Parameters,
mut progress: F,
) -> Population<M::Individual>
where
F: FnMut(&Population<M::Individual>) -> bool,
{
self.algorithm.borrow_mut().configure(parameters);
let mut population = self
.algorithm
.borrow()
.initialize_population(initial_population);
let mut new_population = Vec::with_capacity(parameters.max_population_size());
let pool = Pool::new(rayon::current_num_threads(), M::rng);
while progress(&population) {
new_population.clear();
self.algorithm
.borrow_mut()
.prepare_for_next_population(&population);
self.algorithm
.borrow()
.select_elites(&population, &mut new_population);
self.algorithm.borrow().generate_new_population(
&population,
&mut new_population,
&pool,
);
self.algorithm
.borrow()
.replace_population(&mut population, &mut new_population);
}
population
}
}
impl<A, M> Default for Evolution<A, M>
where
A: EvolutionAlgorithm<M> + Default,
M: EvolutionModel + Default,
{
fn default() -> Self {
Self {
algorithm: Default::default(),
_marker: Default::default(),
}
}
}
impl<A, M> From<A> for Evolution<A, M>
where
A: EvolutionAlgorithm<M> + From<M>,
M: EvolutionModel,
{
fn from(algorithm: A) -> Self {
Self {
algorithm: RefCell::new(algorithm),
_marker: Default::default(),
}
}
}