Source code for mealpy.swarm_based.FOA

#!/usr/bin/env python
# Created by "Thieu" at 14:01, 16/11/2020 ----------%
#       Email: nguyenthieu2102@gmail.com            %
#       Github: https://github.com/thieu1995        %
# --------------------------------------------------%

import numpy as np
from mealpy.optimizer import Optimizer
from mealpy.utils.agent import Agent


[docs]class OriginalFOA(Optimizer): """ The original version of: Fruit-fly Optimization Algorithm (FOA) Links: 1. https://doi.org/10.1016/j.knosys.2011.07.001 Examples ~~~~~~~~ >>> import numpy as np >>> from mealpy import FloatVar, FOA >>> >>> def objective_function(solution): >>> return np.sum(solution**2) >>> >>> problem_dict = { >>> "bounds": FloatVar(n_vars=30, lb=(-10.,) * 30, ub=(10.,) * 30, name="delta"), >>> "minmax": "min", >>> "obj_func": objective_function >>> } >>> >>> model = FOA.OriginalFOA(epoch=1000, pop_size=50) >>> g_best = model.solve(problem_dict) >>> print(f"Solution: {g_best.solution}, Fitness: {g_best.target.fitness}") >>> print(f"Solution: {model.g_best.solution}, Fitness: {model.g_best.target.fitness}") References ~~~~~~~~~~ [1] Pan, W.T., 2012. A new fruit fly optimization algorithm: taking the financial distress model as an example. Knowledge-Based Systems, 26, pp.69-74. """ def __init__(self, epoch: int = 10000, pop_size: int = 100, **kwargs: object) -> None: """ Args: epoch (int): maximum number of iterations, default = 10000 pop_size (int): number of population size, default = 100 """ super().__init__(**kwargs) self.epoch = self.validator.check_int("epoch", epoch, [1, 100000]) self.pop_size = self.validator.check_int("pop_size", pop_size, [5, 10000]) self.set_parameters(["epoch", "pop_size"]) self.sort_flag = False
[docs] def norm_consecutive_adjacent__(self, position=None): return np.array([np.linalg.norm([position[x], position[x + 1]]) for x in range(0, self.problem.n_dims - 1)] + \ [np.linalg.norm([position[-1], position[0]])])
[docs] def generate_empty_agent(self, solution: np.ndarray = None) -> Agent: if solution is None: solution = self.problem.generate_solution(encoded=True) solution = self.norm_consecutive_adjacent__(solution) return Agent(solution=solution)
[docs] def evolve(self, epoch): """ The main operations (equations) of algorithm. Inherit from Optimizer class Args: epoch (int): The current iteration """ pop_new = [] for idx in range(0, self.pop_size): pos_new = self.pop[idx].solution + self.generator.random() * self.generator.normal(self.problem.lb, self.problem.ub) pos_new = self.norm_consecutive_adjacent__(pos_new) pos_new = self.correct_solution(pos_new) agent = self.generate_empty_agent(pos_new) pop_new.append(agent) if self.mode not in self.AVAILABLE_MODES: agent.target = self.get_target(pos_new) self.pop[idx] = self.get_better_agent(agent, self.pop[idx], self.problem.minmax) if self.mode in self.AVAILABLE_MODES: pop_new = self.update_target_for_population(pop_new) self.pop = self.greedy_selection_population(pop_new, self.pop, self.problem.minmax)
[docs]class DevFOA(OriginalFOA): """ The developed version: Fruit-fly Optimization Algorithm (FOA) Notes: + The fitness function (small function) is changed by taking the distance each 2 adjacent dimensions + Update the position if only new generated solution is better + The updated position is created by norm distance * gaussian random number Examples ~~~~~~~~ >>> import numpy as np >>> from mealpy import FloatVar, FOA >>> >>> def objective_function(solution): >>> return np.sum(solution**2) >>> >>> problem_dict = { >>> "bounds": FloatVar(n_vars=30, lb=(-10.,) * 30, ub=(10.,) * 30, name="delta"), >>> "minmax": "min", >>> "obj_func": objective_function >>> } >>> >>> model = FOA.DevFOA(epoch=1000, pop_size=50) >>> g_best = model.solve(problem_dict) >>> print(f"Solution: {g_best.solution}, Fitness: {g_best.target.fitness}") >>> print(f"Solution: {model.g_best.solution}, Fitness: {model.g_best.target.fitness}") """ def __init__(self, epoch: int = 10000, pop_size: int = 100, **kwargs: object) -> None: """ Args: epoch (int): maximum number of iterations, default = 10000 pop_size (int): number of population size, default = 100 """ super().__init__(epoch, pop_size, **kwargs)
[docs] def evolve(self, epoch): """ The main operations (equations) of algorithm. Inherit from Optimizer class Args: epoch (int): The current iteration """ c = 1 - epoch / self.epoch pop_new = [] for idx in range(0, self.pop_size): pos_new = self.pop[idx].solution + self.generator.normal(self.problem.lb, self.problem.ub) pos_new = c * self.generator.random() * self.norm_consecutive_adjacent__(pos_new) pos_new = self.correct_solution(pos_new) agent = self.generate_empty_agent(pos_new) pop_new.append(agent) if self.mode not in self.AVAILABLE_MODES: agent.target = self.get_target(pos_new) self.pop[idx] = self.get_better_agent(agent, self.pop[idx], self.problem.minmax) if self.mode in self.AVAILABLE_MODES: pop_new = self.update_target_for_population(pop_new) self.pop = self.greedy_selection_population(pop_new, self.pop, self.problem.minmax)
[docs]class WhaleFOA(OriginalFOA): """ The original version of: Whale Fruit-fly Optimization Algorithm (WFOA) Links: 1. https://doi.org/10.1016/j.eswa.2020.113502 Examples ~~~~~~~~ >>> import numpy as np >>> from mealpy import FloatVar, FOA >>> >>> def objective_function(solution): >>> return np.sum(solution**2) >>> >>> problem_dict = { >>> "bounds": FloatVar(n_vars=30, lb=(-10.,) * 30, ub=(10.,) * 30, name="delta"), >>> "minmax": "min", >>> "obj_func": objective_function >>> } >>> >>> model = FOA.WhaleFOA(epoch=1000, pop_size=50) >>> g_best = model.solve(problem_dict) >>> print(f"Solution: {g_best.solution}, Fitness: {g_best.target.fitness}") >>> print(f"Solution: {model.g_best.solution}, Fitness: {model.g_best.target.fitness}") References ~~~~~~~~~~ [1] Fan, Y., Wang, P., Heidari, A.A., Wang, M., Zhao, X., Chen, H. and Li, C., 2020. Boosted hunting-based fruit fly optimization and advances in real-world problems. Expert Systems with Applications, 159, p.113502. """ def __init__(self, epoch: int = 10000, pop_size: int = 100, **kwargs: object) -> None: """ Args: epoch (int): maximum number of iterations, default = 10000 pop_size (int): number of population size, default = 100 """ super().__init__(epoch, pop_size, **kwargs)
[docs] def evolve(self, epoch): """ The main operations (equations) of algorithm. Inherit from Optimizer class Args: epoch (int): The current iteration """ a = 2. - 2. * epoch / self.epoch # linearly decreased from 2 to 0 pop_new = [] for idx in range(0, self.pop_size): r = self.generator.random() A = 2 * a * r - a C = 2 * r l = self.generator.uniform(-1, 1) p = 0.5 b = 1 if self.generator.random() < p: if np.abs(A) < 1: D = np.abs(C * self.g_best.solution - self.pop[idx].solution) pos_new = self.g_best.solution - A * D else: # select random 1 position in pop x_rand = self.pop[self.generator.integers(self.pop_size)] D = np.abs(C * x_rand.solution - self.pop[idx].solution) pos_new = (x_rand.solution - A * D) else: D1 = np.abs(self.g_best.solution - self.pop[idx].solution) pos_new = D1 * np.exp(b * l) * np.cos(2 * np.pi * l) + self.g_best.solution smell = self.norm_consecutive_adjacent__(pos_new) pos_new = self.correct_solution(smell) agent = self.generate_empty_agent(pos_new) pop_new.append(agent) if self.mode not in self.AVAILABLE_MODES: agent.target = self.get_target(pos_new) self.pop[idx] = self.get_better_agent(agent, self.pop[idx], self.problem.minmax) if self.mode in self.AVAILABLE_MODES: pop_new = self.update_target_for_population(pop_new) self.pop = self.greedy_selection_population(pop_new, self.pop, self.problem.minmax)