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
|
## 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.
|
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.
|
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