use crate::{
algorithm::EvaluatedPopulation,
genetic::{Fitness, Genotype, Offspring},
operator::{GeneticOperator, MultiObjective, ReinsertionOp, SingleObjective},
random::{random_index, Rng},
};
#[allow(missing_copy_implementations)]
#[derive(Clone, Debug, PartialEq)]
pub struct UniformReinserter {
replace_ratio: f64,
}
impl UniformReinserter {
pub fn new(replace_ratio: f64) -> Self {
UniformReinserter { replace_ratio }
}
pub fn replace_ratio(&self) -> f64 {
self.replace_ratio
}
pub fn set_replace_ratio(&mut self, value: f64) {
self.replace_ratio = value;
}
}
impl GeneticOperator for UniformReinserter {
fn name() -> String {
"Uniform-Reinserter".to_string()
}
}
impl SingleObjective for UniformReinserter {}
impl MultiObjective for UniformReinserter {}
impl<G, F> ReinsertionOp<G, F> for UniformReinserter
where
G: Genotype,
F: Fitness,
{
fn combine<R>(
&self,
offspring: &mut Offspring<G>,
evaluated: &EvaluatedPopulation<G, F>,
rng: &mut R,
) -> Vec<G>
where
R: Rng + Sized,
{
let old_individuals = evaluated.individuals();
let population_size = old_individuals.len();
let mut new_population = Vec::with_capacity(population_size);
let num_offspring = (population_size as f64 * self.replace_ratio + 0.5).floor() as usize;
if num_offspring < offspring.len() {
while num_offspring > new_population.len() {
let index = random_index(rng, offspring.len());
new_population.push(offspring.remove(index));
}
} else {
let mut i = 0;
while i < offspring.len() {
new_population.push(offspring.remove(i));
i += 1;
}
}
let num_old_population = population_size - new_population.len();
for _ in 0..num_old_population {
let index = random_index(rng, old_individuals.len());
new_population.push(old_individuals[index].clone());
}
new_population
}
}