| Total Complexity | 71 |
| Total Lines | 864 |
| Duplicated Lines | 4.51 % |
| Changes | 0 | ||
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like NiaPy.algorithms.basic.fwa often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # encoding=utf8 |
||
| 2 | # 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 | View Code Duplication | @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): |
|
| 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 |
|
| 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 | |||
| 866 |