-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from king-11/examples
Simple Examples
- Loading branch information
Showing
3 changed files
with
331 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>>()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} |