use super::ga_core::{GAConfig, GAFactory, GAFlags, GeneticAlgorithm, GASolution};
use super::ga_population::GAPopulation;
use super::ga_random::{GARandomCtx, GASeed};
#[derive(Copy, Clone, Default, Debug)]
pub struct SimpleGeneticAlgorithmCfg
{
pub d_seed : GASeed,
pub pconv : f32,
pub is_min : bool,
pub max_generations : i32,
pub flags : GAFlags,
pub probability_crossover : f32,
pub probability_mutation : f32,
pub elitism : bool,
}
impl GAConfig for SimpleGeneticAlgorithmCfg
{
fn flags(&self) -> GAFlags
{
self.flags
}
fn max_generations(&self) -> i32
{
self.max_generations
}
fn probability_crossover(&self) -> f32
{
self.probability_crossover
}
fn probability_mutation(&self) -> f32
{
self.probability_mutation
}
}
impl SimpleGeneticAlgorithmCfg
{
fn elitism(&self) -> bool
{
self.elitism
}
}
pub struct SimpleGeneticAlgorithm<T: GASolution>
{
current_generation : i32,
config : SimpleGeneticAlgorithmCfg,
population : GAPopulation<T>,
rng_ctx : GARandomCtx,
}
impl<T: GASolution> SimpleGeneticAlgorithm<T>
{
pub fn new(cfg: SimpleGeneticAlgorithmCfg,
factory: Option<&mut GAFactory<T>>,
population: Option<GAPopulation<T>>) -> SimpleGeneticAlgorithm<T>
{
let p : GAPopulation<T>;
match factory
{
Some(f) => {
p = f.initial_population();
},
None => {
match population
{
Some(p_) =>
{
p = p_;
},
None =>
{
panic!("Simple Genetic Algorithm - either factory or population need to be provided");
}
}
}
}
SimpleGeneticAlgorithm { current_generation: 0, config : cfg, population : p, rng_ctx : GARandomCtx::from_seed(cfg.d_seed, String::from("")) }
}
}
impl<T: GASolution> GeneticAlgorithm<T> for SimpleGeneticAlgorithm <T>
{
fn config(&mut self) -> &GAConfig
{
&self.config
}
fn population(&mut self) -> &mut GAPopulation<T>
{
&mut self.population
}
fn initialize_internal(&mut self)
{
assert!(self.population().size() > 0);
self.population.sort();
}
fn step_internal(&mut self) -> i32
{
let mut new_individuals : Vec<T> = vec![];
for _ in 0..self.population.size()
{
let ind = self.population.select();
let mut new_ind = ind.clone();
if self.rng_ctx.test_value(self.config.probability_crossover())
{
let ind_2 = self.population.select();
new_ind = ind.crossover(ind_2);
}
new_ind.mutate(self.config.probability_mutation());
new_individuals.push(new_ind);
}
self.population.evaluate();
self.population.sort();
let best_old_individual = self.population.best().clone();
if self.config.elitism()
{
if best_old_individual.fitness() > self.population.worst().fitness()
{
}
}
self.current_generation += 1;
self.current_generation
}
fn done_internal(&mut self) -> bool
{
self.current_generation >= self.config().max_generations()
}
}