Source code for NiaPy.algorithms.basic.mke

# encoding=utf8
import logging
from math import ceil

from numpy import apply_along_axis, vectorize, argmin, argmax, full, tril, asarray

from NiaPy.algorithms.algorithm import Algorithm, Individual, defaultIndividualInit, defaultNumPyInit

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

__all__ = ['MonkeyKingEvolutionV1', 'MonkeyKingEvolutionV2', 'MonkeyKingEvolutionV3']

class MkeSolution(Individual):
	r"""Implementation of Monkey King Evolution individual.

	Data:
		2018

	Authors:
		Klemen Berkovič

	License:
		MIT

	Attributes:
		x_pb (array of (float or int)): Personal best position of Monkey particle.
		f_pb (float): Personal best fitness/function value.
		MonkeyKing (bool): Boolean value indicating if particle is Monkey King particle.

	See Also:
		* :class:`NiaPy.algorithms.Individual`
	"""
	def __init__(self, **kwargs):
		r"""Initialize Monkey particle.

		Args:
			**kwargs: Additional arguments

		See Also:
			* :class:`NiaPy.algorithms.Individual.__init__()`
		"""
		Individual.__init__(self, **kwargs)
		self.f_pb, self.x_pb = self.f, self.x
		self.MonkeyKing = False

	def uPersonalBest(self):
		r"""Update presonal best position of particle."""
		if self.f < self.f_pb: self.x_pb, self.f_pb = self.x, self.f

