Passed
Push — master ( 8465f7...8358a6 )
by Grega
01:08
created

DynamicFireworksAlgorithmGauss.algorithmInfo()   A

Complexity

Conditions 1

Size

Total Lines 11
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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