extern crate oxigen;
extern crate rand;
use oxigen::prelude::*;
use rand::distributions::Standard;
use rand::prelude::*;
use std::fmt::Display;
#[derive(Clone)]
struct OneMax(Vec<bool>);
impl Display for OneMax {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "{:?}", self.0)
}
}
impl Genotype<bool> for OneMax {
type ProblemSize = usize;
fn iter(&self) -> std::slice::Iter<bool> {
self.0.iter()
}
fn into_iter(self) -> std::vec::IntoIter<bool> {
self.0.into_iter()
}
fn from_iter<I: Iterator<Item = bool>>(&mut self, genes: I) {
self.0 = genes.collect();
}
fn generate(size: &Self::ProblemSize) -> Self {
let mut individual = Vec::with_capacity(*size as usize);
let mut rgen = SmallRng::from_entropy();
for _i in 0..*size {
individual.push(rgen.sample(Standard));
}
OneMax(individual)
}
fn fitness(&self) -> f64 {
(self.0.iter().filter(|el| **el).count()) as f64
}
fn mutate(&mut self, _rgen: &mut SmallRng, index: usize) {
self.0[index] = !self.0[index];
}
fn is_solution(&self, fitness: f64) -> bool {
fitness as usize == self.0.len()
}
}
fn main() {
let problem_size: usize = std::env::args()
.nth(1)
.expect("Enter a number bigger than 1")
.parse()
.expect("Enter a number bigger than 1");
let population_size = problem_size * 8;
let log2 = (f64::from(problem_size as u32) * 4_f64).log2().ceil();
let (solutions, generation, _progress, _population) = GeneticExecution::<bool, OneMax>::new()
.population_size(population_size)
.genotype_size(problem_size)
.mutation_rate(Box::new(MutationRates::Linear(SlopeParams {
start: f64::from(problem_size as u32) / (8_f64 + 2_f64 * log2) / 100_f64,
bound: 0.005,
coefficient: -0.0002,
})))
.selection_rate(Box::new(SelectionRates::Linear(SlopeParams {
start: log2 - 2_f64,
bound: log2 / 1.5,
coefficient: -0.0005,
})))
.select_function(Box::new(SelectionFunctions::Cup))
.run();
println!("Finished in the generation {}", generation);
for sol in &solutions {
println!("{}", sol);
}
}