NiaPy.algorithms.basic.fwa   F
last analyzed

Complexity

Total Complexity 69

Size/Duplication

Total Lines 871
Duplicated Lines 4.48 %

Importance

Changes 0
Metric Value
wmc 69
eloc 222
dl 39
loc 871
rs 2.88
c 0
b 0
f 0

42 Methods

Rating   Name   Duplication   Size   Complexity  
B FireworksAlgorithm.typeParameters() 7 7 6
A FireworksAlgorithm.algorithmInfo() 0 11 1
A BareBonesFireworksAlgorithm.runIteration() 0 27 2
A FireworksAlgorithm.ExplosionAmplitude() 0 13 1
A BareBonesFireworksAlgorithm.initPopulation() 0 16 1
A FireworksAlgorithm.SparsksNo() 0 13 2
A BareBonesFireworksAlgorithm.algorithmInfo() 0 11 1
A BareBonesFireworksAlgorithm.typeParameters() 0 5 4
A BareBonesFireworksAlgorithm.setParameters() 0 11 1
A DynamicFireworksAlgorithmGauss.Mapping() 0 15 1
A DynamicFireworksAlgorithm.algorithmInfo() 0 11 1
A EnhancedFireworksAlgorithm.setParameters() 0 13 1
A EnhancedFireworksAlgorithm.typeParameters() 0 16 3
A FireworksAlgorithm.setParameters() 0 13 1
A DynamicFireworksAlgorithm.runIteration() 0 30 1
A EnhancedFireworksAlgorithm.initPopulation() 0 22 1
A FireworksAlgorithm.initAmplitude() 0 10 1
A FireworksAlgorithm.initPopulation() 0 20 1
A DynamicFireworksAlgorithmGauss.setParameters() 0 15 1
A EnhancedFireworksAlgorithm.initRanges() 0 14 1
A EnhancedFireworksAlgorithm.ExplosionAmplitude() 0 18 1
A FireworksAlgorithm.Mapping() 15 15 1
A FireworksAlgorithm.p() 0 11 1
A EnhancedFireworksAlgorithm.NextGeneration() 0 21 4
A DynamicFireworksAlgorithmGauss.NextGeneration() 0 21 3
A FireworksAlgorithm.R() 0 11 1
A DynamicFireworksAlgorithmGauss.ExplosionAmplitude() 0 2 1
A DynamicFireworksAlgorithmGauss.initAmplitude() 0 12 1
A FireworksAlgorithm.GaussianSpark() 0 11 1
A DynamicFireworksAlgorithmGauss.initPopulation() 0 17 1
A EnhancedFireworksAlgorithm.algorithmInfo() 0 11 1
A DynamicFireworksAlgorithmGauss.runIteration() 0 33 2
A EnhancedFireworksAlgorithm.runIteration() 0 36 2
A DynamicFireworksAlgorithmGauss.uCF() 0 23 3
A EnhancedFireworksAlgorithm.uAmin() 0 12 1
A FireworksAlgorithm.runIteration() 0 37 2
A FireworksAlgorithm.ExplodeSpark() 0 12 1
A DynamicFireworksAlgorithmGauss.algorithmInfo() 0 11 1
A EnhancedFireworksAlgorithm.GaussianSpark() 0 12 1
A FireworksAlgorithm.NextGeneration() 0 23 2
A DynamicFireworksAlgorithmGauss.typeParameters() 17 17 5
A DynamicFireworksAlgorithmGauss.repair() 0 14 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like NiaPy.algorithms.basic.fwa often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# encoding=utf8
2
import logging
3
from numpy import apply_along_axis, argmin, argmax, sum, sqrt, round, argsort, fabs, asarray, where
4
from NiaPy.algorithms.algorithm import Algorithm
5
from NiaPy.util import fullArray
6
7
logging.basicConfig()
8
logger = logging.getLogger('NiaPy.algorithms.basic')
9
logger.setLevel('INFO')
10
11
__all__ = ['FireworksAlgorithm', 'EnhancedFireworksAlgorithm', 'DynamicFireworksAlgorithm', 'DynamicFireworksAlgorithmGauss', 'BareBonesFireworksAlgorithm']
12
13
class BareBonesFireworksAlgorithm(Algorithm):
14
	r"""Implementation of Bare Bones Fireworks Algorithm.
15
16
	Algorithm:
17
		Bare Bones Fireworks Algorithm
18
19
	Date:
20
		2018
21
22
	Authors:
23
		Klemen Berkovič
24
25
	License:
26
		MIT
27
28
	Reference URL:
29
		https://www.sciencedirect.com/science/article/pii/S1568494617306609
30
31
	Reference paper:
32
		Junzhi Li, Ying Tan, The bare bones fireworks algorithm: A minimalist global optimizer, Applied Soft Computing, Volume 62, 2018, Pages 454-462, ISSN 1568-4946, https://doi.org/10.1016/j.asoc.2017.10.046.
33
34
	Attributes:
35
		Name (lsit of str): List of strings representing algorithm names
36
		n (int): Number of spraks
37
		C_a (float): amplification coefficient
38
		C_r (float): reduction coefficient
39
	"""
