BareBonesFireworksAlgorithm.runIteration()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 27
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nop 8
dl 0
loc 27
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
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