Passed
Pull Request — master (#202)
by Grega
01:02
created

DynamicFireworksAlgorithm.runIteration()   A

Complexity

Conditions 1

Size

Total Lines 30
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

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