40
	Name = ['BareBonesFireworksAlgorithm', 'BBFWA']
41
42
	@staticmethod
43
	def algorithmInfo():
44
		r"""Get default information of algorithm.
45
46
		Returns:
47
			str: Basic information.
48
49
		See Also:
50
			* :func:`NiaPy.algorithms.Algorithm.algorithmInfo`
51
		"""
52
		return r"""Junzhi Li, Ying Tan, The bare bones fireworks algorithm: A minimalist global optimizer, Applied Soft Computing, Volume 62, 2018, Pages 454-462, ISSN 1568-4946, https://doi.org/10.1016/j.asoc.2017.10.046."""
53
54
	@staticmethod
55
	def typeParameters(): return {
56
			'n': lambda x: isinstance(x, int) and x > 0,
57
			'C_a': lambda x: isinstance(x, (float, int)) and x > 1,
58
			'C_r': lambda x: isinstance(x, (float, int)) and 0 < x < 1
59
	}
60
61
	def setParameters(self, n=10, C_a=1.5, C_r=0.5, **ukwargs):
62
		r"""Set the arguments of an algorithm.
63
64
		Arguments:
65
			n (int): Number of sparks :math:`\in [1, \infty)`.
66
			C_a (float): Amplification coefficient :math:`\in [1, \infty)`.
67
			C_r (float): Reduction coefficient :math:`\in (0, 1)`.
68
		"""
69
		ukwargs.pop('NP', None)
70
		Algorithm.setParameters(self, NP=1, **ukwargs)
71
		self.n, self.C_a, self.C_r = n, C_a, C_r
72
73
	def initPopulation(self, task):
74
		r"""Initialize starting population.
75
76
		Args:
77
			task (Task): Optimization task.
78
79
		Returns:
80
			Tuple[numpy.ndarray, float, Dict[str, Any]]:
81
				1. Initial solution.
82
				2. Initial solution function/fitness value.
83
				3. Additional arguments:
84
					* A (numpy.ndarray): Starting aplitude or search range.
85
		"""
86
		x, x_fit, d = Algorithm.initPopulation(self, task)
87
		d.update({'A': task.bRange})
88
		return x, x_fit, d
89
90
	def runIteration(self, task, x, x_fit, xb, fxb, A, **dparams):
91
		r"""Core function of Bare Bones Fireworks Algorithm.
92
93
		Args:
94
			task (Task): Optimization task.
95
			x (numpy.ndarray): Current solution.
96
			x_fit (float): Current solution fitness/function value.
97
			xb (numpy.ndarray): Current best solution.
98
			fxb (float): Current best solution fitness/function value.
99
			A (numpy.ndarray): Serach range.
100
			dparams (Dict[str, Any]): Additional parameters.
101
102
		Returns:
103
			Tuple[numpy.ndarray, float, numpy.ndarray, float, Dict[str, Any]]:
104
				1. New solution.
105
				2. New solution fitness/function value.
106
				3. New global best solution.
107
				4. New global best solutions fitness/objective value.
108
				5. Additional arguments:
109
					* A (numpy.ndarray): Serach range.
110
		"""
111
		S = apply_along_axis(task.repair, 1, self.uniform(x - A, x + A, [self.n, task.D]), self.Rand)
112
		S_fit = apply_along_axis(task.eval, 1, S)
113
		iS = argmin(S_fit)
114
		if S_fit[iS] < x_fit: x, x_fit, A = S[iS], S_fit[iS], self.C_a * A
115
		else: A = self.C_r * A
116
		return x, x_fit, x.copy(), x_fit, {'A': A}
117
118
class FireworksAlgorithm(Algorithm):
119
	r"""Implementation of fireworks algorithm.
120
121
	Algorithm:
122
		Fireworks Algorithm
123
124
	Date:
125
		2018
126
127
	Authors:
128
		Klemen Berkovič
129
130
	License:
131
		MIT
132
133
	Reference URL:
134
		https://www.springer.com/gp/book/9783662463529
135
136
	Reference paper:
137
		Tan, Ying. "Fireworks algorithm." Heidelberg, Germany: Springer 10 (2015): 978-3
138
139
	Attributes:
140
		Name (List[str]): List of stirngs representing algorithm names.
141
	"""
142
	Name = ['FireworksAlgorithm', 'FWA']
143
144
	@staticmethod
145
	def algorithmInfo():
146
		r"""Get default information of algorithm.
147
148
		Returns:
149
			str: Basic information.
150
151
		See Also:
152
			* :func:`NiaPy.algorithms.Algorithm.algorithmInfo`
153
		"""
154
		return r"""Tan, Ying. "Fireworks algorithm." Heidelberg, Germany: Springer 10 (2015): 978-3."""
155
156 View Code Duplication
	@staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
157
	def typeParameters(): return {
158
			'N': lambda x: isinstance(x, int) and x > 0,
159
			'm': lambda x: isinstance(x, int) and x > 0,
160
			'a': lambda x: isinstance(x, (int, float)) and x > 0,
161
			'b': lambda x: isinstance(x, (int, float)) and x > 0,
162
			'epsilon': lambda x: isinstance(x, float) and 0 < x < 1
163
	}
