From f0675e4bdf65212e0ee9cf4e853a1056e605eb5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ahmet=20Kaan=20G=C3=9CM=C3=9C=C5=9E?= <96421894+Tahinli@users.noreply.github.com> Date: Wed, 20 Nov 2024 00:20:40 +0300 Subject: [PATCH] refactor: :recycle: bee, food --- artificial_bee_colony/src/bee.rs | 65 ++++++++++++ artificial_bee_colony/src/food.rs | 57 ++++++++++ artificial_bee_colony/src/lib.rs | 48 +++++++++ artificial_bee_colony/src/main.rs | 166 +----------------------------- 4 files changed, 174 insertions(+), 162 deletions(-) create mode 100644 artificial_bee_colony/src/bee.rs create mode 100644 artificial_bee_colony/src/food.rs create mode 100644 artificial_bee_colony/src/lib.rs diff --git a/artificial_bee_colony/src/bee.rs b/artificial_bee_colony/src/bee.rs new file mode 100644 index 0000000..7aae79c --- /dev/null +++ b/artificial_bee_colony/src/bee.rs @@ -0,0 +1,65 @@ +use rand::Rng; + +use crate::food::FoodSource; + +pub enum Bee {} +impl Bee { + pub fn worker_bee( + food_sources: &mut [FoodSource], + index: usize, + decision_variable_count: usize, + ) { + 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 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]); + let mut candidate_coordinates = food_sources[index].coordinates.clone(); + candidate_coordinates[selected_coordinate_index] = candidate_one_index; + let candidate = FoodSource::get(candidate_coordinates); + food_sources[index].try_counter += 1; + if candidate.fitness > food_sources[index].fitness { + food_sources[index] = candidate; + food_sources[index].try_counter = 0; + } + } + + pub fn onlooker_bee( + food_sources: &mut [FoodSource], + index: usize, + total_fitness: f64, + decision_variable_count: usize, + ) { + let fitness_for_index = food_sources[index].fitness; + if fitness_for_index / total_fitness <= rand::thread_rng().gen_range(0.0..=1.0) { + Self::worker_bee(food_sources, index, decision_variable_count); + } + } + + pub fn scout_bee( + food_sources: &mut [FoodSource], + most_tried_index: usize, + limit: u128, + lower_bound: f64, + upper_bound: f64, + decision_variable_count: usize, + ) { + if food_sources[most_tried_index].try_counter > limit { + let mut coordinates_for_new = vec![]; + for _ in 0..decision_variable_count { + let random = lower_bound + + rand::thread_rng().gen_range(0.0..=1.0) * (upper_bound - lower_bound); + coordinates_for_new.push(random); + } + let new_food_source = FoodSource::get(coordinates_for_new); + food_sources[most_tried_index] = new_food_source; + } + } +} diff --git a/artificial_bee_colony/src/food.rs b/artificial_bee_colony/src/food.rs new file mode 100644 index 0000000..96b6768 --- /dev/null +++ b/artificial_bee_colony/src/food.rs @@ -0,0 +1,57 @@ +use rand::Rng; + +#[derive(Debug, Clone)] +pub struct FoodSource { + pub fitness: f64, + pub coordinates: Vec, + pub try_counter: u128, +} + +impl FoodSource { + pub fn get(coordinates: Vec) -> Self { + let mut food_source = FoodSource { + fitness: 0.0, + coordinates, + try_counter: 0, + }; + if !food_source.coordinates.is_empty() { + food_source.fitness_function(); + } + food_source + } + fn fitness_function(&mut self) { + let calculation = Self::calculate(self.coordinates.clone()); + if calculation >= 0.0 { + self.fitness = 1.0 / (1.0 + calculation); + } else { + self.fitness = 1.0 + calculation.abs(); + } + } + + fn calculate(decision_variables: Vec) -> f64 { + let mut result = 0.0; + for element in decision_variables { + result += element * element; + } + result + } + + pub fn create_food_sources( + food_source_number: u128, + decision_variable_count: usize, + upper_bound: f64, + lower_bound: f64, + ) -> Vec { + let mut food_sources = vec![]; + + for _ in 0..food_source_number { + let mut coordinates = vec![]; + for _ in 0..decision_variable_count { + let random = rand::thread_rng().gen_range(lower_bound..=upper_bound); + coordinates.push(random); + } + food_sources.push(FoodSource::get(coordinates)); + } + food_sources + } +} diff --git a/artificial_bee_colony/src/lib.rs b/artificial_bee_colony/src/lib.rs new file mode 100644 index 0000000..498436f --- /dev/null +++ b/artificial_bee_colony/src/lib.rs @@ -0,0 +1,48 @@ +use std::io; + +pub mod bee; +pub mod food; + +pub struct Input { + pub decision_variable_count: usize, + pub food_source_number: u128, + pub food_source_try_limit: u128, + pub upper_bound: f64, + pub lower_bound: f64, + pub iteration: usize, +} +impl Input { + pub fn get() -> Self { + println!("Decision Variable Count"); + let decision_variable_count = Self::get_input().parse().unwrap(); + + println!("Food Source Number"); + let food_source_number = Self::get_input().parse().unwrap(); + + println!("Food Source Try Limit"); + let food_source_try_limit = Self::get_input().parse().unwrap(); + + println!("Upper Bound"); + let upper_bound = Self::get_input().parse().unwrap(); + + println!("Lower Bound"); + let lower_bound = Self::get_input().parse().unwrap(); + + println!("Iteration"); + let iteration = Self::get_input().parse().unwrap(); + + Input { + decision_variable_count, + food_source_number, + food_source_try_limit, + upper_bound, + lower_bound, + iteration, + } + } + fn get_input() -> String { + let mut input = String::new(); + io::stdin().read_line(&mut input).unwrap(); + input.trim().to_string() + } +} diff --git a/artificial_bee_colony/src/main.rs b/artificial_bee_colony/src/main.rs index 2548c9f..1d693aa 100644 --- a/artificial_bee_colony/src/main.rs +++ b/artificial_bee_colony/src/main.rs @@ -1,162 +1,4 @@ -use std::io; - -use rand::Rng; - -#[derive(Debug, Clone)] -struct FoodSource { - fitness: f64, - coordinates: Vec, - try_counter: u128, -} - -impl FoodSource { - fn get(coordinates: Vec) -> Self { - let mut food_source = FoodSource { - fitness: 0.0, - coordinates, - try_counter: 0, - }; - if !food_source.coordinates.is_empty() { - food_source.fitness_function(); - } - food_source - } - fn fitness_function(&mut self) { - let calculation = Self::calculate(self.coordinates.clone()); - if calculation >= 0.0 { - self.fitness = 1.0 / (1.0 + calculation); - } else { - self.fitness = 1.0 + calculation.abs(); - } - } - - fn calculate(decision_variables: Vec) -> f64 { - let mut result = 0.0; - for element in decision_variables { - result += element * element; - } - result - } - - fn create_food_sources( - food_source_number: u128, - decision_variable_count: usize, - upper_bound: f64, - lower_bound: f64, - ) -> Vec { - let mut food_sources = vec![]; - - for _ in 0..food_source_number { - let mut coordinates = vec![]; - for _ in 0..decision_variable_count { - let random = rand::thread_rng().gen_range(lower_bound..=upper_bound); - coordinates.push(random); - } - food_sources.push(FoodSource::get(coordinates)); - } - food_sources - } -} -enum Bee {} -impl Bee { - fn worker_bee(food_sources: &mut [FoodSource], index: usize, decision_variable_count: usize) { - 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 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]); - let mut candidate_coordinates = food_sources[index].coordinates.clone(); - candidate_coordinates[selected_coordinate_index] = candidate_one_index; - let candidate = FoodSource::get(candidate_coordinates); - food_sources[index].try_counter += 1; - if candidate.fitness > food_sources[index].fitness { - food_sources[index] = candidate; - food_sources[index].try_counter = 0; - } - } - - fn onlooker_bee( - food_sources: &mut [FoodSource], - index: usize, - total_fitness: f64, - decision_variable_count: usize, - ) { - let fitness_for_index = food_sources[index].fitness; - if fitness_for_index / total_fitness <= rand::thread_rng().gen_range(0.0..=1.0) { - Self::worker_bee(food_sources, index, decision_variable_count); - } - } - - fn scout_bee( - food_sources: &mut [FoodSource], - most_tried_index: usize, - limit: u128, - lower_bound: f64, - upper_bound: f64, - decision_variable_count: usize, - ) { - if food_sources[most_tried_index].try_counter > limit { - let mut coordinates_for_new = vec![]; - for _ in 0..decision_variable_count { - let random = lower_bound - + rand::thread_rng().gen_range(0.0..=1.0) * (upper_bound - lower_bound); - coordinates_for_new.push(random); - } - let new_food_source = FoodSource::get(coordinates_for_new); - food_sources[most_tried_index] = new_food_source; - } - } -} -struct Input { - decision_variable_count: usize, - food_source_number: u128, - food_source_try_limit: u128, - upper_bound: f64, - lower_bound: f64, - iteration: usize, -} -impl Input { - fn get() -> Self { - println!("Decision Variable Count"); - let decision_variable_count = Self::get_input().parse().unwrap(); - - println!("Food Source Number"); - let food_source_number = Self::get_input().parse().unwrap(); - - println!("Food Source Try Limit"); - let food_source_try_limit = Self::get_input().parse().unwrap(); - - println!("Upper Bound"); - let upper_bound = Self::get_input().parse().unwrap(); - - println!("Lower Bound"); - let lower_bound = Self::get_input().parse().unwrap(); - - println!("Iteration"); - let iteration = Self::get_input().parse().unwrap(); - - Input { - decision_variable_count, - food_source_number, - food_source_try_limit, - upper_bound, - lower_bound, - iteration, - } - } - fn get_input() -> String { - let mut input = String::new(); - io::stdin().read_line(&mut input).unwrap(); - input.trim().to_string() - } -} +use artificial_bee_colony::{bee::Bee, food::FoodSource, Input}; fn main() { println!("Hello, world!"); @@ -176,15 +18,15 @@ fn main() { } } for _ in 0..input.iteration { - for i in 0..input.food_source_number as usize { - Bee::worker_bee(&mut food_sources, i, input.decision_variable_count); + for index in 0..input.food_source_number as usize { + Bee::worker_bee(&mut food_sources, index, input.decision_variable_count); let mut total_fitness = 0.0; for food_source in &food_sources { total_fitness += food_source.fitness; } Bee::onlooker_bee( &mut food_sources, - i, + index, total_fitness, input.decision_variable_count, );