use super::*;
use rand::prelude::*;
use rayon::prelude::*;
pub trait EvolutionModel: Sync {
type Individual: Individual;
type Rng: Rng + Send;
fn rng() -> Self::Rng;
fn crossover(
&self,
parent1: &Self::Individual,
parent2: &Self::Individual,
rng: &mut Self::Rng,
) -> Self::Individual;
fn mutate(&self, individual: &mut Self::Individual, rng: &mut Self::Rng);
fn improve(&self, _individual: &mut Self::Individual) {}
fn evaluate(&self, individual: &mut Self::Individual);
fn pre_generation(
&mut self,
_population: &Population<Self::Individual>,
_breeding_parameters: &mut ReproductionParameters<Self>,
) where
Self: Sized,
{
}
fn breed(
&self,
population: &Population<Self::Individual>,
parameters: &ReproductionParameters<Self>,
rng: &mut Self::Rng,
) -> Self::Individual
where
Self: Sized,
{
let (_, parent1) = parameters.parent_selector.select(population, rng);
let parent2 = if population.len() > 1 && rng.gen::<f64>() < parameters.crossover_rate {
parameters
.parent_selector
.select_distinct(population, rng, 3, parent1)
.map(|(_, parent)| parent)
} else {
None
};
let mut fittest_parent = parent1;
let mut offspring = if let Some(parent2) = parent2 {
if parent2.fitness() > parent1.fitness() {
fittest_parent = parent2;
}
self.crossover(parent1, parent2, rng)
} else {
parent1.clone()
};
if rng.gen::<f64>() < parameters.mutation_rate {
self.mutate(&mut offspring, rng);
}
self.improve(&mut offspring);
self.evaluate(&mut offspring);
if offspring.is_valid() && self.can_survive(&offspring, fittest_parent, population, rng) {
offspring
} else {
fittest_parent.clone()
}
}
#[inline]
fn can_survive(
&self,
offspring: &Self::Individual,
fittest_parent: &Self::Individual,
_population: &Population<Self::Individual>,
_rng: &mut Self::Rng,
) -> bool {
offspring.fitness() >= fittest_parent.fitness()
}
fn extend_population<T>(&self, individuals: &mut Vec<Self::Individual>, size: usize, args: &T)
where
T: Sync,
Self::Individual: RandomIndividual<T>,
{
if size == 0 {
return;
}
individuals.reserve(size);
individuals.par_extend(
rayon::iter::repeatn(args, size).map_init(Self::rng, |rng, args| {
Self::Individual::new_random(args, rng)
}),
);
}
fn extend_population_with(
&self,
individuals: &mut Vec<Self::Individual>,
size: usize,
model: Self::Individual,
) {
if size == 0 {
return;
}
individuals.reserve(size);
individuals.push(model.clone());
if size == 1 {
return;
}
individuals.par_extend(rayon::iter::repeatn(model, size - 1).map_init(
Self::rng,
|rng, mut new_individual| {
self.mutate(&mut new_individual, rng);
new_individual
},
));
}
}
pub struct ReproductionParameters<M: EvolutionModel> {
pub crossover_rate: f64,
pub mutation_rate: f64,
pub parent_selector: Box<dyn SelectionMechanism<M::Individual, M::Rng>>,
}
impl<M: EvolutionModel> Default for ReproductionParameters<M> {
fn default() -> Self {
Self {
crossover_rate: 0.8,
mutation_rate: 0.1,
parent_selector: Box::<RouletteWheelSelection>::default(),
}
}
}