164
165
	def setParameters(self, N=40, m=40, a=1, b=2, A=40, epsilon=1e-31, **ukwargs):
166
		r"""Set the arguments of an algorithm.
167
168
		Arguments:
169
			N (int): Number of Fireworks
170
			m (int): Number of sparks
171
			a (int): Limitation of sparks
172
			b (int): Limitation of sparks
173
			A (float): --
174
			epsilon (float): Small number for non 0 devision
175
		"""
176
		Algorithm.setParameters(self, NP=N, **ukwargs)
177
		self.m, self.a, self.b, self.A, self.epsilon = m, a, b, A, epsilon
178
179
	def initAmplitude(self, task):
180
		r"""Initialize amplitudes for dimensions.
181
182
		Args:
183
			task (Task): Optimization task.
184
185
		Returns:
186
			numpy.ndarray[float]: Starting amplitudes.
187
		"""
188
		return fullArray(self.A, task.D)
189
190
	def SparsksNo(self, x_f, xw_f, Ss):
191
		r"""Calculate number of sparks based on function value of individual.
192
193
		Args:
194
			x_f (float): Individuals function/fitness value.
195
			xw_f (float): Worst individual function/fitness value.
196
			Ss (): TODO
197
198
		Returns:
199
			int: Number of sparks that individual will create.
200
		"""
201
		s = self.m * (xw_f - x_f + self.epsilon) / (Ss + self.epsilon)
202
		return round(self.b * self.m) if s > self.b * self.m and self.a < self.b < 1 else round(self.a * self.m)
203
204
	def ExplosionAmplitude(self, x_f, xb_f, A, As):
205
		r"""Calculate explosion amplitude.
206
207
		Args:
208
			x_f (float): Individuals function/fitness value.
209
			xb_f (float): Best individuals function/fitness value.
210
			A (numpy.ndarray): Amplitudes.
211
			As ():
212
213
		Returns:
214
			numpy.ndarray: TODO.
215
		"""
216
		return A * (x_f - xb_f - self.epsilon) / (As + self.epsilon)
217
218
	def ExplodeSpark(self, x, A, task):
219
		r"""Explode a spark.
220
221
		Args:
222
			x (numpy.ndarray): Individuals creating spark.
223
			A (numpy.ndarray): Amplitude of spark.
224
			task (Task): Optimization task.
225
226
		Returns:
227
			numpy.ndarray: Sparks exploded in with specified amplitude.
228
		"""
229
		return self.Mapping(x + self.rand(task.D) * self.uniform(-A, A, task.D), task)
230
231
	def GaussianSpark(self, x, task):
232
		r"""Create gaussian spark.
233
234
		Args:
235
			x (numpy.ndarray): Individual creating a spark.
236
			task (Task): Optimization task.
237
238
		Returns:
239
			numpy.ndarray: Spark exploded based on gaussian amplitude.
240
		"""
241
		return self.Mapping(x + self.rand(task.D) * self.normal(1, 1, task.D), task)
242
243 View Code Duplication
	def Mapping(self, x, task):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
244
		r"""Fix value to bounds..
245
246
		Args:
247
			x (numpy.ndarray): Individual to fix.
248
			task (Task): Optimization task.
249
250
		Returns:
251
			numpy.ndarray: Individual in search range.
252
		"""
253
		ir = where(x > task.Upper)
254
		x[ir] = task.Lower[ir] + x[ir] % task.bRange[ir]
255
		ir = where(x < task.Lower)
256
		x[ir] = task.Lower[ir] + x[ir] % task.bRange[ir]
257
		return x
258
259
	def R(self, x, FW):
260
		r"""Calculate ranges.
261
262
		Args:
263
			x (numpy.ndarray): Individual in population.
264
			FW (numpy.ndarray): Current population.
265
266
		Returns:
267
			numpy,ndarray[float]: Ranges values.
268
		"""
269
		return sqrt(sum(fabs(x - FW)))
270
271
	def p(self, r, Rs):
272
		r"""Calculate p.
273
274
		Args:
275
			r (float): Range of individual.
276
			Rs (float): Sum of ranges.
277
278
		Returns:
279
			float: p value.
280
		"""
281
		return r / Rs
282
283
	def NextGeneration(self, FW, FW_f, FWn, task):
284
		r"""Generate new generation of individuals.
285
286
		Args:
287
			FW (numpy.ndarray): Current population.
288
			FW_f (numpy.ndarray[float]): Currents population fitness/function values.
289
			FWn (numpy.ndarray): New population.
290
			task (Task): Optimization task.
291
292
		Returns:
293
			Tuple[numpy.ndarray, numpy.ndarray[float]]:
294
				1. New population.
295
				2. New populations fitness/function values.
296
		"""
297
		FWn_f = apply_along_axis(task.eval, 1, FWn)
298
		ib = argmin(FWn_f)
299
		if FWn_f[ib] < FW_f[0]: FW[0], FW_f[0] = FWn[ib], FWn_f[ib]
300
		R = asarray([self.R(FWn[i], FWn) for i in range(len(FWn))])
301
		Rs = sum(R)
302
		P = asarray([self.p(R[i], Rs) for i in range(len(FWn))])
