Source code for mealpy.swarm_based.FHO

#!/usr/bin/env python
# Created by "Thieu" at 21:16, 26/10/2022 ----------%                                                                               
#       Email: nguyenthieu2102@gmail.com            %                                                    
#       Github: https://github.com/thieu1995        %                         
# --------------------------------------------------%

import numpy as np
from mealpy.optimizer import Optimizer
from mealpy.utils.opt_info import OptInfo, ScientificConcern


[docs]class OriginalFHO(Optimizer): """ The original version of: Fire Hawk Optimization (FHO) Parameters ---------- epoch : int Maximum number of iterations, default = 10000. pop_size : int Number of population size, default = 100. Note ~~~~ 1. There are discrepancies between the author's MATLAB code and the paper. 2. This Python version strictly follows what is written in the paper. Links ----- 1. https://doi.org/10.1007/s10462-022-10173-w 2. https://www.mathworks.com/matlabcentral/fileexchange/114325-fire-hawk-optimizer-fho-a-novel-metaheuristic-algorithm References ~~~~~~~~~~ 1. Azizi, M., Talatahari, S., & Gandomi, A. H. (2022). Fire Hawk Optimizer: a novel metaheuristic algorithm. Artificial Intelligence Review, 1-77. Examples ~~~~~~~~ >>> import numpy as np >>> from mealpy import FloatVar, FHO >>> >>> def objective_function(solution): >>> return np.sum(solution**2) >>> >>> problem_dict = { >>> "bounds": FloatVar(lb=(-10.,) * 30, ub=(10.,) * 30, name="delta"), >>> "minmax": "min", >>> "obj_func": objective_function >>> } >>> >>> model = FHO.OriginalFHO(epoch=1000, pop_size=50) >>> g_best = model.solve(problem_dict) >>> print(f"Solution: {g_best.solution}, Fitness: {g_best.target.fitness}") """ OPT_INFO = OptInfo(name="Fire Hawk Optimization", year=2022, difficulty="medium", kind="original", scientific_status="questionable", concerns=( ScientificConcern.FABRICATED_RESULTS, ScientificConcern.CODE_PSEUDOCODE_MISMATCH, ScientificConcern.AMBIGUOUS_METHODOLOGY, ScientificConcern.POOR_REPRODUCIBILITY )) def __init__(self, epoch: int = 10000, pop_size: int = 100, **kwargs: object) -> None: 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 evolve(self, epoch: int): """ The main operations (equations) of algorithm. Inherit from Optimizer class Args: epoch (int): The current iteration """ # Generate random integer for the number of Fire Hawks (n) n = self.generator.integers(1, self.pop_size // 5 + 1) m = self.pop_size - n # Number of Preys (PR) # Sort candidates to determine Fire Hawks (best) and Preys (rest) _, sorted_indices = self.get_sorted_population(self.pop, self.problem.minmax) pos_list = np.array([agent.solution for agent in self.pop]) FH = pos_list[sorted_indices[:n]] PR = pos_list[sorted_indices[n:]] new_FH = np.zeros_like(FH) new_PR = np.zeros_like(PR) # Eq. 5: Calculate total distance between Fire Hawks and Preys # dist matrix shape: (n, m) dist = np.linalg.norm(FH[:, np.newaxis, :] - PR[np.newaxis, :, :], axis=2) # Determine territory by assigning preys to the nearest Fire Hawk territory_assignments = np.argmin(dist, axis=0) # Update Fire Hawks' positions for idx in range(n): r1, r2 = self.generator.random(2) # Select another Fire Hawk randomly available_fh = [jdx for jdx in range(n) if jdx != idx] jdx = self.generator.choice(available_fh) if available_fh else idx # Eq. 6: New position of Fire Hawks new_FH[idx] = FH[idx] + (r1 * self.g_best.solution - r2 * FH[jdx]) # Calculate safe place outside all territories (Eq. 10) SP_global = np.mean(PR, axis=0) if m > 0 else np.zeros(self.problem.n_dims) # Update Preys' positions for idx in range(m): l = territory_assignments[idx] r3, r4, r5, r6 = self.generator.random(4) # Eq. 9: Calculate safe place under l-th Fire Hawk territory preys_in_territory = PR[territory_assignments == l] SP_l = np.mean(preys_in_territory, axis=0) if len(preys_in_territory) > 0 else PR[idx] # Eq. 7: Update position inside the territory PR_temp = PR[idx] + (r3 * FH[l] - r4 * SP_l) # Select an alternative Fire Hawk available_fh = [jdx for jdx in range(n) if jdx != l] jdx = self.generator.choice(available_fh) if available_fh else l # Eq. 8: Update position outside the territory new_PR[idx] = PR_temp + (r5 * FH[jdx] - r6 * SP_global) # Merge new populations and enforce boundary constraints new_X = np.vstack((new_FH, new_PR)) pop_new = [] for idx in range(self.pop_size): pos_new = self.correct_solution(new_X[idx]) pop_new.append(self.generate_empty_agent(pos_new)) if self.mode not in self.AVAILABLE_MODES: pop_new[-1].target = self.get_target(pos_new) # Evaluate fitness in parallel if self.mode in self.AVAILABLE_MODES: pop_new = self.update_target_for_population(pop_new) # Update population self.pop = pop_new