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

GlowwormSwarmOptimizationV1.__setParams()   A

Complexity

Conditions 2

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nop 3
dl 0
loc 8
rs 10
c 0
b 0
f 0
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