feat: ✨ differential_evolution
This commit is contained in:
parent
ba805501c0
commit
6584d8d24d
3 changed files with 152 additions and 2 deletions
|
@ -2,11 +2,11 @@
|
|||
|
||||
## Steepest Descent
|
||||
|
||||
1- We need starting solution x^t. Zeroise the iteration which is t. Specify tolerance value as ε.
|
||||
1- We need starting solution x^t. Reset the iteration which is t. Specify tolerance value as ε.
|
||||
|
||||
2- at x^t point calculate g^t gradient and ||g^t|| then if ||g^t|| <= ε stop it, else continue.
|
||||
|
||||
3- Specfify road direction as d^t = -g^t.
|
||||
3- Specify road direction as d^t = -g^t.
|
||||
|
||||
4- Calculate f(x^t + a^t*d^t) as like a^t (step size) is minimum.
|
||||
|
||||
|
|
9
differential_evolution/Cargo.toml
Normal file
9
differential_evolution/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "differential_evolution"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rand = "0.8.5"
|
141
differential_evolution/src/main.rs
Normal file
141
differential_evolution/src/main.rs
Normal file
|
@ -0,0 +1,141 @@
|
|||
use std::io;
|
||||
|
||||
use rand::Rng;
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
|
||||
println!("Decision Variable Count");
|
||||
let decision_variable_count = get_float_input() as usize;
|
||||
|
||||
println!("Population Number");
|
||||
let population_number = get_float_input() as u64;
|
||||
|
||||
println!("Crossover Rate");
|
||||
let crossover_rate = get_float_input();
|
||||
|
||||
println!("Scale Factor");
|
||||
let scale_factor = get_float_input();
|
||||
|
||||
println!("Upper Bound");
|
||||
let upper_bound = get_float_input();
|
||||
|
||||
println!("Lower Bound");
|
||||
let lower_bound = get_float_input();
|
||||
|
||||
println!("Iteration");
|
||||
let iteration = get_float_input() as usize;
|
||||
|
||||
let mut population = create_population(
|
||||
population_number,
|
||||
decision_variable_count,
|
||||
upper_bound,
|
||||
lower_bound,
|
||||
);
|
||||
|
||||
for _ in 0..iteration {
|
||||
for (current_location, element) in population.clone().iter().enumerate() {
|
||||
let new_volunteer = mutate_and_recombine(
|
||||
current_location,
|
||||
crossover_rate,
|
||||
scale_factor,
|
||||
decision_variable_count,
|
||||
population.clone(),
|
||||
);
|
||||
|
||||
let current_calculation = calculate(element.clone());
|
||||
let new_calculation = calculate(new_volunteer.clone());
|
||||
if new_calculation < current_calculation {
|
||||
println!(
|
||||
"Changed | Old = {} | New {}",
|
||||
current_calculation, new_calculation
|
||||
);
|
||||
population[current_location] = new_volunteer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("{:#?}", population);
|
||||
}
|
||||
|
||||
fn get_float_input() -> f64 {
|
||||
let mut input = String::new();
|
||||
io::stdin().read_line(&mut input).unwrap();
|
||||
let input: f64 = input.trim().parse().unwrap();
|
||||
input
|
||||
}
|
||||
|
||||
fn create_population(
|
||||
population_number: u64,
|
||||
decision_variable_count: usize,
|
||||
upper_bound: f64,
|
||||
lower_bound: f64,
|
||||
) -> Vec<Vec<f64>> {
|
||||
let mut population = vec![vec![decision_variable_count as f64]; population_number as usize];
|
||||
|
||||
for i in 0..population_number {
|
||||
let mut randomized_single_dimension = vec![];
|
||||
for _ in 0..decision_variable_count {
|
||||
randomized_single_dimension
|
||||
.push(rand::thread_rng().gen_range(lower_bound..=upper_bound));
|
||||
}
|
||||
population[i as usize] = randomized_single_dimension;
|
||||
}
|
||||
population
|
||||
}
|
||||
|
||||
fn calculate(decision_variables: Vec<f64>) -> f64 {
|
||||
let mut result = 0.0;
|
||||
for element in decision_variables {
|
||||
result += element * element;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn mutate_and_recombine(
|
||||
current_location: usize,
|
||||
crossover_rate: f64,
|
||||
scale_factor: f64,
|
||||
decision_variable_count: usize,
|
||||
population: Vec<Vec<f64>>,
|
||||
) -> Vec<f64> {
|
||||
let definite_random_decision_index: usize =
|
||||
rand::thread_rng().gen_range(0..=decision_variable_count);
|
||||
let mut definite_random = rand::thread_rng().gen_range(0..population.len());
|
||||
|
||||
while definite_random == current_location {
|
||||
definite_random = rand::thread_rng().gen_range(0..population.len());
|
||||
}
|
||||
|
||||
let mut chosen_indices = vec![];
|
||||
for _ in 0..3 {
|
||||
chosen_indices.sort();
|
||||
|
||||
let mut maybe = rand::thread_rng().gen_range(0..population.len());
|
||||
while maybe == current_location || chosen_indices.binary_search(&maybe).is_ok() {
|
||||
maybe = rand::thread_rng().gen_range(0..population.len());
|
||||
}
|
||||
chosen_indices.push(maybe);
|
||||
}
|
||||
|
||||
let ingredients: Vec<Vec<f64>> = vec![
|
||||
population[chosen_indices[0]].clone(),
|
||||
population[chosen_indices[1]].clone(),
|
||||
population[chosen_indices[2]].clone(),
|
||||
];
|
||||
|
||||
let mut new_volunteer = vec![];
|
||||
|
||||
for i in 0..decision_variable_count {
|
||||
if rand::thread_rng().gen_range(0.0..=1.0) < crossover_rate
|
||||
|| i == definite_random_decision_index
|
||||
{
|
||||
new_volunteer
|
||||
.push(ingredients[0][i] + scale_factor * (ingredients[1][i] - ingredients[2][i]));
|
||||
} else {
|
||||
new_volunteer.push(population[definite_random][i]);
|
||||
}
|
||||
}
|
||||
|
||||
new_volunteer
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue