Passed
Branch master (13db34)
by Grega
02:16
created

GlowwormSwarmOptimization.setParameters()   A

Complexity

Conditions 2

Size

Total Lines 16
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nop 10
dl 0
loc 16
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
# encoding=utf8
2
# pylint: disable=mixed-indentation, trailing-whitespace, line-too-long, multiple-statements, attribute-defined-outside-init, logging-not-lazy, no-self-use, redefined-builtin, singleton-comparison, unused-argument, arguments-differ, no-else-return, bad-continuation
3
import logging
4
5
from scipy.spatial.distance import euclidean
6
from numpy import full, apply_along_axis, copy, sum, fmax, pi, where
7
8
from NiaPy.algorithms.algorithm import Algorithm
9
10
logging.basicConfig()
11
logger = logging.getLogger('NiaPy.algorithms.basic')
12
logger.setLevel('INFO')
13
14
__all__ = ['GlowwormSwarmOptimization', 'GlowwormSwarmOptimizationV1', 'GlowwormSwarmOptimizationV2', 'GlowwormSwarmOptimizationV3']
15
16
class GlowwormSwarmOptimization(Algorithm):
17
	r"""Implementation of glowwarm swarm optimization.
18
19
	Algorithm:
20
		Glowwarm Swarm Optimization Algorithm
21
22
	Date:
23
		2018
24
25
	Authors:
26
		Klemen Berkovič
27
28
	License:
29
		MIT
30
31
	Reference URL:
32
		https://www.springer.com/gp/book/9783319515946
33
34
	Reference paper:
35
		Kaipa, Krishnanand N., and Debasish Ghose. Glowworm swarm optimization: theory, algorithms, and applications. Vol. 698. Springer, 2017.
36
37
	Attributes:
38
		Name (List[str]): List of strings represeinting algorithm name.
39
		n (int): Number of glowworms in population.
40
		l0 (float): Initial luciferin quantity for each glowworm.
41
		nt (float): --
42
		rs (float): Maximum sensing range.
43
		rho (float): Luciferin decay constant.
44
		gamma (float): Luciferin enhancement constant.
45
		beta (float): --
46
		s (float): --
47
		Distance (Callable[[numpy.ndarray, numpy.ndarray], float]]): Measure distance between two individuals.
48
49
	See Also:
50
		* :class:`NiaPy.algorithms.algorithm.Algorithm`
51
	"""
52
	Name = ['GlowwormSwarmOptimization', 'GSO']
53
54
	@staticmethod
55
	def typeParameters():
56
		r"""Get dictionary with functions for checking values of parameters.
57
58
		Returns:
59
			Dict[str, Callable]:
60
				* n (Callable[[int], bool]): TODO
61
				* l0 (Callable[[Union[float, int]], bool]): TODO
62
				* nt (Callable[[Union[float, int]], bool]): TODO
63
				* rho (Callable[[Union[float, int]], bool]): TODO
64
				* gamma (Callable[[float], bool]): TODO
65
				* beta (Callable[[float], bool]): TODO
66
				* s (Callable[[float], bool]): TODO
67
		"""
68
		return {
69
			'n': lambda x: isinstance(x, int) and x > 0,
70
			'l0': lambda x: isinstance(x, (float, int)) and x > 0,
71
			'nt': lambda x: isinstance(x, (float, int)) and x > 0,
72
			'rho': lambda x: isinstance(x, float) and 0 < x < 1,
73
			'gamma': lambda x: isinstance(x, float) and 0 < x < 1,
74
			'beta': lambda x: isinstance(x, float) and x > 0,
75
			's': lambda x: isinstance(x, float) and x > 0
76
		}
77
78
	def setParameters(self, n=25, l0=5, nt=5, rho=0.4, gamma=0.6, beta=0.08, s=0.03, Distance=euclidean, **ukwargs):
79
		r"""Set the arguments of an algorithm.
80
81
		Arguments:
82
			n (Optional[int]): Number of glowworms in population.
83
			l0 (Optional[float]): Initial luciferin quantity for each glowworm.
84
			nt (Optional[float]): --
85
			rs (Optional]float]): Maximum sensing range.
86
			rho (Optional[float]): Luciferin decay constant.
87
			gamma (Optional[float]): Luciferin enhancement constant.
88
			beta (Optional[float]): --
89
			s (Optional[float]): --
90
			Distance (Optional[Callable[[numpy.ndarray, numpy.ndarray], float]]]): Measure distance between two individuals.
91
		"""
92
		self.n, self.l0, self.nt, self.rho, self.gamma, self.beta, self.s, self.Distance = n, l0, nt, rho, gamma, beta, s, Distance
93
		if ukwargs: logger.info('Unused arguments: %s' % (ukwargs))
94
95
	def randMove(self, i):
96
		r"""Move a glowworm to another glowworm.
97
98
		Args:
99
			i (int): Index of glowworm that is making a move.
100
101
		Returns:
102
			int: Index of glowworm to move to.
103
		"""
104
		j = i
105
		while i == j: j = self.randint(self.n)
