Skip to content

Commit

Permalink
Merge pull request #19 from m-decoster/generic-fitness
Browse files Browse the repository at this point in the history
Generic fitness
  • Loading branch information
m-decoster committed Feb 22, 2016
2 parents 399c78e + e7aa7f9 commit 4cccece
Show file tree
Hide file tree
Showing 16 changed files with 274 additions and 675 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rsgenetic"
version = "0.13.1"
version = "0.14.0"
authors = ["Mathieu De Coster <[email protected]>"]
description = "A library providing genetic algorithm execution."
repository = "https://github.com/m-decoster/RsGenetic"
Expand Down
125 changes: 0 additions & 125 deletions examples/hello_world.rs

This file was deleted.

43 changes: 39 additions & 4 deletions examples/max_parabole.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,50 @@ use rsgenetic::sim::seq::Simulator;
use rsgenetic::sim::select::*;
use rsgenetic::pheno::*;
use rand::distributions::{IndependentSample, Range};
use std::cmp::Ordering;

struct MyFitness {
f: f64,
}

impl Eq for MyFitness {}

impl PartialEq for MyFitness {
fn eq(&self, other: &MyFitness) -> bool {
(self.f - other.f).abs() < 0.0001
}
}

impl PartialOrd for MyFitness {
fn partial_cmp(&self, other: &MyFitness) -> Option<Ordering> {
self.f.partial_cmp(&other.f)
}
}

impl Ord for MyFitness {
fn cmp(&self, other: &MyFitness) -> Ordering {
self.partial_cmp(other).unwrap_or(Ordering::Equal)
}
}

impl Fitness for MyFitness {
fn zero() -> MyFitness {
MyFitness { f: 0.0 }
}

fn abs_diff(&self, other: &MyFitness) -> MyFitness {
MyFitness { f: (self.f - other.f).abs() }
}
}

struct MyData {
x: f64,
}