[docs]class MonkeyKingEvolutionV1(Algorithm): r"""Implementation of monkey king evolution algorithm version 1. Algorithm: Monkey King Evolution version 1 Date: 2018 Authors: Klemen Berkovič License: MIT Reference URL: https://www.sciencedirect.com/science/article/pii/S0950705116000198 Reference paper: Zhenyu Meng, Jeng-Shyang Pan, Monkey King Evolution: A new memetic evolutionary algorithm and its application in vehicle fuel consumption optimization, Knowledge-Based Systems, Volume 97, 2016, Pages 144-157, ISSN 0950-7051, https://doi.org/10.1016/j.knosys.2016.01.009. Attributes: Name (List[str]): List of strings representing algorithm names. F (float): Scale factor for normal particles. R (float): Procentual value of now many new particle Monkey King particle creates. C (int): Number of new particles generated by Monkey King particle. FC (float): Scale factor for Monkey King particles. See Also: * :class:`NiaPy.algorithms.algorithm.Algorithm` """ Name = ['MonkeyKingEvolutionV1', 'MKEv1']
[docs] @staticmethod def algorithmInfo(): r"""Get basic information of algorithm. Returns: str: Basic information. See Also: * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` """ return r"""Zhenyu Meng, Jeng-Shyang Pan, Monkey King Evolution: A new memetic evolutionary algorithm and its application in vehicle fuel consumption optimization, Knowledge-Based Systems, Volume 97, 2016, Pages 144-157, ISSN 0950-7051, https://doi.org/10.1016/j.knosys.2016.01.009."""
[docs] @staticmethod def typeParameters(): r"""Get dictionary with functions for checking values of parameters. Returns: Dict[str, Callable]: * F (Callable[[int], bool]) * R (Callable[[Union[int, float]], bool]) * C (Callable[[Union[int, float]], bool]) * FC (Callable[[Union[int, float]], bool]) """ d = Algorithm.typeParameters() d.update({ 'NP': lambda x: isinstance(x, int) and x > 0, 'F': lambda x: isinstance(x, (float, int)) and x > 0, 'R': lambda x: isinstance(x, (float, int)) and x > 0, 'C': lambda x: isinstance(x, int) and x > 0, 'FC': lambda x: isinstance(x, (float, int)) and x > 0 }) return d
[docs] def setParameters(self, NP=40, F=0.7, R=0.3, C=3, FC=0.5, **ukwargs): r"""Set Monkey King Evolution v1 algorithms static parameters. Args: NP (int): Population size. F (float): Scale factor for normal particle. R (float): Procentual value of now many new particle Monkey King particle creates. Value in rage [0, 1]. C (int): Number of new particles generated by Monkey King particle. FC (float): Scale factor for Monkey King particles. **ukwargs (Dict[str, Any]): Additional arguments. See Also: * :func:`NiaPy.algorithms.algorithm.Algorithm.setParameters` """ Algorithm.setParameters(self, NP=NP, itype=ukwargs.pop('itype', MkeSolution), InitPopFunc=ukwargs.pop('InitPopFunc', defaultIndividualInit), **ukwargs) self.F, self.R, self.C, self.FC = F, R, C, FC
[docs] def getParameters(self): r"""Get algorithms parametes values. Returns: Dict[str, Any] See Also: * :func:`NiaPy.algorithms.Algorithm.getParameters` """ d = Algorithm.getParameters(self) d.update({ 'F': self.F, 'R': self.R, 'C': self.C, 'FC': self.FC }) return d
[docs] def moveP(self, x, x_pb, x_b, task): r"""Move normal particle in search space. For moving particles algorithm uses next formula: :math:`\mathbf{x_{pb} - \mathit{F} \odot \mathbf{r} \odot (\mathbf{x_b} - \mathbf{x})` where :math:`\mathbf{r}` is one dimension array with `D` components. Components in this vector are in range [0, 1]. Args: x (numpy.ndarray): Paticle position. x_pb (numpy.ndarray): Particle best position. x_b (numpy.ndarray): Best particle position. task (Task): Optimization task. Returns: numpy.ndarray: Particle new position. """ return x_pb + self.F * self.rand(task.D) * (x_b - x)
[docs] def moveMK(self, x, task): r"""Move Mokey King paticle. For moving Monkey King particles algorithm uses next formula: :math:`\mathbf{x} + \mathit{FC} \odot \mathbf{R} \odot \mathbf{x}` where :math:`\mathbf{R}` is two dimensional array with shape `{C * D, D}`. Componentes of this array are in range [0, 1] Args: x (numpy.ndarray): Monkey King patricle position. task (Task): Optimization task. Returns: numpy.ndarray: New particles generated by Monkey King particle. """ return x + self.FC * self.rand([int(self.C * task.D), task.D]) * x
[docs] def movePartice(self, p, p_b, task): r"""Move patricles. Args: p (MkeSolution): Monke particle. p_b (MkeSolution): Population best particle. task (Task): Optimization task. """ p.x = self.moveP(p.x, p.x_pb, p_b, task) p.evaluate(task, rnd=self.Rand)
[docs] def moveMokeyKingPartice(self, p, task): r"""Move Monky King Particles. Args: p (MkeSolution): Monkey King particle to apply this function on. task (Task): Optimization task. """ p.MonkeyKing = False A = apply_along_axis(task.repair, 1, self.moveMK(p.x, task), self.Rand) A_f = apply_along_axis(task.eval, 1, A) ib = argmin(A_f) p.x, p.f = A[ib], A_f[ib]
[docs] def movePopulation(self, pop, xb, task): r"""Move population. Args: pop (numpy.ndarray[MkeSolution]): Current population. xb (MkeSolution): Current best solution. task (Task): Optimization task. Returns: numpy.ndarray[MkeSolution]: New particles. """ for p in pop: if p.MonkeyKing: self.moveMokeyKingPartice(p, task) else: self.movePartice(p, xb, task) p.uPersonalBest() return pop
[docs] def initPopulation(self, task): r"""Init population. Args: task (Task): Optimization task Returns: Tuple(numpy.ndarray[MkeSolution], numpy.ndarray[float], Dict[str, Any]]: 1. Initialized solutions 2. Fitness/function values of solution 3. Additional arguments """ pop, fpop, _ = Algorithm.initPopulation(self, task) for i in self.Rand.choice(self.NP, int(self.R * len(pop)), replace=False): pop[i].MonkeyKing = True return pop, fpop, {}
[docs] def runIteration(self, task, pop, fpop, xb, fxb, **dparams): r"""Core function of Monkey King Evolution v1 algorithm. Args: task (Task): Optimization task. pop (numpy.ndarray[MkeSolution]): Current population. fpop (numpy.ndarray[float]): Current population fitness/function values. xb (MkeSolution): Current best solution. fxb (float): Current best solutions function/fitness value. **dparams (Dict[str, Any]): Additional arguments. Returns: Tuple(numpy.ndarray[MkeSolution], numpy.ndarray[float], Dict[str, Any]]: 1. Initialized solutions. 2. Fitness/function values of solution. 3. Additional arguments. """ pop = self.movePopulation(pop, xb, task) for i in self.Rand.choice(self.NP, int(self.R * len(pop)), replace=False): pop[i].MonkeyKing = True fpop = asarray([m.f for m in pop]) xb, fxb = self.getBest(pop, fpop, xb, fxb) return pop, fpop, xb, fxb, {}
[docs]class MonkeyKingEvolutionV2(MonkeyKingEvolutionV1): r"""Implementation of monkey king evolution algorithm version 2. Algorithm: Monkey King Evolution version 2 Date: 2018 Authors: Klemen Berkovič License: MIT Reference URL: https://www.sciencedirect.com/science/article/pii/S0950705116000198 Reference paper: Zhenyu Meng, Jeng-Shyang Pan, Monkey King Evolution: A new memetic evolutionary algorithm and its application in vehicle fuel consumption optimization, Knowledge-Based Systems, Volume 97, 2016, Pages 144-157, ISSN 0950-7051, https://doi.org/10.1016/j.knosys.2016.01.009. Attributes: Name (List[str]): List of strings representing algorithm names. See Also: * :class:`NiaPy.algorithms.basic.mke.MonkeyKingEvolutionV1` """ Name = ['MonkeyKingEvolutionV2', 'MKEv2']
[docs] @staticmethod def algorithmInfo(): r"""Get basic information of algorithm. Returns: str: Basic information. See Also: * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` """ return r"""Zhenyu Meng, Jeng-Shyang Pan, Monkey King Evolution: A new memetic evolutionary algorithm and its application in vehicle fuel consumption optimization, Knowledge-Based Systems, Volume 97, 2016, Pages 144-157, ISSN 0950-7051, https://doi.org/10.1016/j.knosys.2016.01.009."""
[docs] def moveMK(self, x, dx, task): r"""Move Monkey King particle. For movment of particles algorithm uses next formula: :math:`\mathbf{x} - \mathit{FC} \odot \mathbf{dx}` Args: x (numpy.ndarray): Particle to apply movment on. dx (numpy.ndarray): Difference between to random paricles in population. task (Task): Optimization task. Returns: numpy.ndarray: Moved particles. """ return x - self.FC * dx
[docs] def moveMokeyKingPartice(self, p, pop, task): r"""Move Monkey King particles. Args: p (MkeSolution): Monkey King particle to move. pop (numpy.ndarray[MkeSolution]): Current population. task (Task): Optimization task. """ p.MonkeyKing = False p_b, p_f = p.x, p.f for _i in range(int(self.C * self.NP)): r = self.Rand.choice(self.NP, 2, replace=False) a = task.repair(self.moveMK(p.x, pop[r[0]].x - pop[r[1]].x, task), self.Rand) a_f = task.eval(a) if a_f < p_f: p_b, p_f = a, a_f p.x, p.f = p_b, p_f
[docs] def movePopulation(self, pop, xb, task): r"""Move population. Args: pop (numpy.ndarray[MkeSolution]): Current population. xb (MkeSolution): Current best solution. task (Task): Optimization task. Returns: numpy.ndarray[MkeSolution]: Moved population. """ for p in pop: if p.MonkeyKing: self.moveMokeyKingPartice(p, pop, task) else: self.movePartice(p, xb, task) p.uPersonalBest() return pop
[docs]class MonkeyKingEvolutionV3(MonkeyKingEvolutionV1): r"""Implementation of monkey king evolution algorithm version 3. Algorithm: Monkey King Evolution version 3 Date: 2018 Authors: Klemen Berkovič License: MIT Reference URL: https://www.sciencedirect.com/science/article/pii/S0950705116000198 Reference paper: Zhenyu Meng, Jeng-Shyang Pan, Monkey King Evolution: A new memetic evolutionary algorithm and its application in vehicle fuel consumption optimization, Knowledge-Based Systems, Volume 97, 2016, Pages 144-157, ISSN 0950-7051, https://doi.org/10.1016/j.knosys.2016.01.009. Attributes: Name (List[str]): List of strings that represent algorithm names. See Also: * :class:`NiaPy.algorithms.basic.mke.MonkeyKingEvolutionV1` """ Name = ['MonkeyKingEvolutionV3', 'MKEv3']
[docs] @staticmethod def algorithmInfo(): r"""Get basic information of algorithm. Returns: str: Basic information. See Also: * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` """ return r"""Zhenyu Meng, Jeng-Shyang Pan, Monkey King Evolution: A new memetic evolutionary algorithm and its application in vehicle fuel consumption optimization, Knowledge-Based Systems, Volume 97, 2016, Pages 144-157, ISSN 0950-7051, https://doi.org/10.1016/j.knosys.2016.01.009."""
[docs] def setParameters(self, **ukwargs): r"""Set core parameters of MonkeyKingEvolutionV3 algorithm. Args: **ukwargs (Dict[str, Any]): Additional arguments. See Also: * :func:`NiaPy.algorithms.basic.MonkeyKingEvolutionV1.setParameters` """ MonkeyKingEvolutionV1.setParameters(self, itype=ukwargs.pop('itype', None), InitPopFunc=ukwargs.pop('InitPopFunc', defaultNumPyInit), **ukwargs)
[docs] def neg(self, x): r"""Transform function. Args: x (Union[int, float]): Sould be 0 or 1. Returns: float: If 0 thet 1 else 1 then 0. """ return 0.0 if x == 1.0 else 1.0
[docs] def initPopulation(self, task): r"""Initialize the population. Args: task (Task): Optimization task. Returns: Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]: 1. Initialized population. 2. Initialized population function/fitness values. 3. Additional arguments: * k (int): Starting number of rows to include from lower triangular matrix. * c (int): Constant. See Also: * :func:`NiaPy.algorithms.algorithm.Algorithm.initPopulation` """ X, X_f, d = Algorithm.initPopulation(self, task) k, c = int(ceil(self.NP / task.D)), int(ceil(self.C * task.D)) d.update({'k': k, 'c': c}) return X, X_f, d
[docs] def runIteration(self, task, X, X_f, xb, fxb, k, c, **dparams): r"""Core funciton of Monkey King Evolution v3 algorithm. Args: task (Task): Optimization task. X (numpy.ndarray): Current population. X_f (numpy.ndarray[float]): Current population fitness/function values. xb (numpy.ndarray): Current best individual. fxb (float): Current best individual function/fitness value. k (int): Starting number of rows to include from lower triangular matrix. c (int: Constant. **dparams: Additional arguments Returns: Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]: 1. Initialized population. 2. Initialized population function/fitness values. 3. Additional arguments: * k (int): Starting number of rows to include from lower triangular matrix. * c (int): Constant. """ X_gb = apply_along_axis(task.repair, 1, xb + self.FC * X[self.Rand.choice(len(X), c)] - X[self.Rand.choice(len(X), c)], self.Rand) X_gb_f = apply_along_axis(task.eval, 1, X_gb) xb, fxb = self.getBest(X_gb, X_gb_f, xb, fxb) M = full([self.NP, task.D], 1.0) for i in range(k): M[i * task.D:(i + 1) * task.D] = tril(M[i * task.D:(i + 1) * task.D]) for i in range(self.NP): self.Rand.shuffle(M[i]) X = apply_along_axis(task.repair, 1, M * X + vectorize(self.neg)(M) * xb, self.Rand) X_f = apply_along_axis(task.eval, 1, X) xb, fxb = self.getBest(X, X_f, xb, fxb) iw, ib_gb = argmax(X_f), argmin(X_gb_f) if X_gb_f[ib_gb] <= X_f[iw]: X[iw], X_f[iw] = X_gb[ib_gb], X_gb_f[ib_gb] return X, X_f, xb, fxb, {'k': k, 'c': c}
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3