303
		isort = argsort(P)[-(self.NP - 1):]
304
		FW[1:], FW_f[1:] = asarray(FWn)[isort], FWn_f[isort]
305
		return FW, FW_f
306
307
	def initPopulation(self, task):
308
		r"""Initialize starting population.
309
310
		Args:
311
			task (Task): Optimization task.
312
313
		Returns:
314
			Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
315
				1. Initialized population.
316
				2. Initialized populations function/fitness values.
317
				3. Additional arguments:
318
					* Ah (numpy.ndarray): Initialized amplitudes.
319
320
		See Also:
321
			* :func:`NiaPy.algorithms.algorithm.Algorithm.initPopulation`
322
		"""
323
		FW, FW_f, d = Algorithm.initPopulation(self, task)
324
		Ah = self.initAmplitude(task)
325
		d.update({'Ah': Ah})
326
		return FW, FW_f, d
327
328
	def runIteration(self, task, FW, FW_f, xb, fxb, Ah, **dparams):
329
		r"""Core function of Fireworks algorithm.
330
331
		Args:
332
			task (Task): Optimization task.
333
			FW (numpy.ndarray): Current population.
334
			FW_f (numpy.ndarray[float]): Current populations function/fitness values.
335
			xb (numpy.ndarray): Global best individual.
336
			fxb (float): Global best individuals fitness/function value.
337
			Ah (numpy.ndarray): Current amplitudes.
338
			**dparams (Dict[str, Any)]: Additional arguments
339
340
		Returns:
341
			Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]:
342
				1. Initialized population.
343
				2. Initialized populations function/fitness values.
344
				3. New global best solution.
345
				4. New global best solutions fitness/objective value.
346
				5. Additional arguments:
347
					* Ah (numpy.ndarray): Initialized amplitudes.
348
349
		See Also:
350
			* :func:`FireworksAlgorithm.SparsksNo`.
351
			* :func:`FireworksAlgorithm.ExplosionAmplitude`
352
			* :func:`FireworksAlgorithm.ExplodeSpark`
353
			* :func:`FireworksAlgorithm.GaussianSpark`
354
			* :func:`FireworksAlgorithm.NextGeneration`
355
		"""
356
		iw, ib = argmax(FW_f), 0
357
		Ss, As = sum(FW_f[iw] - FW_f), sum(FW_f - FW_f[ib])
358
		S = [self.SparsksNo(FW_f[i], FW_f[iw], Ss) for i in range(self.NP)]
359
		A = [self.ExplosionAmplitude(FW_f[i], FW_f[ib], Ah, As) for i in range(self.NP)]
360
		FWn = [self.ExplodeSpark(FW[i], A[i], task) for i in range(self.NP) for _ in range(S[i])]
361
		for i in range(self.m): FWn.append(self.GaussianSpark(self.randint(self.NP), task))
362
		FW, FW_f = self.NextGeneration(FW, FW_f, FWn, task)
363
		xb, fxb = self.getBest(FW, FW_f, xb, fxb)
364
		return FW, FW_f, xb, fxb, {'Ah': Ah}
365
366
class EnhancedFireworksAlgorithm(FireworksAlgorithm):
367
	r"""Implementation of enganced fireworks algorithm.
368
369
	Algorithm:
370
		Enhanced Fireworks Algorithm
371
372
	Date:
373
		2018
374
375
	Authors:
376
		Klemen Berkovič
377
378
	License:
379
		MIT
380
381
	Reference URL:
382
		https://ieeexplore.ieee.org/document/6557813/
383
384
	Reference paper:
385
		S. Zheng, A. Janecek and Y. Tan, "Enhanced Fireworks Algorithm," 2013 IEEE Congress on Evolutionary Computation, Cancun, 2013, pp. 2069-2077. doi: 10.1109/CEC.2013.6557813
386
387
	Attributes:
388
		Name (List[str]): List of strings representing algorithm names.
389
		Ainit (float): Initial amplitude of sparks.
390
		Afinal (float): Maximal amplitude of sparks.
391
	"""
392
	Name = ['EnhancedFireworksAlgorithm', 'EFWA']
393
394
	@staticmethod
395
	def algorithmInfo():
396
		r"""Get default information of algorithm.
397
398
		Returns:
399
			str: Basic information.
400
401
		See Also:
402
			* :func:`NiaPy.algorithms.Algorithm.algorithmInfo`
403
		"""
404
		return r"""S. Zheng, A. Janecek and Y. Tan, "Enhanced Fireworks Algorithm," 2013 IEEE Congress on Evolutionary Computation, Cancun, 2013, pp. 2069-2077. doi: 10.1109/CEC.2013.6557813"""
405
406
	@staticmethod
407
	def typeParameters():
408
		r"""Get dictionary with functions for checking values of parameters.
409
410
		Returns:
411
			Dict[str, Callable]:
412
				* Ainit (Callable[[Union[int, float]], bool]): TODO
413
				* Afinal (Callable[[Union[int, float]], bool]): TODO
414
415
		See Also:
416
			* :func:`FireworksAlgorithm.typeParameters`
417
		"""
418
		d = FireworksAlgorithm.typeParameters()
419
		d['Ainit'] = lambda x: isinstance(x, (float, int)) and x > 0
