Passed
Pull Request — master (#202)
by Grega
01:02
created

GlowwormSwarmOptimization.setParameters()   A

Complexity

Conditions 2

Size

Total Lines 18
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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