From 22ace4415e29f69248ae48023fc289cefebad402 Mon Sep 17 00:00:00 2001 From: logaritmisk Date: Mon, 25 Dec 2017 22:32:48 +0100 Subject: [PATCH] Fmt. Clippy. --- examples/parabole.rs | 19 +++--- examples/parabole.rs.bk | 134 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 44 ++++++------- src/lib.rs.bk | 131 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 297 insertions(+), 31 deletions(-) create mode 100644 examples/parabole.rs.bk create mode 100644 src/lib.rs.bk diff --git a/examples/parabole.rs b/examples/parabole.rs index bf718d2..63d3da5 100644 --- a/examples/parabole.rs +++ b/examples/parabole.rs @@ -44,9 +44,7 @@ impl Individual for Parabole { type Fitness = Fitness; fn mate(&self, other: &Parabole) -> Parabole { - Parabole { - x: (self.x + other.x) / 2.0, - } + Parabole { x: (self.x + other.x) / 2.0 } } fn mutate(&mut self) { @@ -93,13 +91,13 @@ fn main() { .take(5), ) .map(|(a, b)| a.individual.mate(&b.individual)) - .map(|individual| Wrapper { - individual: individual, - fitness: None, + .map(|individual| { + Wrapper { + individual: individual, + fitness: None, + } }) - .for_each(|wrapper| { - population.push(wrapper); - }); + .for_each(|wrapper| { population.push(wrapper); }); // Mutate all to get new children. parents @@ -124,7 +122,8 @@ fn main() { println!( "{:#?}", - simulation.population + simulation + .population .iter() .take(10) .map(|individual| &individual.individual) diff --git a/examples/parabole.rs.bk b/examples/parabole.rs.bk new file mode 100644 index 0000000..bf718d2 --- /dev/null +++ b/examples/parabole.rs.bk @@ -0,0 +1,134 @@ +extern crate rand; +extern crate rayon; +extern crate genetisk; + +use std::cmp::Ordering; + + +use rand::distributions::{IndependentSample, Range}; +use rayon::prelude::*; + +use genetisk::{Individual, Wrapper, MaximizeSelector, MinimizeSelector, Select, Simulation}; + + +#[derive(Clone, Copy, Debug)] +struct Fitness(f64); + +impl PartialEq for Fitness { + fn eq(&self, other: &Fitness) -> bool { + (self.0 - other.0).abs() < 0.0001 + } +} + +impl Eq for Fitness {} + +impl PartialOrd for Fitness { + fn partial_cmp(&self, other: &Fitness) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl Ord for Fitness { + fn cmp(&self, other: &Fitness) -> Ordering { + self.0.partial_cmp(&other.0).unwrap_or(Ordering::Equal) + } +} + + +#[derive(Clone, Debug)] +struct Parabole { + x: f64, +} + +impl Individual for Parabole { + type Fitness = Fitness; + + fn mate(&self, other: &Parabole) -> Parabole { + Parabole { + x: (self.x + other.x) / 2.0, + } + } + + fn mutate(&mut self) { + let between = Range::new(-1.0, 1.0); + + let mut rng = rand::thread_rng(); + let offset = between.ind_sample(&mut rng); + + self.x += offset; + } + + fn fitness(&self) -> Self::Fitness { + Fitness(10.0 - ((self.x + 3.0) * (self.x + 3.0))) + } +} + + +fn main() { + let initial = (0..300) + .map(|i| Parabole { x: i as f64 }) + .collect::>(); + + let population_size = initial.len(); + + let mut simulation = Simulation::with_population(initial); + + simulation.calculate(); + + for _ in 0..250_000 { + simulation.evolve(|parents, population| { + // Mate top 10 to get 5 children. + parents + .iter() + .enumerate() + .filter(|&(n, _)| n % 2 == 0) + .map(|(_, wrapper)| wrapper) + .take(5) + .zip( + parents + .iter() + .enumerate() + .filter(|&(n, _)| n % 2 == 1) + .map(|(_, wrapper)| wrapper) + .take(5), + ) + .map(|(a, b)| a.individual.mate(&b.individual)) + .map(|individual| Wrapper { + individual: individual, + fitness: None, + }) + .for_each(|wrapper| { + population.push(wrapper); + }); + + // Mutate all to get new children. + parents + .par_iter() + .map(|wrapper| wrapper.individual.clone()) + .map(|mut individual| { + individual.mutate(); + + Wrapper { + individual: individual, + fitness: None, + } + }) + .collect_into(population); + + // Add all parents again. + population.extend(parents.iter().cloned()); + }); + + simulation.population.truncate(population_size); + } + + println!( + "{:#?}", + simulation.population + .iter() + .take(10) + .map(|individual| &individual.individual) + .collect::>() + ); + println!(); +} diff --git a/src/lib.rs b/src/lib.rs index 8d40f13..e09ccfa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ pub trait Individual: Send { pub trait Select: Send where - T: Individual + T: Individual, { fn select(&self, population: Vec>) -> Vec>; } @@ -28,18 +28,16 @@ pub struct MaximizeSelector { impl MaximizeSelector { pub fn new(count: usize) -> Self { - MaximizeSelector { - count: count, - } + MaximizeSelector { count: count } } } impl Select for MaximizeSelector where - T: Individual + T: Individual, { fn select(&self, mut population: Vec>) -> Vec> { - population.par_sort_unstable_by(|a, b| b.fitness.cmp(&a.fitness)); + population.sort_unstable_by(|a, b| b.fitness.cmp(&a.fitness)); population.into_iter().take(self.count).collect() } @@ -52,18 +50,16 @@ pub struct MinimizeSelector { impl MinimizeSelector { pub fn new(count: usize) -> Self { - MinimizeSelector { - count: count, - } + MinimizeSelector { count: count } } } impl Select for MinimizeSelector where - T: Individual + T: Individual, { fn select(&self, mut population: Vec>) -> Vec> { - population.par_sort_unstable_by(|a, b| a.fitness.cmp(&b.fitness)); + population.sort_unstable_by(|a, b| a.fitness.cmp(&b.fitness)); population.into_iter().take(self.count).collect() } @@ -96,28 +92,34 @@ where initial .into_par_iter() - .map(|individual| Wrapper { - individual: individual, - fitness: None, + .map(|individual| { + Wrapper { + individual: individual, + fitness: None, + } }) .collect_into(&mut population); - Simulation { - population: population, - } + Simulation { population: population } } + #[inline] pub fn calculate(&mut self) { - self.population.par_iter_mut() + self.population + .par_iter_mut() .filter(|wrapper| wrapper.fitness.is_none()) - .for_each(|wrapper| wrapper.fitness = Some(wrapper.individual.fitness())); + .for_each(|wrapper| { + wrapper.fitness = Some(wrapper.individual.fitness()) + }); - self.population.par_sort_unstable_by(|a, b| b.fitness.cmp(&a.fitness)); + self.population.par_sort_unstable_by( + |a, b| b.fitness.cmp(&a.fitness), + ); } pub fn evolve(&mut self, func: F) where - F: Fn(&[Wrapper], &mut Vec>) + F: Fn(&[Wrapper], &mut Vec>), { let mut population = Vec::with_capacity(self.population.len()); diff --git a/src/lib.rs.bk b/src/lib.rs.bk new file mode 100644 index 0000000..2f778e6 --- /dev/null +++ b/src/lib.rs.bk @@ -0,0 +1,131 @@ +extern crate rayon; + + +use rayon::prelude::*; + + +pub trait Individual: Send { + type Fitness: Send + Ord; + + fn fitness(&self) -> Self::Fitness; + + fn mate(&self, other: &Self) -> Self; + fn mutate(&mut self); +} + + +pub trait Select: Send +where + T: Individual +{ + fn select(&self, population: Vec>) -> Vec>; +} + + +pub struct MaximizeSelector { + count: usize, +} + +impl MaximizeSelector { + pub fn new(count: usize) -> Self { + MaximizeSelector { + count: count, + } + } +} + +impl Select for MaximizeSelector +where + T: Individual +{ + fn select(&self, mut population: Vec>) -> Vec> { + population.sort_unstable_by(|a, b| b.fitness.cmp(&a.fitness)); + + population.into_iter().take(self.count).collect() + } +} + + +pub struct MinimizeSelector { + count: usize, +} + +impl MinimizeSelector { + pub fn new(count: usize) -> Self { + MinimizeSelector { + count: count, + } + } +} + +impl Select for MinimizeSelector +where + T: Individual +{ + fn select(&self, mut population: Vec>) -> Vec> { + population.sort_unstable_by(|a, b| a.fitness.cmp(&b.fitness)); + + population.into_iter().take(self.count).collect() + } +} + + +#[derive(Clone)] +pub struct Wrapper +where + T: Individual, +{ + pub individual: T, + pub fitness: Option, +} + + +pub struct Simulation +where + T: Individual, +{ + pub population: Vec>, +} + +impl Simulation +where + T: Individual, +{ + pub fn with_population(initial: Vec) -> Self { + let mut population = Vec::with_capacity(initial.len() * 2); + + initial + .into_par_iter() + .map(|individual| Wrapper { + individual: individual, + fitness: None, + }) + .collect_into(&mut population); + + Simulation { + population: population, + } + } + + #[inline] + pub fn calculate(&mut self) { + self.population.par_iter_mut() + .filter(|wrapper| wrapper.fitness.is_none()) + .for_each(|wrapper| wrapper.fitness = Some(wrapper.individual.fitness())); + + self.population.par_sort_unstable_by(|a, b| b.fitness.cmp(&a.fitness)); + } + + pub fn evolve(&mut self, func: F) + where + F: Fn(&[Wrapper], &mut Vec>) + { + let mut population = Vec::with_capacity(self.population.len()); + + func(&self.population, &mut population); + + self.population = population; + + self.calculate(); + } +}