Skip to content

Commit

Permalink
Merge pull request #17 from king-11/examples
Browse files Browse the repository at this point in the history
Simple Examples
  • Loading branch information
king-11 authored Oct 31, 2021
2 parents 21bbc27 + 19118ab commit a69b798
Show file tree
Hide file tree
Showing 3 changed files with 331 additions and 0 deletions.
69 changes: 69 additions & 0 deletions examples/eqn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use genx::{
crossover::simulated_binary_crossover,
mutation::polynomial_mutation,
selection::{random_selection, stochastic_universal_selection},
};
use rand::{distributions::Uniform, prelude::Distribution};

fn main() {
let equation = |x: f32| 3.0 * x * x + 8.0 * (-x) + 5.0;
let population_size = 15;
let iterations = 1000;
let mutation_probability = 0.5;
let between = Uniform::from(-10.0..10.0);
let mut prng = rand::thread_rng();

let fitness_function = |x: f32| 1.0 / ((equation(x) - x).abs() + 1.0);
let mut population = (0..population_size)
.map(|_| between.sample(&mut prng))
.collect::<Vec<f32>>();

let get_fitness_values = |population: &Vec<f32>| {
population
.iter()
.map(|x| fitness_function(*x))
.collect::<Vec<f32>>()
};

let best_fitness_value = |population: &Vec<f32>| {
population
.iter()
.max_by(|&a, &b| {
fitness_function(*a)
.partial_cmp(&fitness_function(*b))
.unwrap_or(std::cmp::Ordering::Equal)
})
.unwrap()
.clone()
};

let mut best_now = best_fitness_value(&population);
let between = Uniform::from(0.0..1.0);
for _ in 0..iterations {
let idxs = random_selection(population_size, 2, None);
let (mut child1, mut child2) =
simulated_binary_crossover(population[idxs[0]], population[idxs[1]], 5.0, None);

if between.sample(&mut prng) < mutation_probability {
child1 = polynomial_mutation(child1, 100.0, 10.0, None)
}
if between.sample(&mut prng) < mutation_probability {
child2 = polynomial_mutation(child2, 100.0, 10.0, None)
}

population.push(child1);
population.push(child2);

let fitness_values = get_fitness_values(&population);
let selected_idx = stochastic_universal_selection(&fitness_values, population_size, None);
population = selected_idx
.iter()
.map(|&a| population[a])
.collect::<Vec<f32>>();
let best = best_fitness_value(&population);
if fitness_function(best) > fitness_function(best_now) {
best_now = best;
}
}
println!("{} {}", best_now, equation(best_now));
}
167 changes: 167 additions & 0 deletions examples/knp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
use std::fmt::{Debug, Display};

use genx::{
crossover::uniform_crossover,
mutation::inversion_mutation,
selection::{random_selection, stochastic_universal_selection},
};

use rand::{distributions::Uniform, prelude::Distribution};

struct Item {
weight: u32,
value: u32,
}

impl Debug for Item {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Item {{ weight: {}, value: {} }}",
self.weight, self.value
)
}
}

impl Display for Item {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Item {{ weight: {}, value: {} }}",
self.weight, self.value
)
}
}

