# 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): TODO.
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): TODO.
* c (int): TODO.
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): TODO
c (int: TODO
**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): TODO.
* c (int): TODO.
"""
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