420
		d['Afinal'] = lambda x: isinstance(x, (float, int)) and x > 0
421
		return d
422
423
	def setParameters(self, Ainit=20, Afinal=5, **ukwargs):
424
		r"""Set EnhancedFireworksAlgorithm algorithms core parameters.
425
426
		Args:
427
			Ainit (float): TODO
428
			Afinal (float): TODO
429
			**ukwargs (Dict[str, Any]): Additional arguments.
430
431
		See Also:
432
			* :func:`FireworksAlgorithm.setParameters`
433
		"""
434
		FireworksAlgorithm.setParameters(self, **ukwargs)
435
		self.Ainit, self.Afinal = Ainit, Afinal
436
437
	def initRanges(self, task):
438
		r"""Initialize ranges.
439
440
		Args:
441
			task (Task): Optimization task.
442
443
		Returns:
444
			Tuple[numpy.ndarray[float], numpy.ndarray[float], numpy.ndarray[float]]:
445
				1. Initial amplitude values over dimensions.
446
				2. Final amplitude values over dimensions.
447
				3. uAmin.
448
		"""
449
		Ainit, Afinal = fullArray(self.Ainit, task.D), fullArray(self.Afinal, task.D)
450
		return Ainit, Afinal, self.uAmin(Ainit, Afinal, task)
451
452
	def uAmin(self, Ainit, Afinal, task):
453
		r"""Calculate the value of `uAmin`.
454
455
		Args:
456
			Ainit (numpy.ndarray[float]): Initial amplitude values over dimensions.
457
			Afinal (numpy.ndarray[float]): Final amplitude values over dimensions.
458
			task (Task): Optimization task.
459
460
		Returns:
461
			numpy.ndarray[float]: uAmin.
462
		"""
463
		return Ainit - sqrt(task.Evals * (2 * task.nFES - task.Evals)) * (Ainit - Afinal) / task.nFES
464
465
	def ExplosionAmplitude(self, x_f, xb_f, Ah, As, A_min=None):
466
		r"""Calculate explosion amplitude.
467
468
		Args:
469
			x_f (float): Individuals function/fitness value.
470
			xb_f (float): Best individual function/fitness value.
471
			Ah (numpy.ndarray):
472
			As (): TODO.
473
			A_min (Optional[numpy.ndarray]): Minimal amplitude values.
474
			task (Task): Optimization task.
475
476
		Returns:
477
			numpy.ndarray: New amplitude.
478
		"""
479
		A = FireworksAlgorithm.ExplosionAmplitude(self, x_f, xb_f, Ah, As)
480
		ifix = where(A < A_min)
481
		A[ifix] = A_min[ifix]
482
		return A
483
484
	def GaussianSpark(self, x, xb, task):
485
		r"""Create new individual.
486
487
		Args:
488
			x (numpy.ndarray):
489
			xb (numpy.ndarray):
490
			task (Task): Optimization task.
491
492
		Returns:
493
			numpy.ndarray: New individual generated by gaussian noise.
494
		"""
495
		return self.Mapping(x + self.rand(task.D) * (xb - x) * self.normal(1, 1, task.D), task)
496
497
	def NextGeneration(self, FW, FW_f, FWn, task):
498
		r"""Generate new population.
499
500
		Args:
501
			FW (numpy.ndarray): Current population.
502
			FW_f (numpy.ndarray[float]): Current populations fitness/function values.
503
			FWn (numpy.ndarray): New population.
504
			task (Task): Optimization task.
505
506
		Returns:
507
			Tuple[numpy.ndarray, numpy.ndarray[float]]:
508
				1. New population.
509
				2. New populations fitness/function values.
510
		"""
511
		FWn_f = apply_along_axis(task.eval, 1, FWn)
512
		ib = argmin(FWn_f)
513
		if FWn_f[ib] < FW_f[0]: FW[0], FW_f[0] = FWn[ib], FWn_f[ib]
514
		for i in range(1, self.NP):
515
			r = self.randint(len(FWn))
516
			if FWn_f[r] < FW_f[i]: FW[i], FW_f[i] = FWn[r], FWn_f[r]
517
		return FW, FW_f
518
519
	def initPopulation(self, task):
520
		r"""Initialize population.
521
522
		Args:
523
			task (Task): Optimization task.
524
525
		Returns:
526
			Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
527
				1. Initial population.
528
				2. Initial populations fitness/function values.
529
				3. Additional arguments:
530
					* Ainit (numpy.ndarray): Initial amplitude values.
531
					* Afinal (numpy.ndarray): Final amplitude values.
532
					* A_min (numpy.ndarray): Minimal amplitude values.
533
534
		See Also:
535
			* :func:`FireworksAlgorithm.initPopulation`
536
		"""
537
		FW, FW_f, d = FireworksAlgorithm.initPopulation(self, task)
538
		Ainit, Afinal, A_min = self.initRanges(task)
539
		d.update({'Ainit': Ainit, 'Afinal': Afinal, 'A_min': A_min})
540
		return FW, FW_f, d
541
542
	def runIteration(self, task, FW, FW_f, xb, fxb, Ah, Ainit, Afinal, A_min, **dparams):