impl Phenotype for MyData {
fn fitness(&self) -> Fitness {
impl Phenotype<MyFitness> for MyData {
fn fitness(&self) -> MyFitness {
// Calculate the function here, because it's what we wish to maximize.
Fitness::new(10.0 - ((self.x + 3.0) * (self.x + 3.0)))
MyFitness { f: 10.0 - ((self.x + 3.0) * (self.x + 3.0)) }
}

fn crossover(&self, other: &MyData) -> MyData {
Expand Down Expand Up @@ -72,5 +107,5 @@ fn main() {
let time = s.time();
println!("Execution time: {} ns.", time.unwrap());
println!("Expected result: (-3, 10).");
println!("Result: ({}, {}).", result.x, result.fitness());
println!("Result: ({}, {}).", result.x, result.fitness().f);
}
47 changes: 42 additions & 5 deletions examples/max_parabole_steps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,50 @@ use rsgenetic::sim::seq::Simulator;
use rsgenetic::sim::select::*;
use rsgenetic::pheno::*;
use rand::distributions::{IndependentSample, Range};
use std::cmp::Ordering;

struct MyFitness {
f: f64,
}

impl Eq for MyFitness {}

impl PartialEq for MyFitness {
fn eq(&self, other: &MyFitness) -> bool {
(self.f - other.f).abs() < 0.0001
}
}

impl PartialOrd for MyFitness {
fn partial_cmp(&self, other: &MyFitness) -> Option<Ordering> {
self.f.partial_cmp(&other.f)
}
}

impl Ord for MyFitness {
fn cmp(&self, other: &MyFitness) -> Ordering {
self.partial_cmp(other).unwrap_or(Ordering::Equal)
}
}

impl Fitness for MyFitness {
fn zero() -> MyFitness {
MyFitness { f: 0.0 }
}

fn abs_diff(&self, other: &MyFitness) -> MyFitness {
MyFitness { f: (self.f - other.f).abs() }
}
}

struct MyData {
x: f64,
}

impl Phenotype for MyData {
fn fitness(&self) -> Fitness {
impl Phenotype<MyFitness> for MyData {
fn fitness(&self) -> MyFitness {
// Calculate the function here, because it's what we wish to maximize.
Fitness::new((10.0 - ((self.x + 3.0) * (self.x + 3.0))))
MyFitness { f: 10.0 - ((self.x + 3.0) * (self.x + 3.0)) }
}

fn crossover(&self, other: &MyData) -> MyData {
Expand Down Expand Up @@ -71,11 +106,13 @@ fn main() {
.build();
while let StepResult::Success = s.step() {
let result = s.get().unwrap();
println!("Intermediate result: ({}, {}).", result.x, result.fitness());
println!("Intermediate result: ({}, {}).",
result.x,
result.fitness().f);
}
let result = s.get().unwrap();
let time = s.time();
println!("Execution time: {} ns.", time.unwrap());
println!("Expected result: (-3, 10).");
println!("Result: ({}, {}).", result.x, result.fitness());
println!("Result: ({}, {}).", result.x, result.fitness().f);
}
36 changes: 25 additions & 11 deletions examples/truck_loading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,28 @@ const NUM_TRUCKS: usize = 5;
const CAPACITY: i32 = 10;
const PACKAGES: &'static [i32] = &[3, 8, 2, 7, 6, 1, 3];

#[derive(PartialOrd,Ord,PartialEq,Eq)]
struct SchemeFitness {
f: i32,
}

impl Fitness for SchemeFitness {
fn zero() -> SchemeFitness {
SchemeFitness { f: 0 }
}

fn abs_diff(&self, other: &Self) -> Self {
SchemeFitness { f: (self.f - other.f).abs() }
}
}

struct LoadingScheme {
scheme: Scheme,
}

impl Phenotype for LoadingScheme {
fn fitness(&self) -> Fitness {
let mut ret: f64 = 0.0;
impl Phenotype<SchemeFitness> for LoadingScheme {
fn fitness(&self) -> SchemeFitness {
let mut ret: i32 = 100;
// Calculate for each truck the total load.
let mut trucks: Vec<PackageSize> = vec![0; NUM_TRUCKS];
for load in self.scheme.clone() {
Expand All @@ -54,20 +69,20 @@ impl Phenotype for LoadingScheme {
let space_left = CAPACITY - load;
if space_left < 0 {
// We have overfilled a truck: penalize this solution heavily.
return Fitness::new(std::f64::INFINITY);
return SchemeFitness { f: 0 };
}
if space_left == CAPACITY {
// We have an empty truck: give this solution a little boost.
// Normally, the contribution to the fitness value is 0, but now we
// detract 3 to make this an even fitter solution.
// add 3 to make this an even fitter solution.
// Note that this is an empirically found value. We could even optimize this value
// with a separate genetic algorithm!
ret -= 3.0;
ret += 10;
} else {
ret += space_left as f64;
ret -= space_left;
}
}
Fitness::new(ret)
SchemeFitness { f: ret }
}

fn crossover(&self, other: &LoadingScheme) -> LoadingScheme {
Expand Down Expand Up @@ -118,17 +133,16 @@ fn main() {
population.push(LoadingScheme { scheme: pheno });
}
let mut s = Simulator::builder(&mut population)
.set_selector(Box::new(RouletteSelector::new(10)))
.set_selector(Box::new(MaximizeSelector::new(10)))
.set_max_iters(50)
.set_fitness_type(FitnessType::Minimize)
.build();
s.run();
let result = s.get().unwrap();
let time = s.time();
println!("Execution time: {} ns.", time.unwrap());
println!("Result: {:?} | Fitness: {}.",
result.scheme,
result.fitness());
result.fitness().f);
let mut trucks: Vec<_> = vec![0; NUM_TRUCKS];
for &(index, size) in &result.scheme {
trucks[index] += size;
Expand Down
Loading

0 comments on commit 4cccece

Please sign in to comment.