diff --git a/artificial_bee_colony/abc_config.toml b/artificial_bee_colony/abc_config.toml index 7f4dbba..2fb0fa8 100644 --- a/artificial_bee_colony/abc_config.toml +++ b/artificial_bee_colony/abc_config.toml @@ -1,8 +1,8 @@ [start_parameters] -decision_variable_count = 3 -food_source_number = 100 -food_source_try_limit = 100 -upper_bound = 5 -lower_bound = -5 -iteration = 1000 -run = 5 \ No newline at end of file +decision_variable_count = 50 +food_source_number = 20 +food_source_try_limit = 1000 +upper_bound = 100 +lower_bound = -100 +iteration = 100 +run = 30 \ No newline at end of file diff --git a/artificial_bee_colony/src/bee.rs b/artificial_bee_colony/src/bee.rs index 6a885b6..0309387 100644 --- a/artificial_bee_colony/src/bee.rs +++ b/artificial_bee_colony/src/bee.rs @@ -2,18 +2,18 @@ use rand::Rng; use crate::food::FoodSource; -pub enum Bee {} +pub struct Bee {} impl Bee { pub fn employed_bee( food_sources: &mut [FoodSource], - index: usize, + food_source_index: usize, decision_variable_count: usize, upper_bound: f64, lower_bound: f64, ) { - send_bee( + Self::send_bee( food_sources, - index, + food_source_index, decision_variable_count, upper_bound, lower_bound, @@ -22,33 +22,35 @@ impl Bee { pub fn onlooker_bee( food_sources: &mut [FoodSource], - index: usize, + food_source_index: usize, total_fitness: f64, decision_variable_count: usize, upper_bound: f64, lower_bound: f64, - ) { - let fitness_for_index = food_sources[index].fitness_calculation; + ) -> bool { + let fitness_for_index = food_sources[food_source_index].fitness_calculation; if fitness_for_index / total_fitness <= rand::thread_rng().gen_range(0.0..=1.0) { - send_bee( + Self::send_bee( food_sources, - index, + food_source_index, decision_variable_count, upper_bound, lower_bound, ); + return true; } + false } pub fn scout_bee( food_sources: &mut [FoodSource], - most_tried_index: usize, + most_tried_food_source_index: usize, limit: u128, lower_bound: f64, upper_bound: f64, decision_variable_count: usize, ) { - if food_sources[most_tried_index].try_counter > limit { + if food_sources[most_tried_food_source_index].try_counter > limit { let mut coordinates_for_new = vec![]; for _ in 0..decision_variable_count { let random = lower_bound @@ -56,41 +58,51 @@ impl Bee { coordinates_for_new.push(random); } let new_food_source = FoodSource::new(coordinates_for_new); - food_sources[most_tried_index] = new_food_source; + food_sources[most_tried_food_source_index] = new_food_source; + } + } + + fn send_bee( + food_sources: &mut [FoodSource], + food_source_index: usize, + decision_variable_count: usize, + upper_bound: f64, + lower_bound: f64, + ) { + let mut different_food_source_index = rand::thread_rng().gen_range(0..food_sources.len()); + while different_food_source_index == food_source_index { + different_food_source_index = rand::thread_rng().gen_range(0..food_sources.len()); + } + let decision_variable_index = rand::thread_rng().gen_range(0..decision_variable_count); + let randomness = rand::thread_rng().gen_range(-1.0..=1.0); + + let mut candidate_decision_variable = food_sources[food_source_index].coordinates + [decision_variable_index] + + randomness + * (food_sources[food_source_index].coordinates[decision_variable_index] + - food_sources[different_food_source_index].coordinates + [decision_variable_index]); + if candidate_decision_variable > upper_bound { + candidate_decision_variable = upper_bound; + } + if candidate_decision_variable < lower_bound { + candidate_decision_variable = lower_bound; + } + + let candidate_food_source = { + let mut original_decision_variables = + food_sources[food_source_index].coordinates.clone(); + original_decision_variables[decision_variable_index] = candidate_decision_variable; + let candidate_decision_variables = original_decision_variables; + FoodSource::new(candidate_decision_variables) + }; + + food_sources[food_source_index].try_counter += 1; + if candidate_food_source.fitness_calculation + > food_sources[food_source_index].fitness_calculation + { + food_sources[food_source_index] = candidate_food_source; + food_sources[food_source_index].try_counter = 0; } } } - -fn send_bee( - food_sources: &mut [FoodSource], - index: usize, - decision_variable_count: usize, - upper_bound: f64, - lower_bound: f64, -) { - let mut different_food_source_index = rand::thread_rng().gen_range(0..food_sources.len()); - while different_food_source_index == index { - different_food_source_index = rand::thread_rng().gen_range(0..food_sources.len()); - } - let selected_coordinate_index = rand::thread_rng().gen_range(0..decision_variable_count); - let randomness = rand::thread_rng().gen_range(-1.0..=1.0); - - let mut candidate_one_index = food_sources[index].coordinates[selected_coordinate_index] - + randomness - * (food_sources[index].coordinates[selected_coordinate_index] - - food_sources[different_food_source_index].coordinates[selected_coordinate_index]); - if candidate_one_index > upper_bound { - candidate_one_index = upper_bound; - } - if candidate_one_index < lower_bound { - candidate_one_index = lower_bound; - } - let mut candidate_coordinates = food_sources[index].coordinates.clone(); - candidate_coordinates[selected_coordinate_index] = candidate_one_index; - let candidate = FoodSource::new(candidate_coordinates); - food_sources[index].try_counter += 1; - if candidate.fitness_calculation > food_sources[index].fitness_calculation { - food_sources[index] = candidate; - food_sources[index].try_counter = 0; - } -} diff --git a/artificial_bee_colony/src/food.rs b/artificial_bee_colony/src/food.rs index 9d8b9bc..05ade6b 100644 --- a/artificial_bee_colony/src/food.rs +++ b/artificial_bee_colony/src/food.rs @@ -40,7 +40,7 @@ impl FoodSource { } pub fn create_food_sources( - food_source_number: u128, + food_source_number: usize, decision_variable_count: usize, upper_bound: f64, lower_bound: f64, @@ -58,13 +58,22 @@ impl FoodSource { food_sources } - pub fn find_best_food_source(food_sources: &Vec) -> FoodSource { + pub fn find_best_food_source(food_sources: &[FoodSource]) -> FoodSource { food_sources .iter() .max_by(|x, y| x.fitness_calculation.total_cmp(&y.fitness_calculation)) .unwrap() .clone() } + + pub fn find_most_tried_food_source_index(food_sources: &[FoodSource]) -> usize { + let (most_tried_food_source_index, _) = food_sources + .iter() + .enumerate() + .max_by(|(_, x), (_, y)| x.try_counter.cmp(&y.try_counter)) + .unwrap(); + most_tried_food_source_index + } } impl fmt::Display for FoodSource { diff --git a/artificial_bee_colony/src/main.rs b/artificial_bee_colony/src/main.rs index de66081..918cc39 100644 --- a/artificial_bee_colony/src/main.rs +++ b/artificial_bee_colony/src/main.rs @@ -10,61 +10,62 @@ fn main() { let mut function_results = vec![]; let mut fitness_results = vec![]; - let mut food_sources = FoodSource::create_food_sources( - input.food_source_number, - input.decision_variable_count, - input.upper_bound, - input.lower_bound, - ); - for run_counter in 0..input.run { + let mut food_sources = FoodSource::create_food_sources( + input.food_source_number, + input.decision_variable_count, + input.upper_bound, + input.lower_bound, + ); let mut best_food_source = FoodSource::find_best_food_source(&food_sources); for _ in 0..input.iteration { - for index in 0..input.food_source_number as usize { + for food_source_index in 0..input.food_source_number { Bee::employed_bee( &mut food_sources, - index, + food_source_index, input.decision_variable_count, input.upper_bound, input.lower_bound, ); } - let total_fitness = food_sources.iter().map(|food_source|food_source.fitness_calculation).sum(); + + let total_fitness = food_sources + .iter() + .map(|food_source| food_source.fitness_calculation) + .sum(); + let onlooker_bee_count = input.food_source_number; let mut last_looked = 0; - for _ in 0..input.food_source_number { - if last_looked >= input.food_source_number { - last_looked = 0; + for _ in 0..onlooker_bee_count { + loop { + if last_looked >= input.food_source_number { + last_looked = 0; + } + if Bee::onlooker_bee( + &mut food_sources, + last_looked, + total_fitness, + input.decision_variable_count, + input.upper_bound, + input.lower_bound, + ) { + break; + } + last_looked += 1; } - } - for index in 0..input.food_source_number as usize { - Bee::onlooker_bee( - &mut food_sources, - index, - total_fitness, - input.decision_variable_count, - input.upper_bound, - input.lower_bound, - ); - } - // önce employed biticek sonra onlooker bakacak ve bakılandan tekrar başla best_food_source = FoodSource::find_best_food_source(&food_sources); - for index in 0..food_sources.len() { - if food_sources[index].try_counter >= input.food_source_try_limit { - // en büyüğü bul sonra limiti geçiyosa kaşif gider - Bee::scout_bee( - &mut food_sources, - index, - input.food_source_try_limit, - input.lower_bound, - input.upper_bound, - input.decision_variable_count, - ); - break; - } - } + let most_tried_food_source_index = + FoodSource::find_most_tried_food_source_index(&food_sources); + Bee::scout_bee( + &mut food_sources, + most_tried_food_source_index, + input.food_source_try_limit, + input.lower_bound, + input.upper_bound, + input.decision_variable_count, + ); } function_results.push(best_food_source.function_calculation); fitness_results.push(best_food_source.fitness_calculation); diff --git a/artificial_bee_colony/src/utils.rs b/artificial_bee_colony/src/utils.rs index a3eb149..88d9602 100644 --- a/artificial_bee_colony/src/utils.rs +++ b/artificial_bee_colony/src/utils.rs @@ -10,7 +10,7 @@ use crate::food::FoodSource; pub struct Input { pub decision_variable_count: usize, - pub food_source_number: u128, + pub food_source_number: usize, pub food_source_try_limit: u128, pub upper_bound: f64, pub lower_bound: f64,