use crate::common::*;
use crate::fitness::*;
use crate::individual::*;
use crate::population::*;
pub trait Terminate {
fn meets<G: Genome>(&mut self, generation: &Generation<G>) -> bool;
}
#[derive(Debug, Clone)]
pub struct RunningMean {
nlast: usize,
epsilon: f64,
scores: Vec<f64>,
}
impl Default for RunningMean {
fn default() -> Self {
Self {
nlast: 30,
epsilon: 1e-6,
scores: Vec::with_capacity(30),
}
}
}
impl RunningMean {
pub fn new(nlast: usize) -> Self {
Self {
nlast,
..Self::default()
}
}
}
impl Terminate for RunningMean {
fn meets<G: Genome>(&mut self, generation: &Generation<G>) -> bool {
let best = generation
.population
.best_member()
.expect("empty population!")
.individual
.objective_value();
if generation.index < self.nlast {
self.scores.push(best);
return false;
} else {
let n = self.scores.len();
assert_eq!(n, self.nlast);
let fmean = self.scores.iter().sum::<f64>() / n as f64;
let diff = (best - fmean).abs();
if diff < self.epsilon {
return true;
}
let _ = self.scores.remove(0);
self.scores.push(best);
}
false
}
}
#[derive(Debug)]
pub struct Generation<G>
where
G: Genome,
{
pub index: usize,
pub population: Population<G>,
}
impl<G> Generation<G>
where
G: Genome + std::fmt::Display,
{
pub fn summary(&self) {
println!("# generation: {}", self.index);
let best = self.best_individual();
println!(
" best individual {}: objective value = {:}",
best.genome(),
best.objective_value()
);
println!("population members:");
let mut members: Vec<_> = self.population.members().collect();
members.sort_by_fitness();
for m in members {
println!(" {:}", m);
}
}
pub fn best_individual(&self) -> Individual<G> {
if let Some(member) = self.population.best_member() {
member.individual.to_owned()
} else {
panic!("empty population!")
}
}
}