106
		return j
107
108
	def getNeighbors(self, i, r, GS, L):
109
		r"""Get neighbours of glowworm.
110
111
		Args:
112
			i (int): Index of glowworm.
113
			r (float): Neighborhood distance.
114
			GS (numpy.ndarray):
115
			L (numpy.ndarray[float]): Luciferin value of glowworm.
116
117
		Returns:
118
			numpy.ndarray[int]: Indexes of neighborhood glowworms.
119
		"""
120
		N = full(self.n, 0)
121
		for j, gw in enumerate(GS): N[j] = 1 if i != j and self.Distance(GS[i], gw) <= r and L[i] >= L[j] else 0
122
		return N
123
124
	def probabilityes(self, i, N, L):
125
		r"""TODO.
126
127
		Args:
128
			i:
129
			N:
130
			L:
131
132
		Returns:
133
134
		"""
135
		d, P = sum(L[where(N == 1)] - L[i]), full(self.n, .0)
136
		for j in range(self.n): P[i] = ((L[j] - L[i]) / d) if N[j] == 1 else 0
137
		return P
138
139
	def moveSelect(self, pb, i):
140
		r"""TODO.
141
142
		Args:
143
			pb:
144
			i:
145
146
		Returns:
147
148
		"""
149
		r, b_l, b_u = self.rand(), 0, 0
150
		for j in range(self.n):
151
			b_l, b_u = b_u, b_u + pb[i]
152
			if b_l < r < b_u: return j
153
		return self.randint(self.n)
154
155
	def calcLuciferin(self, L, GS_f):
156
		r"""TODO.
157
158
		Args:
159
			L:
160
			GS_f:
161
162
		Returns:
163
164
		"""
165
		return (1 - self.rho) * L + self.gamma * GS_f
166
167
	def rangeUpdate(self, R, N, rs):
168
		r"""TODO.
169
170
		Args:
171
			R:
172
			N:
173
			rs:
174
175
		Returns:
176
177
		"""
178
		return R + self.beta * (self.nt - sum(N))
179
180
	def initPopulation(self, task):
181
		r"""Initialize population.
182
183
		Args:
184
			task (Task): Optimization task.
185
186
		Returns:
187
			Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
188
				1. Initialized population of glowwarms.
189
				2. Initialized populations function/fitness values.
190
				3. Additional arguments:
191
					* L (numpy.ndarray): TODO.
192
					* R (numpy.ndarray): TODO.
193
					* rs (numpy.ndarray): TODO.
194
		"""
195
		rs = euclidean(full(task.D, 0), task.bRange)
196
		GS, L, R = self.uniform(task.Lower, task.Upper, [self.n, task.D]), full(self.n, self.l0), full(self.n, rs)
197
		GS_f = apply_along_axis(task.eval, 1, GS)
198
		return GS, GS_f, {'L': L, 'R': R, 'rs': rs}
199
200
	def runIteration(self, task, GS, GS_f, xb, fxb, L, R, rs, **dparams):
201
		r"""Core function of GlowwormSwarmOptimization algorithm.
202
203
		Args:
204
			task (Task): Optimization taks.
205
			GS (numpy.ndarray): Current population.
206
			GS_f (numpy.ndarray[float]): Current populations fitness/function values.
207
			xb (numpy.ndarray): Global best individual.
208
			fxb (float): Global best individuals function/fitness value.
209
			L (numpy.ndarray):
210
			R (numpy.ndarray):
211
			rs (numpy.ndarray):
212
			**dparams Dict[str, Any]: Additional arguments.
213
214
		Returns:
215
			Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
216
				1. Initialized population of glowwarms.
217
				2. Initialized populations function/fitness values.
218
				3. Additional arguments:
219
					* L (numpy.ndarray): TODO.
220
					* R (numpy.ndarray): TODO.
221
					* rs (numpy.ndarray): TODO.
222
		"""
223
		GSo, Ro = copy(GS), copy(R)
224
		L = self.calcLuciferin(L, GS_f)
225
		N = [self.getNeighbors(i, Ro[i], GSo, L) for i in range(self.n)]
226
		P = [self.probabilityes(i, N[i], L) for i in range(self.n)]
227
		j = [self.moveSelect(P[i], i) for i in range(self.n)]
228
		for i in range(self.n): GS[i] = task.repair(GSo[i] + self.s * ((GSo[j[i]] - GSo[i]) / (self.Distance(GSo[j[i]], GSo[i]) + 1e-31)), rnd=self.Rand)
229
		for i in range(self.n): R[i] = max(0, min(rs, self.rangeUpdate(Ro[i], N[i], rs)))
230
		GS_f = apply_along_axis(task.eval, 1, GS)
231
		return GS, GS_f, {'L': L, 'R': R, 'rs': rs}