543
		r"""Core function of EnhancedFireworksAlgorithm algorithm.
544
545
		Args:
546
			task (Task): Optimization task.
547
			FW (numpy.ndarray): Current population.
548
			FW_f (numpy.ndarray[float]): Current populations fitness/function values.
549
			xb (numpy.ndarray): Global best individual.
550
			fxb (float): Global best individuals function/fitness value.
551
			Ah (numpy.ndarray[float]): Current amplitude.
552
			Ainit (numpy.ndarray[float]): Initial amplitude.
553
			Afinal (numpy.ndarray[float]): Final amplitude values.
554
			A_min (numpy.ndarray[float]): Minial amplitude values.
555
			**dparams (Dict[str, Any]): Additional arguments.
556
557
		Returns:
558
			Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]:
559
				1. Initial population.
560
				2. Initial populations fitness/function values.
561
				3. New global best solution.
562
				4. New global best solutions fitness/objective value.
563
				5. Additional arguments:
564
					* Ainit (numpy.ndarray): Initial amplitude values.
565
					* Afinal (numpy.ndarray): Final amplitude values.
566
					* A_min (numpy.ndarray): Minimal amplitude values.
567
		"""
568
		iw, ib = argmax(FW_f), 0
569
		Ss, As = sum(FW_f[iw] - FW_f), sum(FW_f - FW_f[ib])
570
		S = [self.SparsksNo(FW_f[i], FW_f[iw], Ss) for i in range(self.NP)]
571
		A = [self.ExplosionAmplitude(FW_f[i], FW_f[ib], Ah, As, A_min) for i in range(self.NP)]
572
		A_min = self.uAmin(Ainit, Afinal, task)
573
		FWn = [self.ExplodeSpark(FW[i], A[i], task) for i in range(self.NP) for _ in range(S[i])]
574
		for i in range(self.m): FWn.append(self.GaussianSpark(self.randint(self.NP), FW[ib], task))
575
		FW, FW_f = self.NextGeneration(FW, FW_f, FWn, task)
576
		xb, fxb = self.getBest(FW, FW_f, xb, fxb)
577
		return FW, FW_f, xb, fxb, {'Ah': Ah, 'Ainit': Ainit, 'Afinal': Afinal, 'A_min': A_min}
578
579
class DynamicFireworksAlgorithmGauss(EnhancedFireworksAlgorithm):
580
	r"""Implementation of dynamic fireworks algorithm.
581
582
	Algorithm:
583
		Dynamic Fireworks Algorithm
584
585
	Date:
586
		2018
587
588
	Authors:
589
		Klemen Berkovič
590
591
	License:
592
		MIT
593
594
	Reference URL:
595
		http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=6900485&isnumber=6900223
596
597
	Reference paper:
598
		S. Zheng, A. Janecek, J. Li and Y. Tan, "Dynamic search in fireworks algorithm," 2014 IEEE Congress on Evolutionary Computation (CEC), Beijing, 2014, pp. 3222-3229. doi: 10.1109/CEC.2014.6900485
599
600
	Attributes:
601
		Name (List[str]): List of strings representing algorithm names.
602
		A_cf (Union[float, int]): TODO
603
		C_a (Union[float, int]): Amplification factor.
604
		C_r (Union[float, int]): Reduction factor.
605
		epsilon (Union[float, int]): Small value.
606
	"""
607
	Name = ['DynamicFireworksAlgorithmGauss', 'dynFWAG']
608
609
	@staticmethod
610
	def algorithmInfo():
611
		r"""Get default information of algorithm.
612
613
		Returns:
614
			str: Basic information.
615
616
		See Also:
617
			* :func:`NiaPy.algorithms.Algorithm.algorithmInfo`
618
		"""
619
		return r"""S. Zheng, A. Janecek, J. Li and Y. Tan, "Dynamic search in fireworks algorithm," 2014 IEEE Congress on Evolutionary Computation (CEC), Beijing, 2014, pp. 3222-3229. doi: 10.1109/CEC.2014.6900485"""
620
621 View Code Duplication
	@staticmethod
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
622
	def typeParameters():
623
		r"""Get dictionary with functions for checking values of parameters.
624
625
		Returns:
626
			Dict[str, Callable]:
627
				* A_cr (Callable[[Union[float, int], bool]): TODo
628
629
		See Also:
630
			* :func:`FireworksAlgorithm.typeParameters`
631
		"""
632
		d = FireworksAlgorithm.typeParameters()
633
		d['A_cf'] = lambda x: isinstance(x, (float, int)) and x > 0
634
		d['C_a'] = lambda x: isinstance(x, (float, int)) and x > 1
635
		d['C_r'] = lambda x: isinstance(x, (float, int)) and 0 < x < 1
636
		d['epsilon'] = lambda x: isinstance(x, (float, int)) and 0 < x < 1
637
		return d
638
639
	def setParameters(self, A_cf=20, C_a=1.2, C_r=0.9, epsilon=1e-8, **ukwargs):
