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

GlowwormSwarmOptimizationV1.calcLuciferin()   A

Complexity

Conditions 1

Size

Total Lines 11
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 3
dl 0
loc 11
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, no-member
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 View Code Duplication
	@staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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
104
	def getParameters(self):
105
		r"""Get algorithms parameters values.
106
107
		Returns:
108
			Dict[str, Any]: TODO.
109
		"""
110
		d = Algorithm.getParameters(self)
111
		d.pop('NP', None)
112
		d.update({
113
			'n': self.NP,
114
			'l0': self.l0,
115
			'nt': self.nt,
116
			'rho': self.rho,
117
			'gamma': self.gamma,
118
			'beta': self.beta,
119
			's': self.s,
120
			'Distance': self.Distance
121
		})
122
		return d
123
124
	def getNeighbors(self, i, r, GS, L):
125
		r"""Get neighbours of glowworm.
126
127
		Args:
128
			i (int): Index of glowworm.
129
			r (float): Neighborhood distance.
130
			GS (numpy.ndarray):
131
			L (numpy.ndarray[float]): Luciferin value of glowworm.
132
133
		Returns:
134
			numpy.ndarray[int]: Indexes of neighborhood glowworms.
135
		"""
136
		N = full(self.NP, 0)
137
		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
138
		return N
139
140
	def probabilityes(self, i, N, L):
141
		r"""Calculate probabilities for glowworm to movement.
142
143
		Args:
144
			i (int): Index of glowworm to search for probable movement.
145
			N (numpy.ndarray[float]):
146
			L (numpy.ndarray[float]):
147
148
		Returns:
149
			numpy.ndarray[float]: Probabilities for each glowworm in swarm.
150
		"""
151
		d, P = sum(L[where(N == 1)] - L[i]), full(self.NP, .0)
152
		for j in range(self.NP): P[i] = ((L[j] - L[i]) / d) if N[j] == 1 else 0
153
		return P
154
155
	def moveSelect(self, pb, i):
156
		r"""TODO.
157
158
		Args:
159
			pb:
160
			i:
161
162
		Returns:
163
164
		"""
165
		r, b_l, b_u = self.rand(), 0, 0
166
		for j in range(self.NP):
167
			b_l, b_u = b_u, b_u + pb[i]
168
			if b_l < r < b_u: return j
169
		return self.randint(self.NP)
170
171
	def calcLuciferin(self, L, GS_f):
172
		r"""TODO.
173
174
		Args:
175
			L:
176
			GS_f:
177
178
		Returns:
179
180
		"""
181
		return (1 - self.rho) * L + self.gamma * GS_f
182
183
	def rangeUpdate(self, R, N, rs):
184
		r"""TODO.
185
186
		Args:
187
			R:
188
			N:
189
			rs:
190
191
		Returns:
192
193
		"""
194
		return R + self.beta * (self.nt - sum(N))
195
196
	def initPopulation(self, task):
197
		r"""Initialize population.
198
199
		Args:
200
			task (Task): Optimization task.
201
202
		Returns:
203
			Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
204
				1. Initialized population of glowwarms.
205
				2. Initialized populations function/fitness values.
206
				3. Additional arguments:
207
					* L (numpy.ndarray): TODO.
208
					* R (numpy.ndarray): TODO.
209
					* rs (numpy.ndarray): TODO.
210
		"""
211
		GS, GS_f, d = Algorithm.initPopulation(self, task)
212
		rs = euclidean(full(task.D, 0), task.bRange)
213
		L, R = full(self.NP, self.l0), full(self.NP, rs)
214
		d.update({'L': L, 'R': R, 'rs': rs})
215
		return GS, GS_f, d
216
217
	def runIteration(self, task, GS, GS_f, xb, fxb, L, R, rs, **dparams):
218
		r"""Core function of GlowwormSwarmOptimization algorithm.
219
220
		Args:
221
			task (Task): Optimization taks.
222
			GS (numpy.ndarray): Current population.
223
			GS_f (numpy.ndarray): Current populations fitness/function values.
224
			xb (numpy.ndarray): Global best individual.
225
			fxb (float): Global best individuals function/fitness value.
226
			L (numpy.ndarray):
227
			R (numpy.ndarray):
228
			rs (numpy.ndarray):
229
			**dparams Dict[str, Any]: Additional arguments.
230
231
		Returns:
232
			Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]:
233
				1. Initialized population of glowwarms.
234
				2. Initialized populations function/fitness values.
235
				3. New global best solution
236
				4. New global best sloutions fitness/objective value.
237
				5. Additional arguments:
238
					* L (numpy.ndarray): TODO.
239
					* R (numpy.ndarray): TODO.
240
					* rs (numpy.ndarray): TODO.
241
		"""
242
		GSo, Ro = copy(GS), copy(R)
243
		L = self.calcLuciferin(L, GS_f)
244
		N = [self.getNeighbors(i, Ro[i], GSo, L) for i in range(self.NP)]
245
		P = [self.probabilityes(i, N[i], L) for i in range(self.NP)]
246
		j = [self.moveSelect(P[i], i) for i in range(self.NP)]
247
		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)
248
		for i in range(self.NP): R[i] = max(0, min(rs, self.rangeUpdate(Ro[i], N[i], rs)))
249
		GS_f = apply_along_axis(task.eval, 1, GS)
250
		xb, fxb = self.getBest(GS, GS_f, xb, fxb)
251
		return GS, GS_f, xb, fxb, {'L': L, 'R': R, 'rs': rs}