232
233
class GlowwormSwarmOptimizationV1(GlowwormSwarmOptimization):
234
	r"""Implementation of glowwarm swarm optimization.
235
236
	Algorithm:
237
		Glowwarm Swarm Optimization Algorithm
238
239
	Date:
240
		2018
241
242
	Authors:
243
		Klemen Berkovič
244
245
	License:
246
		MIT
247
248
	Reference URL:
249
		https://www.springer.com/gp/book/9783319515946
250
251
	Reference paper:
252
		Kaipa, Krishnanand N., and Debasish Ghose. Glowworm swarm optimization: theory, algorithms, and applications. Vol. 698. Springer, 2017.
253
254
	Attributes:
255
		Name (list of str): TODO
256
	"""
257
	Name = ['GlowwormSwarmOptimizationV1', 'GSOv1']
258
259
	def setParameters(self, **kwargs):
260
		self.__setParams(**kwargs)
261
		GlowwormSwarmOptimization.setParameters(self, **kwargs)
262
263
	def __setParams(self, alpha=0.2, **ukwargs):
264
		r"""Set the arguments of an algorithm.
265
266
		Arguments:
267
			alpha (float): --
268
		"""
269
		self.alpha = alpha
270
		if ukwargs: logger.info('Unused arguments: %s' % (ukwargs))
271
272
	def calcLuciferin(self, L, GS_f):
273
		r"""TODO.
274
275
		Args:
276
			L:
277
			GS_f:
278
279
		Returns:
280
281
		"""
282
		return fmax(0, (1 - self.rho) * L + self.gamma * GS_f)
283
284
	def rangeUpdate(self, R, N, rs):
285
		r"""TODO.
286
287
		Args:
288
			R:
289
			N:
290
			rs:
291
292
		Returns:
293
294
		"""
295
		return rs / (1 + self.beta * (sum(N) / (pi * rs ** 2)))
296
297
class GlowwormSwarmOptimizationV2(GlowwormSwarmOptimization):
298
	r"""Implementation of glowwarm swarm optimization.
299
300
	Algorithm:
301
		Glowwarm Swarm Optimization Algorithm
302
303
	Date:
304
		2018
305
306
	Authors:
307
		Klemen Berkovič
308
309
	License:
310
		MIT
311
312
	Reference URL:
313
		https://www.springer.com/gp/book/9783319515946
314
315
	Reference paper:
316
		Kaipa, Krishnanand N., and Debasish Ghose. Glowworm swarm optimization: theory, algorithms, and applications. Vol. 698. Springer, 2017.
317
318
	Attributes:
319
		Name (list or str): TODO
320
	"""
321
	Name = ['GlowwormSwarmOptimizationV2', 'GSOv2']
322
323
	def setParameters(self, **kwargs):
324
		self.__setParams(alpha=kwargs.pop('alpha', 0.2), **kwargs)
325
		GlowwormSwarmOptimization.setParameters(self, **kwargs)
326
327
	def __setParams(self, alpha=0.2, **ukwargs):
328
		r"""Set the arguments of an algorithm.
329
330
		**Arguments:**
331
332
		beta1 {real} --
333
334
		s {real} --
335
		"""
336
		self.alpha = alpha
337
		if ukwargs: logger.info('Unused arguments: %s' % (ukwargs))
338
339
	def rangeUpdate(self, P, N, rs):
340
		r"""TODO.
341
342
		Args:
343
			P:
344
			N:
345
			rs:
346
347
		Returns:
348
349
		"""
350
		return self.alpha + (rs - self.alpha) / (1 + self.beta * sum(N))
351
352
class GlowwormSwarmOptimizationV3(GlowwormSwarmOptimization):
353
	r"""Implementation of glowwarm swarm optimization.
354
355
	Algorithm:
356
		Glowwarm Swarm Optimization Algorithm
357
358
	Date:
359
		2018
360
361
	Authors:
362
		Klemen Berkovič
363
364
	License:
365
		MIT
366
367
	Reference URL:
368
		https://www.springer.com/gp/book/9783319515946
369
370
	Reference paper:
371
		Kaipa, Krishnanand N., and Debasish Ghose. Glowworm swarm optimization: theory, algorithms, and applications. Vol. 698. Springer, 2017.
372
373
	Attributes:
374
		Name (list of str): TODO
375
	"""
376
	Name = ['GlowwormSwarmOptimizationV3', 'GSOv3']
377
378
	def setParameters(self, **kwargs):
379
		self.__setParams(beta1=kwargs.pop('beta1', 0.2), **kwargs)
380
		GlowwormSwarmOptimization.setParameters(self, **kwargs)
381
382
	def __setParams(self, beta1=0.2, **ukwargs):
383
		r"""Set the arguments of an algorithm.
384
385
		**Arguments:**
386
387
		beta1 {real} --
388
389
		s {real} --
390
		"""
391
		self.beta1 = beta1
392
		if ukwargs: logger.info('Unused arguments: %s' % (ukwargs))
393
394
	def rangeUpdate(self, R, N, rs):
395
		r"""TODO.
396
397
		Args:
398
			R:
399
			N:
400
			rs:
401
402
		Returns:
403
404
		"""
405
		return R + (self.beta * sum(N)) if sum(N) < self.nt else (-self.beta1 * sum(N))
406
407
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
408