640
		r"""Set core arguments of DynamicFireworksAlgorithmGauss.
641
642
		Args:
643
			A_cf (Union[int, float]):
644
			C_a (Union[int, float]):
645
			C_r (Union[int, float]):
646
			epsilon (Union[int, float]):
647
			**ukwargs (Dict[str, Any]): Additional arguments.
648
649
		See Also:
650
			* :func:`FireworksAlgorithm.setParameters`
651
		"""
652
		FireworksAlgorithm.setParameters(self, **ukwargs)
653
		self.A_cf, self.C_a, self.C_r, self.epsilon = A_cf, C_a, C_r, epsilon
654
655
	def initAmplitude(self, task):
656
		r"""Initialize amplitude.
657
658
		Args:
659
			task (Task): Optimization task.
660
661
		Returns:
662
			Tuple[numpy.ndarray, numpy.ndarray]:
663
				1. Initial amplitudes.
664
				2. Amplitude for best spark.
665
		"""
666
		return FireworksAlgorithm.initAmplitude(self, task), task.bRange
667
668
	def Mapping(self, x, task):
669
		r"""Fix out of bound solution/individual.
670
671
		Args:
672
			x (numpy.ndarray): Individual.
673
			task (Task): Optimization task.
674
675
		Returns:
676
			numpy.ndarray: Fixed individual.
677
		"""
678
		ir = where(x > task.Upper)
679
		x[ir] = self.uniform(task.Lower[ir], task.Upper[ir])
680
		ir = where(x < task.Lower)
681
		x[ir] = self.uniform(task.Lower[ir], task.Upper[ir])
682
		return x
683
684
	def repair(self, x, d, epsilon):
685
		r"""Repair solution.
686
687
		Args:
688
			x (numpy.ndarray): Individual.
689
			d (numpy.ndarray): Default value.
690
			epsilon (float): Limiting value.
691
692
		Returns:
693
			numpy.ndarray: Fixed solution.
694
		"""
695
		ir = where(x <= epsilon)
696
		x[ir] = d[ir]
697
		return x
698
699
	def NextGeneration(self, FW, FW_f, FWn, task):
700
		r"""TODO.
701
702
		Args:
703
			FW (numpy.ndarray): Current population.
704
			FW_f (numpy.ndarray[float]): Current populations function/fitness values.
705
			FWn (numpy.ndarray): New population.
706
			task (Task): Optimization task.
707
708
		Returns:
709
			Tuple[numpy.ndarray, numpy.ndarray[float]]:
710
				1. New population.
711
				2. New populations function/fitness values.
712
		"""
713
		FWn_f = apply_along_axis(task.eval, 1, FWn)
714
		ib = argmin(FWn_f)
715
		for i, f in enumerate(FW_f):
716
			r = self.randint(len(FWn))
717
			if FWn_f[r] < f: FW[i], FW_f[i] = FWn[r], FWn_f[r]
718
		FW[0], FW_f[0] = FWn[ib], FWn_f[ib]
719
		return FW, FW_f
720
721
	def uCF(self, xnb, xcb, xcb_f, xb, xb_f, Acf, task):
722
		r"""TODO.
723
724
		Args:
725
			xnb:
726
			xcb:
727
			xcb_f:
728
			xb:
729
			xb_f:
730
			Acf:
731
			task (Task): Optimization task.
732
733
		Returns:
734
			Tuple[numpy.ndarray, float, numpy.ndarray]:
735
				1. TODO
736
		"""
737
		xnb_f = apply_along_axis(task.eval, 1, xnb)
738
		ib_f = argmin(xnb_f)
739
		if xnb_f[ib_f] <= xb_f: xb, xb_f = xnb[ib_f], xnb_f[ib_f]
740
		Acf = self.repair(Acf, task.bRange, self.epsilon)
741
		if xb_f >= xcb_f: xb, xb_f, Acf = xcb, xcb_f, Acf * self.C_a
742
		else: Acf = Acf * self.C_r
743
		return xb, xb_f, Acf
744
745
	def ExplosionAmplitude(self, x_f, xb_f, Ah, As, A_min=None):
746
		return FireworksAlgorithm.ExplosionAmplitude(self, x_f, xb_f, Ah, As)
747
748
	def initPopulation(self, task):
749
		r"""Initialize population.
750
751
		Args:
752
			task (Task): Optimization task.
753
754
		Returns:
755
			Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
756
				1. Initialized population.
757
				2. Initialized population function/fitness values.
758
				3. Additional arguments:
759
					* Ah (): TODO
760
					* Ab (): TODO
761
		"""
762
		FW, FW_f, _ = Algorithm.initPopulation(self, task)
763
		Ah, Ab = self.initAmplitude(task)
764
		return FW, FW_f, {'Ah': Ah, 'Ab': Ab}
765
766
	def runIteration(self, task, FW, FW_f, xb, fxb, Ah, Ab, **dparams):
767
		r"""Core function of DynamicFireworksAlgorithmGauss algorithm.
768
769
		Args:
770
			task (Task): Optimization task.
771
			FW (numpy.ndarray): Current population.
772
			FW_f (numpy.ndarray): Current populations function/fitness values.
773
			xb (numpy.ndarray): Global best individual.
774
			fxb (float): Global best fitness/function value.
775
			Ah (Union[numpy.ndarray, float]): TODO
776
			Ab (Union[numpy.ndarray, float]): TODO
777
			**dparams (Dict[str, Any]): Additional arguments.
778
779
		Returns:
780
			Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]:
781
				1. New population.
782
				2. New populations fitness/function values.
783
				3. New global best solution.
784
				4. New global best solutions fitness/objective value.
785
				5. Additional arguments:
786
					* Ah (Union[numpy.ndarray, float]): TODO
787
					* Ab (Union[numpy.ndarray, float]): TODO
788
		"""
