Source code for NiaPy.algorithms.basic.hs

# encoding=utf8
import logging

from numpy import argmax, log, exp, full

from NiaPy.algorithms.algorithm import Algorithm

logging.basicConfig()
logger = logging.getLogger("NiaPy.algorithms.basic")
logger.setLevel("INFO")

__all__ = ["HarmonySearch", "HarmonySearchV1"]


[docs]class HarmonySearch(Algorithm): r"""Implementation of harmony search algorithm. Algorithm: Harmony Search Algorithm Date: 2018 Authors: Klemen Berkovič License: MIT Reference URL: https://link.springer.com/chapter/10.1007/978-3-642-00185-7_1 Reference paper: Geem, Z. W., Kim, J. H., & Loganathan, G. V. (2001). A new heuristic optimization algorithm: harmony search. Simulation, 76(2), 60-68. Attributes: Name (List[str]): List of strings representing algorithm names r_accept (float): Probability of accepting new bandwidth into harmony. r_pa (float): Probability of accepting random bandwidth into harmony. b_range (float): Range of bandwidth. See Also: * :class:`NiaPy.algorithms.algorithm.Algorithm` """ Name = ["HarmonySearch", "HS"]
[docs] @staticmethod def algorithmInfo(): r"""Get basic information about the algorithm. Returns: str: Basic information. """ return r"""Geem, Z. W., Kim, J. H., & Loganathan, G. V. (2001). A new heuristic optimization algorithm: harmony search. Simulation, 76(2), 60-68."""
[docs] @staticmethod def typeParameters(): r"""Get dictionary with functions for checking values of parameters. Returns: Dict[str, Callable]: * HMS (Callable[[int], bool]) * r_accept (Callable[[float], bool]) * r_pa (Callable[[float], bool]) * b_range (Callable[[float], bool]) """ return { "HMS": lambda x: isinstance(x, int) and x > 0, "r_accept": lambda x: isinstance(x, float) and 0 < x < 1, "r_pa": lambda x: isinstance(x, float) and 0 < x < 1, "b_range": lambda x: isinstance(x, (int, float)) and x > 0 }
[docs] def setParameters(self, HMS=30, r_accept=0.7, r_pa=0.35, b_range=1.42, **ukwargs): r"""Set the arguments of the algorithm. Arguments: HMS (Optional[int]): Number of harmony in the memory. r_accept (Optional[float]): Probability of accepting new bandwidth to harmony. r_pa (Optional[float]): Probability of accepting random bandwidth into harmony. b_range (Optional[float]): Bandwidth range. See Also: * :func:`NiaPy.algorithms.algorithm.Algorithm.setParameters` """ ukwargs.pop('NP', None) Algorithm.setParameters(self, NP=HMS, **ukwargs) self.r_accept, self.r_pa, self.b_range = r_accept, r_pa, b_range
[docs] def getParameters(self): d = Algorithm.getParameters(self) d.pop('NP', None) d.update({ 'HMS': self.NP, 'r_accept': self.r_accept, 'r_pa': self.r_pa, 'b_range': self.b_range }) return d
[docs] def bw(self, task): r"""Get bandwidth. Args: task (Task): Optimization task. Returns: float: Bandwidth. """ return self.uniform(-1, 1) * self.b_range
[docs] def adjustment(self, x, task): r"""Adjust value based on bandwidth. Args: x (Union[int, float]): Current position. task (Task): Optimization task. Returns: float: New position. """ return x + self.bw(task)
[docs] def improvize(self, HM, task): r"""Create new individual. Args: HM (numpy.ndarray): Current population. task (Task): Optimization task. Returns: numpy.ndarray: New individual. """ H = full(task.D, .0) for i in range(task.D): r, j = self.rand(), self.randint(self.NP) H[i] = HM[j, i] if r > self.r_accept else self.adjustment(HM[j, i], task) if r > self.r_pa else self.uniform(task.Lower[i], task.Upper[i]) return H
[docs] def initPopulation(self, task): r"""Initialize first population. Args: task (Task): Optimization task. Returns: Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]: 1. New harmony/population. 2. New population fitness/function values. 3. Additional parameters. See Also: * :func:`NiaPy.algorithms.algorithm.Algorithm.initPopulation` """ return Algorithm.initPopulation(self, task)
[docs] def runIteration(self, task, HM, HM_f, xb, fxb, **dparams): r"""Core function of HarmonySearch algorithm. Args: task (Task): Optimization task. HM (numpy.ndarray): Current population. HM_f (numpy.ndarray): Current populations function/fitness values. xb (numpy.ndarray): Global best individual. fxb (float): Global best fitness/function value. **dparams (Dict[str, Any]): Additional arguments. Returns: Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]: 1. New harmony/population. 2. New populations function/fitness values. 3. New global best solution 4. New global best solution fitness/objective value 5. Additional arguments. """ H = self.improvize(HM, task) H_f = task.eval(task.repair(H, self.Rand)) iw = argmax(HM_f) if H_f <= HM_f[iw]: HM[iw], HM_f[iw] = H, H_f xb, fxb = self.getBest(H, H_f, xb, fxb) return HM, HM_f, xb, fxb, {}
[docs]class HarmonySearchV1(HarmonySearch): r"""Implementation of harmony search algorithm. Algorithm: Harmony Search Algorithm Date: 2018 Authors: Klemen Berkovič License: MIT Reference URL: https://link.springer.com/chapter/10.1007/978-3-642-00185-7_1 Reference paper: Yang, Xin-She. "Harmony search as a metaheuristic algorithm." Music-inspired harmony search algorithm. Springer, Berlin, Heidelberg, 2009. 1-14. Attributes: Name (List[str]): List of strings representing algorithm name. bw_min (float): Minimal bandwidth. bw_max (float): Maximal bandwidth. See Also: * :class:`NiaPy.algorithms.basic.hs.HarmonySearch` """ Name = ["HarmonySearchV1", "HSv1"]
[docs] @staticmethod def algorithmInfo(): r"""Get basic information about algorihtm. Returns: str: Basic information. """ return r"""Yang, Xin-She. "Harmony search as a metaheuristic algorithm." Music-inspired harmony search algorithm. Springer, Berlin, Heidelberg, 2009. 1-14."""
[docs] @staticmethod def typeParameters(): r"""Get dictionary with functions for checking values of parameters. Returns: Dict[str, Callable]: Function for testing correctness of parameters. See Also: * :func:`NiaPy.algorithms.basic.HarmonySearch.typeParameters` """ d = HarmonySearch.typeParameters() del d["b_range"] d.update({ "dw_min": lambda x: isinstance(x, (float, int)) and x >= 1, "dw_max": lambda x: isinstance(x, (float, int)) and x >= 1 }) return d
[docs] def setParameters(self, bw_min=1, bw_max=2, **kwargs): r"""Set the parameters of the algorithm. Arguments: bw_min (Optional[float]): Minimal bandwidth bw_max (Optional[float]): Maximal bandwidth kwargs (Dict[str, Any]): Additional arguments. See Also: * :func:`NiaPy.algorithms.basic.hs.HarmonySearch.setParameters` """ HarmonySearch.setParameters(self, **kwargs) self.bw_min, self.bw_max = bw_min, bw_max
[docs] def getParameters(self): d = HarmonySearch.getParameters(self) d.update({ 'bw_min': self.bw_min, 'bw_max': self.bw_max }) return d
[docs] def bw(self, task): r"""Get new bandwidth. Args: task (Task): Optimization task. Returns: float: New bandwidth. """ return self.bw_min * exp(log(self.bw_min / self.bw_max) * task.Iters / task.nGEN)
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3