252
253
class GlowwormSwarmOptimizationV1(GlowwormSwarmOptimization):
254
	r"""Implementation of glowwarm swarm optimization.
255
256
	Algorithm:
257
		Glowwarm Swarm Optimization Algorithm
258
259
	Date:
260
		2018
261
262
	Authors:
263
		Klemen Berkovič
264
265
	License:
266
		MIT
267
268
	Reference URL:
269
		https://www.springer.com/gp/book/9783319515946
270
271
	Reference paper:
272
		Kaipa, Krishnanand N., and Debasish Ghose. Glowworm swarm optimization: theory, algorithms, and applications. Vol. 698. Springer, 2017.
273
274
	Attributes:
275
		Name (List[str]): List of strings representing algorithm names.
276
		alpha (float): --
277
278
	See Also:
279
		* :class:`NiaPy.algorithms.basic.GlowwormSwarmOptimization`
280
	"""
281
	Name = ['GlowwormSwarmOptimizationV1', 'GSOv1']
282
283
	def setParameters(self, **kwargs):
284
		r"""Set default parameters of the algorithm.
285
286
		Args:
287
			**kwargs (dict): Additional arguments.
288
		"""
289
		GlowwormSwarmOptimization.setParameters(self, **kwargs)
290
291
	def calcLuciferin(self, L, GS_f):
292
		r"""TODO.
293
294
		Args:
295
			L:
296
			GS_f:
297
298
		Returns:
299
300
		"""
301
		return fmax(0, (1 - self.rho) * L + self.gamma * GS_f)
302
303
	def rangeUpdate(self, R, N, rs):
304
		r"""TODO.
305
306
		Args:
307
			R:
308
			N:
309
			rs:
310
311
		Returns:
312
313
		"""
314
		return rs / (1 + self.beta * (sum(N) / (pi * rs ** 2)))
315
316
class GlowwormSwarmOptimizationV2(GlowwormSwarmOptimization):
317
	r"""Implementation of glowwarm swarm optimization.
318
319
	Algorithm:
320
		Glowwarm Swarm Optimization Algorithm
321
322
	Date:
323
		2018
324
325
	Authors:
326
		Klemen Berkovič
327
328
	License:
329
		MIT
330
331
	Reference URL:
332
		https://www.springer.com/gp/book/9783319515946
333
334
	Reference paper:
335
		Kaipa, Krishnanand N., and Debasish Ghose. Glowworm swarm optimization: theory, algorithms, and applications. Vol. 698. Springer, 2017.
336
337
	Attributes:
338
		Name (List[str]): List of strings representing algorithm names.
339
		alpha (float): --
340
341
	See Also:
342
		* :class:`NiaPy.algorithms.basic.GlowwormSwarmOptimization`
343
	"""
344
	Name = ['GlowwormSwarmOptimizationV2', 'GSOv2']
345
346
	def setParameters(self, alpha=0.2, **kwargs):
347
		r"""Set core parameters for GlowwormSwarmOptimizationV2 algorithm.
348
349
		Args:
350
			alpha (Optional[float]): --
351
			**kwargs (Dict[str, Any]): Additional arguments.
352
353
		See Also:
354
			* :func:`NiaPy.algorithms.basic.GlowwormSwarmOptimization.setParameters`
355
		"""
356
		GlowwormSwarmOptimization.setParameters(self, **kwargs)
357
		self.alpha = alpha
358
359
	def rangeUpdate(self, P, N, rs):
360
		r"""TODO.
361
362
		Args:
363
			P:
364
			N:
365
			rs:
366
367
		Returns:
368
			float: TODO
369
		"""
370
		return self.alpha + (rs - self.alpha) / (1 + self.beta * sum(N))
371
372
class GlowwormSwarmOptimizationV3(GlowwormSwarmOptimization):
373
	r"""Implementation of glowwarm swarm optimization.
374
375
	Algorithm:
376
		Glowwarm Swarm Optimization Algorithm
377
378
	Date:
379
		2018
380
381
	Authors:
382
		Klemen Berkovič
383
384
	License:
385
		MIT
386
387
	Reference URL:
388
		https://www.springer.com/gp/book/9783319515946
389
390
	Reference paper:
391
		Kaipa, Krishnanand N., and Debasish Ghose. Glowworm swarm optimization: theory, algorithms, and applications. Vol. 698. Springer, 2017.
392
393
	Attributes:
394
		Name (List[str]): List of strings representing algorithm names.
395
		beta1 (float): --
396
397
	See Also:
398
		* :class:`NiaPy.algorithms.basic.GlowwormSwarmOptimization`
399
	"""
400
	Name = ['GlowwormSwarmOptimizationV3', 'GSOv3']
401
402
	def setParameters(self, beta1=0.2, **kwargs):
403
		r"""Set core parameters for GlowwormSwarmOptimizationV3 algorithm.
404
405
		Args:
406
			beta1 (Optional[float]): --
407
			**kwargs (Dict[str, Any]): Additional arguments.
408
409
		See Also:
410
			* :func:`NiaPy.algorithms.basic.GlowwormSwarmOptimization.setParameters`
411
		"""
412
		GlowwormSwarmOptimization.setParameters(self, **kwargs)
413
		self.beta1 = beta1
414
415
	def rangeUpdate(self, R, N, rs):
416
		r"""TODO.
417
418
		Args:
419
			R:
420
			N:
421
			rs:
422
423
		Returns:
424
425
		"""
426
		return R + (self.beta * sum(N)) if sum(N) < self.nt else (-self.beta1 * sum(N))
427
428
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
429