789
		iw, ib = argmax(FW_f), argmin(FW_f)
790
		Ss, As = sum(FW_f[iw] - FW_f), sum(FW_f - FW_f[ib])
791
		S, sb = [self.SparsksNo(FW_f[i], FW_f[iw], Ss) for i in range(len(FW))], self.SparsksNo(fxb, FW_f[iw], Ss)
792
		A = [self.ExplosionAmplitude(FW_f[i], FW_f[ib], Ah, As) for i in range(len(FW))]
793
		FWn, xnb = [self.ExplodeSpark(FW[i], A[i], task) for i in range(self.NP) for _ in range(S[i])], [self.ExplodeSpark(xb, Ab, task) for _ in range(sb)]
794
		for i in range(self.m): FWn.append(self.GaussianSpark(self.randint(self.NP), FW[ib], task))
795
		FW, FW_f = self.NextGeneration(FW, FW_f, FWn, task)
796
		iw, ib = argmax(FW_f), 0
797
		xb, fxb, Ab = self.uCF(xnb, FW[ib], FW_f[ib], xb, fxb, Ab, task)
798
		return FW, FW_f, xb, fxb, {'Ah': Ah, 'Ab': Ab}
799
800
class DynamicFireworksAlgorithm(DynamicFireworksAlgorithmGauss):
801
	r"""Implementation of dynamic fireworks algorithm.
802
803
	Algorithm:
804
		Dynamic Fireworks Algorithm
805
806
	Date:
807
		2018
808
809
	Authors:
810
		Klemen Berkovič
811
812
	License:
813
		MIT
814
815
	Reference URL:
816
		http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=6900485&isnumber=6900223
817
818
	Reference paper:
819
		S. Zheng, A. Janecek, J. Li and Y. Tan, "Dynamic search in fireworks algorithm," 2014 IEEE Congress on Evolutionary Computation (CEC), Beijing, 2014, pp. 3222-3229. doi: 10.1109/CEC.2014.6900485
820
821
	Attributes:
822
		Name (List[str]): List of strings representing algorithm name.
823
824
	See Also:
825
		* :class:`NiaPy.algorithms.basic.DynamicFireworksAlgorithmGauss`
826
	"""
827
	Name = ['DynamicFireworksAlgorithm', 'dynFWA']
828
829
	@staticmethod
830
	def algorithmInfo():
831
		r"""Get default information of algorithm.
832
833
		Returns:
834
			str: Basic information.
835
836
		See Also:
837
			* :func:`NiaPy.algorithms.Algorithm.algorithmInfo`
838
		"""
839
		return r"""S. Zheng, A. Janecek, J. Li and Y. Tan, "Dynamic search in fireworks algorithm," 2014 IEEE Congress on Evolutionary Computation (CEC), Beijing, 2014, pp. 3222-3229. doi: 10.1109/CEC.2014.6900485"""
840
841
	def runIteration(self, task, FW, FW_f, xb, fxb, Ah, Ab, **dparams):
842
		r"""Core function of Dynamic Fireworks Algorithm.
843
844
		Args:
845
			task (Task): Optimization task
846
			FW (numpy.ndarray): Current population
847
			FW_f (numpy.ndarray[float]): Current population fitness/function values
848
			xb (numpy.ndarray): Current best solution
849
			fxb (float): Current best solution's fitness/function value
850
			Ah (): TODO
851
			Ab (): TODO
852
			**dparams:
853
854
		Returns:
855
			Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
856
				1. New population.
857
				2. New population function/fitness values.
858
				3. Additional arguments:
859
					* Ah (): TODO
860
					* Ab (): TODO
861
		"""
862
		iw, ib = argmax(FW_f), argmin(FW_f)
863
		Ss, As = sum(FW_f[iw] - FW_f), sum(FW_f - FW_f[ib])
864
		S, sb = [self.SparsksNo(FW_f[i], FW_f[iw], Ss) for i in range(len(FW))], self.SparsksNo(fxb, FW_f[iw], Ss)
865
		A = [self.ExplosionAmplitude(FW_f[i], FW_f[ib], Ah, As) for i in range(len(FW))]
866
		FWn, xnb = [self.ExplodeSpark(FW[i], A[i], task) for i in range(self.NP) for _ in range(S[i])], [self.ExplodeSpark(xb, Ab, task) for _ in range(sb)]
867
		FW, FW_f = self.NextGeneration(FW, FW_f, FWn, task)
868
		iw, ib = argmax(FW_f), 0
869
		xb, fxb, Ab = self.uCF(xnb, FW[ib], FW_f[ib], xb, fxb, Ab, task)
870
		return FW, FW_f, xb, fxb, {'Ah': Ah, 'Ab': Ab}
871
872
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
873