Completed
Push — master ( cc7745...279fb5 )
by Grega
19s queued 17s
created

GlowwormSwarmOptimization.runIteration()   A

Complexity

Conditions 3

Size

Total Lines 35
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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