fn main() {
let knapsack_threshold = 80;
let knapsack_items = vec![
Item {
weight: 9,
value: 150,
},
Item {
weight: 13,
value: 35,
},
Item {
weight: 15,
value: 10,
},
Item {
weight: 50,
value: 60,
},
Item {
weight: 15,
value: 60,
},
Item {
weight: 68,
value: 45,
},
Item {
weight: 27,
value: 60,
},
Item {
weight: 39,
value: 40,
},
Item {
weight: 23,
value: 30,
},
Item {
weight: 52,
value: 10,
},
Item {
weight: 11,
value: 70,
},
Item {
weight: 32,
value: 30,
},
Item {
weight: 24,
value: 15,
},
];
let knapsack_size = knapsack_items.len();

let iterations = 300;
let population_size = 20;
let mutation_probability = 0.4;
let mut population = (0..population_size)
.into_iter()
.map(|_| (0..knapsack_size).map(|_| rand::random::<bool>()).collect())
.collect::<Vec<Vec<bool>>>();

let fitness_function = |individual: &Vec<bool>| -> f32 {
let mut total_weight = 0;
let mut total_value = 0;
for (item, &is_included) in knapsack_items.iter().zip(individual.iter()) {
if is_included {
total_weight += item.weight;
total_value += item.value;
}
}
if total_weight > knapsack_threshold {
total_value = 0;
}
1.0 + total_value as f32
};

let get_fitness_values = |population: &Vec<Vec<bool>>| {
population
.iter()
.map(|x| fitness_function(x))
.collect::<Vec<f32>>()
};

let best_fitness_value = |population: &Vec<Vec<bool>>| {
population
.iter()
.max_by(|&a, &b| {
fitness_function(a)
.partial_cmp(&fitness_function(b))
.unwrap_or(std::cmp::Ordering::Equal)
})
.unwrap()
.clone()
};

let mut best_now = best_fitness_value(&population);
let between = Uniform::from(0.0..1.0);
let mut prng = rand::thread_rng();
for _ in 0..iterations {
let idxs = random_selection(population_size, 2, None);
let (mut child1, mut child2) =
uniform_crossover(&population[idxs[0]], &population[idxs[1]], 0.5, None);

if between.sample(&mut prng) < mutation_probability {
inversion_mutation(&mut child1, None);
}
if between.sample(&mut prng) < mutation_probability {
inversion_mutation(&mut child2, None);
}
population.push(child1);
population.push(child2);

let fitness_values = get_fitness_values(&population);
let selected_idx = stochastic_universal_selection(&fitness_values, population_size, None);
population = selected_idx
.iter()
.map(|&a| population[a].clone())
.collect::<Vec<Vec<bool>>>();
let best = best_fitness_value(&population);
if fitness_function(&best) > fitness_function(&best_now) {
best_now = best;
}
}

println!("{}", fitness_function(&best_now));
println!("{:?}", best_now.iter().zip(knapsack_items).filter(|predicate| *predicate.0).map(|x| x.1).collect::<Vec<Item>>());
}
95 changes: 95 additions & 0 deletions examples/tsp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use std::{cmp::Ordering, f32::MAX};

use genx::{
crossover::order_crossover,
mutation::scramble_mutation,
selection::{random_selection, stochastic_universal_selection},
};

use rand::{distributions::Uniform, prelude::Distribution, seq::SliceRandom, thread_rng};

fn main() {
let graph = vec![
vec![MAX, 5.0, 6.0, 4.56, 9.84, 3.56, 11.25, 9.80],
vec![5.0, MAX, 3.0, 2.0, 7.0, 1.0, 8.0, 6.0],
vec![6.0, 3.0, MAX, 2.0, 6.0, 1.0, 7.0, 5.0],
vec![4.56, 2.0, 2.0, MAX, 3.0, 1.0, 4.0, 3.0],
vec![9.84, 7.0, 6.0, 3.0, MAX, 2.0, 5.0, 4.0],
vec![3.56, 1.0, 1.0, 1.0, 2.0, MAX, 3.0, 2.0],
vec![11.25, 8.0, 7.0, 4.0, 5.0, 3.0, MAX, 2.0],
vec![9.80, 6.0, 5.0, 3.0, 4.0, 2.0, 2.0, MAX],
];
let n = graph.len();
let population_size = 15;
let iterations = 100;
let mutation_probability = 0.5;
let between = Uniform::from(0.0..1.0);
let mut prng = thread_rng();

let fitness_function = |a: &Vec<usize>| {
let mut sum = 0.0;
let mut prev_idx = a[0];
for (i, &idx) in a.iter().enumerate() {
if i == 0 {
continue;
}
sum += graph[prev_idx][idx];
prev_idx = idx;
}

sum
};

let mut population = (0..population_size)
.map(|_| {
let mut a = (0..n).collect::<Vec<usize>>();
a.shuffle(&mut prng);
a
})
.collect::<Vec<Vec<usize>>>();

let get_fitness_values = |population: &Vec<Vec<usize>>| {
population
.iter()
.map(|a| fitness_function(a))
.collect::<Vec<f32>>()
};

let mut best_now = population[0].clone();

for _ in 0..iterations {
let idxs = random_selection(population_size, 2, None);
let (mut child1, mut child2) =
order_crossover(&population[idxs[0]], &population[idxs[1]], None);

if between.sample(&mut prng) < mutation_probability {
scramble_mutation(&mut child1, None);
}
if between.sample(&mut prng) < mutation_probability {
scramble_mutation(&mut child2, None);
}

population.push(child1);
population.push(child2);
let fitness_values = get_fitness_values(&population);
let selected_idx = stochastic_universal_selection(&fitness_values, population_size, None);
population = selected_idx
.iter()
.map(|&a| population[a].clone())
.collect::<Vec<Vec<usize>>>();

let best = population
.iter()
.min_by(|a, b| {
fitness_function(a)
.partial_cmp(&fitness_function(b))
.unwrap_or(Ordering::Equal)
})
.unwrap();

if fitness_function(best) < fitness_function(&best_now) {
best_now = best.clone();
}
}
print!("{:?} {}", best_now, fitness_function(&best_now));
}

0 comments on commit a69b798

Please sign in to comment.