memega 0.1.0

genetic algorithm library
Documentation
use crate::cfg::Cfg;
use crate::eval::{Evaluator, FitnessFn};
use crate::ops::crossover::crossover_arith;
use crate::ops::distance::dist2;
use crate::ops::mutation::{mutate_normal, mutate_rate, mutate_uniform};
use crate::ops::util::rand_vec;
use crate::run::runner::Runner;

pub type FuncState = Vec<f64>;

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct FuncEvaluator<F: FitnessFn<FuncState>> {
    dim: usize,
    st: f64,
    en: f64,
    f: F,
}

impl<F: FitnessFn<FuncState>> FuncEvaluator<F> {
    fn new(dim: usize, st: f64, en: f64, f: F) -> Self {
        Self { dim, st, en, f }
    }
}

impl<F: FitnessFn<FuncState>> Evaluator for FuncEvaluator<F> {
    type Genome = FuncState;

    fn crossover(&self, s1: &mut FuncState, s2: &mut FuncState, idx: usize) {
        match idx {
            0 => {}
            1 => crossover_arith(s1, s2),
            _ => panic!("bug"),
        };
    }

    fn mutate(&self, s: &mut FuncState, rate: f64, idx: usize) {
        match idx {
            0 => mutate_rate(s, 1.0, |v| mutate_normal(v, rate).clamp(self.st, self.en)),
            _ => panic!("bug"),
        };
    }

    fn fitness(&self, s: &FuncState, gen: usize) -> f64 {
        (self.f)(s, gen)
    }

    fn distance(&self, s1: &FuncState, s2: &FuncState) -> f64 {
        dist2(s1, s2)
    }
}

pub fn func_runner<F: FitnessFn<FuncState>>(
    dim: usize,
    st: f64,
    en: f64,
    f: F,
    cfg: Cfg,
) -> Runner<FuncEvaluator<F>> {
    Runner::new(FuncEvaluator::new(dim, st, en, f), cfg, move || {
        rand_vec(dim, || mutate_uniform(st, en))
    })
}