Source code for niapy.algorithms.basic.hho

# encoding=utf8
import logging

import numpy as np

from niapy.algorithms.algorithm import Algorithm
from niapy.util import levy_flight

logging.basicConfig()
logger = logging.getLogger('niapy.algorithms.basic')
logger.setLevel('INFO')

__all__ = ['HarrisHawksOptimization']


[docs]class HarrisHawksOptimization(Algorithm): r"""Implementation of Harris Hawks Optimization algorithm. Algorithm: Harris Hawks Optimization Date: 2020 Authors: Francisco Jose Solis-Munoz License: MIT Reference paper: Heidari et al. "Harris hawks optimization: Algorithm and applications". Future Generation Computer Systems. 2019. Vol. 97. 849-872. Attributes: Name (List[str]): List of strings representing algorithm name. levy (float): Levy factor. See Also: * :class:`niapy.algorithms.Algorithm` """ Name = ['HarrisHawksOptimization', 'HHO']
[docs] def __init__(self, population_size=40, levy=0.01, *args, **kwargs): """Initialize HarrisHawksOptimization. Args: population_size (Optional[int]): Population size. levy (Optional[float]): Levy factor. """ super().__init__(population_size, *args, **kwargs) self.levy = levy
[docs] @staticmethod def info(): r"""Get algorithms information. Returns: str: Algorithm information. See Also: * :func:`niapy.algorithms.Algorithm.info` """ return r"""Heidari et al. "Harris hawks optimization: Algorithm and applications". Future Generation Computer Systems. 2019. Vol. 97. 849-872."""
[docs] def set_parameters(self, population_size=40, levy=0.01, **kwargs): r"""Set the parameters of the algorithm. Args: population_size (Optional[int]): Population size. levy (Optional[float]): Levy factor. See Also: * :func:`niapy.algorithms.Algorithm.set_parameters` """ super().set_parameters(population_size=population_size, **kwargs) self.levy = levy
[docs] def get_parameters(self): r"""Get parameters of the algorithm. Returns: Dict[str, Any]: Algorithm parameters. """ d = super().get_parameters() d.update({ 'levy': self.levy }) return d
[docs] def run_iteration(self, task, population, population_fitness, best_x, best_fitness, **params): r"""Core function of Harris Hawks Optimization. Args: task (Task): Optimization task. population (numpy.ndarray): Current population population_fitness (numpy.ndarray[float]): Current population fitness/function values best_x (numpy.ndarray): Current best individual best_fitness (float): Current best individual function/fitness value params (Dict[str, Any]): Additional algorithm arguments Returns: Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]: 1. New population 2. New population fitness/function values 3. New global best solution 4. New global best fitness/objective value """ # Decreasing energy factor decreasing_energy_factor = 2 * (1 - (task.iters + 1) / task.max_iters) mean_sol = np.mean(population) # Update population for i in range(self.population_size): jumping_energy = self.rng.uniform(0, 2) decreasing_energy_random = self.rng.uniform(-1, 1) escaping_energy = decreasing_energy_factor * decreasing_energy_random escaping_energy_abs = np.abs(escaping_energy) random_number = self.rng.random() if escaping_energy >= 1 and random_number >= 0.5: # 0. Exploration: Random tall tree rhi = self.rng.integers(self.population_size) random_agent = population[rhi] population[i] = random_agent - self.rng.random() * np.abs(random_agent - 2 * self.rng.random() * population[i]) elif escaping_energy_abs >= 1 and random_number < 0.5: # 1. Exploration: Family members mean population[i] = (best_x - mean_sol) - self.rng.random() * self.rng.uniform(task.lower, task.upper) elif escaping_energy_abs >= 0.5 and random_number >= 0.5: # 2. Exploitation: Soft besiege population[i] = \ (best_x - population[i]) - \ escaping_energy * \ np.abs(jumping_energy * best_x - population[i]) elif escaping_energy_abs < 0.5 <= random_number: # 3. Exploitation: Hard besiege population[i] = \ best_x - \ escaping_energy * \ np.abs(best_x - population[i]) elif escaping_energy_abs >= 0.5 > random_number: # 4. Exploitation: Soft besiege with progressive rapid dives cand1 = task.repair(best_x - escaping_energy * np.abs(jumping_energy * best_x - population[i]), rng=self.rng) random_vector = self.rng.random(task.dimension) cand2 = task.repair(cand1 + random_vector * levy_flight(alpha=self.levy, size=task.dimension, rng=self.rng), rng=self.rng) if task.eval(cand1) < population_fitness[i]: population[i] = cand1 elif task.eval(cand2) < population_fitness[i]: population[i] = cand2 elif escaping_energy_abs < 0.5 and random_number < 0.5: # 5. Exploitation: Hard besiege with progressive rapid dives cand1 = task.repair(best_x - escaping_energy * np.abs(jumping_energy * best_x - mean_sol), rng=self.rng) random_vector = self.rng.random(task.dimension) cand2 = task.repair(cand1 + random_vector * levy_flight(alpha=self.levy, size=task.dimension, rng=self.rng), rng=self.rng) if task.eval(cand1) < population_fitness[i]: population[i] = cand1 elif task.eval(cand2) < population_fitness[i]: population[i] = cand2 # Repair agent (from population) values population[i] = task.repair(population[i], rng=self.rng) # Eval population population_fitness[i] = task.eval(population[i]) # Get best of population best_index = np.argmin(population_fitness) xb_cand = population[best_index].copy() fxb_cand = population_fitness[best_index].copy() if fxb_cand < best_fitness: best_fitness = fxb_cand best_x = xb_cand.copy() return population, population_fitness, best_x, best_fitness, {}