use num::abs;
use optlib::genetic::{self, creation, cross, mutation, pairing, pre_birth, selection};
use optlib::tools::logging;
use optlib::tools::stopchecker;
use optlib::{GoalFromFunction, Optimizer};
use optlib_testfunc;
type Gene = f32;
type Chromosomes = Vec<Gene>;
#[test]
fn genetic_rastrigin() {
let minval: Gene = -5.12;
let maxval: Gene = 5.12;
let population_size = 20;
let chromo_count = 30;
let intervals = vec![(minval, maxval); chromo_count];
let goal = GoalFromFunction::new(optlib_testfunc::rastrigin);
let creator = creation::vec_float::RandomCreator::new(population_size, intervals.clone());
let families_count = population_size / 2;
let rounds_count = 5;
let pairing = pairing::Tournament::new(families_count).rounds_count(rounds_count);
let single_cross = cross::FloatCrossExp::new();
let cross = cross::VecCrossAllGenes::new(Box::new(single_cross));
let mutation_probability = 15.0;
let mutation_gene_count = 3;
let single_mutation = mutation::BitwiseMutation::new(mutation_gene_count);
let mutation = mutation::VecMutation::new(mutation_probability, Box::new(single_mutation));
let pre_births: Vec<Box<dyn genetic::PreBirth<Chromosomes>>> = vec![Box::new(
pre_birth::vec_float::CheckChromoInterval::new(intervals.clone()),
)];
let change_max_iterations = 200;
let change_delta = 1e-7;
let stop_checker = stopchecker::CompositeAny::new(vec![
Box::new(stopchecker::Threshold::new(1e-4)),
Box::new(stopchecker::GoalNotChange::new(
change_max_iterations,
change_delta,
)),
Box::new(stopchecker::MaxIterations::new(3000)),
]);
let selections: Vec<Box<dyn genetic::Selection<Chromosomes>>> = vec![
Box::new(selection::KillFitnessNaN::new()),
Box::new(selection::LimitPopulation::new(population_size)),
];
let loggers: Vec<Box<dyn logging::Logger<Chromosomes>>> = vec![];
let mut optimizer = genetic::GeneticOptimizer::new(
Box::new(goal),
Box::new(stop_checker),
Box::new(creator),
Box::new(pairing),
Box::new(cross),
Box::new(mutation),
selections,
pre_births,
);
optimizer.set_loggers(loggers);
match optimizer.find_min() {
None => assert!(false),
Some((solution, goal_value)) => {
for i in 0..chromo_count {
assert!(abs(solution[i] - 0.0) < 0.01);
}
assert!(abs(goal_value) < 1e-3);
}
}
}