use crate::core::{
solver::IterHook,
Problem, StopCriterion, {Evaluation, Solver},
};
use super::{
population::{Member, Population},
Decoder, RandomKey,
};
use std::{num::NonZeroUsize, usize};
use rand::{prelude::SliceRandom, Rng};
pub struct Brkga<'a, D: Decoder, R: Rng> {
decoder: &'a D,
rng: R,
current: BrkgaPopulation<D>,
next: BrkgaPopulation<D>,
generations: usize,
params: Params,
}
pub type BrkgaPopulation<D> = Population<<D as Decoder>::P, RandomKey>;
pub type BrkgaMember<D> = Member<RandomKey, <<D as Decoder>::P as Problem>::Value>;
impl<'a, R: Rng, D: Decoder> Brkga<'a, D, R> {
pub fn new(decoder: &'a D, mut rng: R, params: Params) -> Self {
let random_member_builder = |_| {
let keys = {
let mut k = vec![0.0; params.member_size.get()].into_boxed_slice();
rng.fill(k.as_mut());
k
};
let value = decoder.decode_value(&keys);
Member { keys, value }
};
let current = Population::new(params.population_size.get(), random_member_builder);
let next = current.clone();
Self {
current,
decoder,
params,
next,
generations: 0,
rng,
}
}
pub fn evolve(&mut self) {
self.transfer_elites();
self.crossover();
std::mem::swap(&mut self.current, &mut self.next);
self.mutate_current();
self.recompute_current();
self.generations += 1;
}
fn transfer_elites(&mut self) {
let elites = Self::elites(&self.current, &self.params);
for (elite, target) in elites.iter().zip(self.next.members.iter_mut()) {
target.keys.copy_from_slice(&elite.keys);
target.value = elite.value;
}
}
fn crossover(&mut self) {
for member in Self::regulars(&mut self.next, &self.params) {
let elite_parent = Self::elites(&self.current, &self.params)
.choose(&mut self.rng)
.unwrap();
let non_elite_parent = Self::not_elites(&self.current, &self.params)
.choose(&mut self.rng)
.unwrap();
for gene in 0..self.params.member_size.get() {
let source_parent = if self.rng.gen::<f64>() < self.params.crossover_bias {
elite_parent
} else {
non_elite_parent
};
member[gene] = source_parent[gene];
}
}
}
fn mutate_current(&mut self) {
for mutant in Self::mutants(&mut self.current, &self.params) {
self.rng.fill(mutant.keys.as_mut());
}
}
fn recompute_current(&mut self) {
for member in self.current.members.iter_mut() {
member.value = self.decoder.decode_value(&member.keys);
}
self.current.sort();
}
pub fn current_generation(&self) -> usize {
self.generations
}
pub fn current_population(&self) -> &BrkgaPopulation<D> {
&self.current
}
pub fn best(&self) -> &BrkgaMember<D> {
&self.current[0]
}
fn regulars<'b>(
population: &'b mut BrkgaPopulation<D>,
p: &Params,
) -> &'b mut [BrkgaMember<D>] {
let regulars = { p.elites..(p.population_size.get() - p.mutants) };
&mut population[regulars]
}
fn mutants<'b>(population: &'b mut BrkgaPopulation<D>, p: &Params) -> &'b mut [BrkgaMember<D>] {
let mutants = (p.population_size.get() - p.mutants)..p.population_size.get();
&mut population[mutants]
}
fn elites<'b>(population: &'b BrkgaPopulation<D>, p: &Params) -> &'b [BrkgaMember<D>] {
&population[..p.elites]
}
fn not_elites<'b>(population: &'b BrkgaPopulation<D>, p: &Params) -> &'b [BrkgaMember<D>] {
&population[p.elites..]
}
}
impl<'a, D, R, SC, H> Solver<SC, H> for Brkga<'a, D, R>
where
D: Decoder,
R: Rng,
SC: StopCriterion<D::P>,
H: BrkgaHook<D>,
{
type P = D::P;
fn iterate(&mut self, _: &mut SC, hook: &mut H) -> Option<Evaluation<Self::P>> {
self.evolve();
hook.evolved(&self.current);
let solution = self.decoder.decode(&self.best().keys);
let evaluation = self.decoder.problem().objective_function(solution);
Some(evaluation)
}
}
#[derive(Debug, Clone, Copy)]
pub struct Params {
pub population_size: NonZeroUsize,
pub member_size: NonZeroUsize,
pub elites: usize,
pub mutants: usize,
pub crossover_bias: f64,
}
pub trait BrkgaHook<D: Decoder>: IterHook<D::P> {
fn evolved(&mut self, _: &BrkgaPopulation<D>) {}
}
#[derive(Clone)]
pub struct EmptyHook;
impl<D: Decoder> BrkgaHook<D> for EmptyHook {}
impl<P: Problem> IterHook<P> for EmptyHook {}