Passed
Pull Request — master (#233)
by
unknown
01:19
created

MonarchButterflyOptimization.setParameters()   A

Complexity

Conditions 1

Size

Total Lines 15
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nop 5
dl 0
loc 15
rs 10
c 0
b 0
f 0
1
# encoding=utf8
2
# pylint: disable=mixed-indentation, trailing-whitespace, multiple-statements, attribute-defined-outside-init, logging-not-lazy, redefined-builtin, line-too-long, no-self-use, arguments-differ, no-else-return, bad-continuation, unused-argument
3
import logging
4
5
from numpy import argsort, sum, apply_along_axis, where, pi, ceil, isinf, array, copy, tan
6
from numpy.random import exponential
7
8
from NiaPy.algorithms.algorithm import Algorithm
9
10
__all__ = ['MonarchButterflyOptimization']
11
12
logging.basicConfig()
13
logger = logging.getLogger('NiaPy.algorithms.basic')
14
logger.setLevel('INFO')
15
16
class MonarchButterflyOptimization(Algorithm):
17
	r"""Implementation of Monarch Butterfly Optimization.
18
19
	Algorithm:
20
		 Monarch Butterfly Optimization
21
22
	Date:
23
		 2019
24
25
	Authors:
26
		 Jan Banko
27
28
	License:
29
		 MIT
30
31
	Reference paper:
32
		 Wang, Gai-Ge & Deb, Suash & Cui, Zhihua. (2015). Monarch Butterfly Optimization. Neural Computing and Applications. 10.1007/s00521-015-1923-y. , https://www.researchgate.net/publication/275964443_Monarch_Butterfly_Optimization.
33
34
	Attributes:
35
		 Name (List[str]): List of strings representing algorithm name.
36
		 PAR (float): Partition.
37
		 PER (float): Period.
38
39
	See Also:
40
		 * :class:`NiaPy.algorithms.Algorithm`
41
	"""
42
	Name = ['MonarchButterflyOptimization', 'MBO']
43
44
	@staticmethod
45
	def algorithmInfo():
46
		r"""Get information of the algorithm.
47
48
		Returns:
49
			str: Algorithm information.
50
51
		See Also:
52
			 * :func:`NiaPy.algorithms.algorithm.Algorithm.algorithmInfo`
53
		"""
54
		return r"""
55
		Description: Monarch butterfly optimization algorithm is inspired by the migration behaviour of the monarch butterflies in nature.
56
		Authors: Wang, Gai-Ge & Deb, Suash & Cui, Zhihua.
57
		Year: 2015
58
		Main reference: Wang, Gai-Ge & Deb, Suash & Cui, Zhihua. (2015). Monarch Butterfly Optimization. Neural Computing and Applications. 10.1007/s00521-015-1923-y. , https://www.researchgate.net/publication/275964443_Monarch_Butterfly_Optimization.
59
    """
60
61 View Code Duplication
	@staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
62
	def typeParameters():
63
		r"""Get dictionary with functions for checking values of parameters.
64
65
		Returns:
66
			 Dict[str, Callable]:
67
				  * PAR (Callable[[float], bool]): Checks if partition parameter has a proper value.
68
				  * PER (Callable[[float], bool]): Checks if period parameter has a proper value.
69
		See Also:
70
			 * :func:`NiaPy.algorithms.algorithm.Algorithm.typeParameters`
71
		"""
72
		d = Algorithm.typeParameters()
73
		d.update({
74
			'PAR': lambda x: isinstance(x, float) and x > 0,
75
			'PER': lambda x: isinstance(x, float) and x > 0
76
		})
77
		return d
78
79
	def setParameters(self, NP=20, PAR=5.0 / 12.0, PER=1.2, **ukwargs):
80
		r"""Set the parameters of the algorithm.
81
82
		Args:
83
			 NP (Optional[int]): Population size.
84
			 PAR (Optional[int]): Partition.
85
			 PER (Optional[int]): Period.
86
			 ukwargs (Dict[str, Any]): Additional arguments.
87
88
		See Also:
89
			 * :func:`NiaPy.algorithms.Algorithm.setParameters`
90
		"""
91
		Algorithm.setParameters(self, NP=NP, **ukwargs)
92
		self.NP, self.PAR, self.PER, self.keep, self.BAR, self.NP1 = NP, PAR, PER, 2, PAR, int(ceil(PAR * NP))
93
		self.NP2 = int(NP - self.NP1)
94
95
	def getParameters(self):
96
		r"""Get parameters values for the algorithm.
97
98
		Returns:
99
			Dict[str, Any]: TODO.
100
		"""
101
		d = Algorithm.getParameters(self)
102
		d.update({
103
			'PAR': self.PAR,
104
			'PER': self.PER,
105
			'keep': self.keep,
106
			'BAR': self.BAR,
107
			'NP1': self.NP1,
108
			'NP2': self.NP2
109
		})
110
		return d
111
112 View Code Duplication
	def repair(self, x, lower, upper):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
113
		r"""Truncate exceeded dimensions to the limits.
114
115
		Args:
116
			 x (numpy.ndarray): Individual to repair.
117
			 lower (numpy.ndarray): Lower limits for dimensions.
118
			 upper (numpy.ndarray): Upper limits for dimensions.
119
120
		Returns:
121
			 numpy.ndarray: Repaired individual.
122
		"""
123
		ir = where(x < lower)
124
		x[ir] = lower[ir]
125
		ir = where(x > upper)
126
		x[ir] = upper[ir]
127
		return x
128
129
	def levy(self, step_size, D):
130
		r"""Calculate levy flight.
131
132
		Args:
133
			 step_size (float): Size of the walk step.
134
			 D (int): Number of dimensions.
135
136
		Returns:
137
			 numpy.ndarray: Calculated values for levy flight.
138
		"""
139
		delataX = array([sum(tan(pi * self.uniform(0.0, 1.0, 10))) for _ in range(0, D)])
140
		return delataX
141
142
	def migrationOperator(self, D, NP1, NP2, Butterflies):
143
		r"""Apply the migration operator.
144
145
		Args:
146
			 D (int): Number of dimensions.
147
			 NP1 (int): Number of butterflies in Land 1.
148
			 NP2 (int): Number of butterflies in Land 2.
149
			 Butterflies (numpy.ndarray): Current butterfly population.
150
151
		Returns:
152
			 numpy.ndarray: Adjusted butterfly population.
153
		"""
154
		pop1 = copy(Butterflies[:NP1])
155
		pop2 = copy(Butterflies[NP1:])
156
		for k1 in range(0, NP1):
157
			for parnum1 in range(0, D):
158
				r1 = self.uniform(0.0, 1.0) * self.PER
159
				if r1 <= self.PAR:
160
					r2 = self.randint(Nmin=0, Nmax=NP1 - 1)
161
					Butterflies[k1, parnum1] = pop1[r2, parnum1]
162
				else:
163
					r3 = self.randint(Nmin=0, Nmax=NP2 - 1)
164
					Butterflies[k1, parnum1] = pop2[r3, parnum1]
165
		return Butterflies
166
167
	def adjustingOperator(self, t, max_t, D, NP1, NP2, Butterflies, best):
168
		r"""Apply the adjusting operator.
169
170
		Args:
171
			 t (int): Current generation.
172
			 max_t (int): Maximum generation.
173
			 D (int): Number of dimensions.
174
			 NP1 (int): Number of butterflies in Land 1.
175
			 NP2 (int): Number of butterflies in Land 2.
176
			 Butterflies (numpy.ndarray): Current butterfly population.
177
			 best (numpy.ndarray): The best butterfly currently.
178
179
		Returns:
180
			 numpy.ndarray: Adjusted butterfly population.
181
		"""
182
		pop2 = copy(Butterflies[NP1:])
183
		for k2 in range(NP1, NP1 + NP2):
184
			scale = 1.0 / ((t + 1)**2)
185
			step_size = ceil(exponential(2 * max_t))
186
			delataX = self.levy(step_size, D)
187
			for parnum2 in range(0, D):
188
				if self.uniform(0.0, 1.0) >= self.PAR:
189
					Butterflies[k2, parnum2] = best[parnum2]
190
				else:
191
					r4 = self.randint(Nmin=0, Nmax=NP2 - 1)
192
					Butterflies[k2, parnum2] = pop2[r4, 1]
193
					if self.uniform(0.0, 1.0) > self.BAR:
194
						Butterflies[k2, parnum2] += scale * \
195
															 (delataX[parnum2] - 0.5)
196
		return Butterflies
197
198
	def evaluateAndSort(self, task, Butterflies):
199
		r"""Evaluate and sort the butterfly population.
200
201
		Args:
202
			 task (Task): Optimization task
203
			 Butterflies (numpy.ndarray): Current butterfly population.
204
205
		Returns:
206
			 numpy.ndarray: Tuple[numpy.ndarray, float, numpy.ndarray]:
207
				  1. Best butterfly according to the evaluation.
208
				  2. The best fitness value.
209
				  3. Butterfly population.
210
		"""
211
		Fitness = apply_along_axis(task.eval, 1, Butterflies)
212
		indices = argsort(Fitness)
213
		Butterflies = Butterflies[indices]
214
		Fitness = Fitness[indices]
215
216
		return Fitness, Butterflies
217
218
	def initPopulation(self, task):
219
		r"""Initialize the starting population.
220
221
		Args:
222
			 task (Task): Optimization task
223
224
		Returns:
225
			 Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
226
				  1. New population.
227
				  2. New population fitness/function values.
228
				  3. Additional arguments:
229
						* dx (float): A small value used in local seeding stage.
230
231
		See Also:
232
			 * :func:`NiaPy.algorithms.Algorithm.initPopulation`
233
		"""
234
		Butterflies = self.uniform(task.Lower, task.Upper, [self.NP, task.D])
235
		Fitness, Butterflies = self.evaluateAndSort(task, Butterflies)
236
		return Butterflies, Fitness, {'tmp_best': Butterflies[0]}
237
238
	def runIteration(self, task, Butterflies, Evaluations, xb, fxb, tmp_best, **dparams):
239
		r"""Core function of Forest Optimization Algorithm.
240
241
		Args:
242
			 task (Task): Optimization task.
243
			 Butterflies (numpy.ndarray): Current population.
244
			 Evaluations (numpy.ndarray[float]): Current population function/fitness values.
245
			 xb (numpy.ndarray): Global best individual.
246
			 fxb (float): Global best individual fitness/function value.
247
			 tmp_best (numpy.ndarray): Best individual currently.
248
			 **dparams (Dict[str, Any]): Additional arguments.
249
250
		Returns:
251
			 Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]:
252
				  1. New population.
253
				  2. New population fitness/function values.
254
				  3. New global best solution
255
				  4. New global best solutions fitness/objective value
256
				  5. Additional arguments:
257
						* dx (float): A small value used in local seeding stage.
258
		"""
259
		tmpElite = copy(Butterflies[:self.keep])
260
		max_t = task.nGEN if isinf(task.nGEN) is False else task.nFES / self.NP
261
		Butterflies = apply_along_axis(self.repair, 1, self.migrationOperator(task.D, self.NP1, self.NP2, Butterflies), task.Lower, task.Upper)
262
		Butterflies = apply_along_axis(self.repair, 1, self.adjustingOperator(task.Iters, max_t, task.D, self.NP1, self.NP2, Butterflies, tmp_best), task.Lower, task.Upper)
263
		Fitness, Butterflies = self.evaluateAndSort(task, Butterflies)
264
		tmp_best = Butterflies[0]
265
		Butterflies[-self.keep:] = tmpElite
266
		Fitness, Butterflies = self.evaluateAndSort(task, Butterflies)
267
		xb, fxb = self.getBest(Butterflies, Fitness, xb, fxb)
268
		return Butterflies, Fitness, xb, fxb, {'tmp_best': tmp_best}
269
270
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
271