Total Complexity | 95 |
Total Lines | 1035 |
Duplicated Lines | 16.81 % |
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.de 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, multiple-statements, line-too-long, unused-argument, no-self-use, no-self-use, attribute-defined-outside-init, logging-not-lazy, len-as-condition, singleton-comparison, arguments-differ, bad-continuation, dangerous-default-value, keyword-arg-before-vararg |
||
3 | import logging |
||
4 | |||
5 | from numpy import random as rand, argmin, argmax, mean, cos, asarray, append, sin |
||
6 | from scipy.spatial.distance import euclidean |
||
7 | |||
8 | from NiaPy.algorithms.algorithm import Algorithm, Individual, defaultIndividualInit |
||
9 | from NiaPy.util.utility import objects2array |
||
10 | |||
11 | __all__ = ['DifferentialEvolution', 'DynNpDifferentialEvolution', 'AgingNpDifferentialEvolution', 'CrowdingDifferentialEvolution', 'MultiStrategyDifferentialEvolution', 'DynNpMultiStrategyDifferentialEvolution', 'AgingNpMultiMutationDifferentialEvolution', 'AgingIndividual', 'CrossRand1', 'CrossBest2', 'CrossBest1', 'CrossBest2', 'CrossCurr2Rand1', 'CrossCurr2Best1', 'multiMutations'] |
||
12 | |||
13 | logging.basicConfig() |
||
14 | logger = logging.getLogger('NiaPy.algorithms.basic') |
||
15 | logger.setLevel('INFO') |
||
16 | |||
17 | View Code Duplication | def CrossRand1(pop, ic, x_b, f, cr, rnd=rand, *args): |
|
|
|||
18 | r"""Mutation strategy with crossover. |
||
19 | |||
20 | Mutation strategy uses three different random individuals from population to perform mutation. |
||
21 | |||
22 | Mutation: |
||
23 | Name: DE/rand/1 |
||
24 | |||
25 | :math:`\mathbf{x}_{r_1, G} + F \cdot (\mathbf{x}_{r_2, G} - \mathbf{x}_{r_3, G}` |
||
26 | where :math:`r_1, r_2, r_3` are random indexes representing current population individuals. |
||
27 | |||
28 | Crossover: |
||
29 | Name: Binomial crossover |
||
30 | |||
31 | :math:`\mathbf{x}_{i, G+1} = \begin{cases} \mathbf{u}_{i, G+1}, & \text{if $f(\mathbf{u}_{i, G+1}) \leq f(\mathbf{x}_{i, G})$}, \\ \mathbf{x}_{i, G}, & \text{otherwise}. \end{cases}` |
||
32 | |||
33 | Args: |
||
34 | pop (numpy.ndarray[Individual]): Current population. |
||
35 | ic (int): Index of individual being mutated. |
||
36 | x_b (Individual): Current global best individual. |
||
37 | f (float): Scale factor. |
||
38 | cr (float): Crossover probability. |
||
39 | rnd (mtrand.RandomState): Random generator. |
||
40 | *args (list): Additional arguments. |
||
41 | |||
42 | Returns: |
||
43 | numpy.ndarray: Mutated and mixed individual. |
||
44 | """ |
||
45 | j = rnd.randint(len(pop[ic])) |
||
46 | p = [1 / (len(pop) - 1.0) if i != ic else 0 for i in range(len(pop))] if len(pop) > 3 else None |
||
47 | r = rnd.choice(len(pop), 3, replace=not len(pop) >= 3, p=p) |
||
48 | x = [pop[r[0]][i] + f * (pop[r[1]][i] - pop[r[2]][i]) if rnd.rand() < cr or i == j else pop[ic][i] for i in range(len(pop[ic]))] |
||
49 | return asarray(x) |
||
50 | |||
51 | View Code Duplication | def CrossBest1(pop, ic, x_b, f, cr, rnd=rand, *args): |
|
52 | r"""Mutation strategy with crossover. |
||
53 | |||
54 | Mutation strategy uses two different random individuals from population and global best individual. |
||
55 | |||
56 | Mutation: |
||
57 | Name: de/best/1 |
||
58 | |||
59 | :math:`\mathbf{v}_{i, G} = \mathbf{x}_{best, G} + F \cdot (\mathbf{x}_{r_1, G} - \mathbf{x}_{r_2, G})` |
||
60 | where :math:`r_1, r_2` are random indexes representing current population individuals. |
||
61 | |||
62 | Crossover: |
||
63 | Name: Binomial crossover |
||
64 | |||
65 | :math:`\mathbf{x}_{i, G+1} = \begin{cases} \mathbf{u}_{i, G+1}, & \text{if $f(\mathbf{u}_{i, G+1}) \leq f(\mathbf{x}_{i, G})$}, \\ \mathbf{x}_{i, G}, & \text{otherwise}. \end{cases}` |
||
66 | |||
67 | args: |
||
68 | pop (numpy.ndarray[Individual]): Current population. |
||
69 | ic (int): Index of individual being mutated. |
||
70 | x_b (Individual): Current global best individual. |
||
71 | f (float): Scale factor. |
||
72 | cr (float): Crossover probability. |
||
73 | rnd (mtrand.RandomState): Random generator. |
||
74 | *args (list): Additional arguments. |
||
75 | |||
76 | returns: |
||
77 | numpy.ndarray: Mutated and mixed individual. |
||
78 | """ |
||
79 | j = rnd.randint(len(pop[ic])) |
||
80 | p = [1 / (len(pop) - 1.0) if i != ic else 0 for i in range(len(pop))] if len(pop) > 2 else None |
||
81 | r = rnd.choice(len(pop), 2, replace=not len(pop) >= 2, p=p) |
||
82 | x = [x_b[i] + f * (pop[r[0]][i] - pop[r[1]][i]) if rnd.rand() < cr or i == j else pop[ic][i] for i in range(len(pop[ic]))] |
||
83 | return asarray(x) |
||
84 | |||
85 | View Code Duplication | def CrossRand2(pop, ic, x_b, f, cr, rnd=rand, *args): |
|
86 | r"""Mutation strategy with crossover. |
||
87 | |||
88 | Mutation strategy uses five different random individuals from population. |
||
89 | |||
90 | Mutation: |
||
91 | Name: de/best/1 |
||
92 | |||
93 | :math:`\mathbf{v}_{i, G} = \mathbf{x}_{r_1, G} + F \cdot (\mathbf{x}_{r_2, G} - \mathbf{x}_{r_3, G}) + F \cdot (\mathbf{x}_{r_4, G} - \mathbf{x}_{r_5, G})` |
||
94 | where :math:`r_1, r_2, r_3, r_4, r_5` are random indexes representing current population individuals. |
||
95 | |||
96 | Crossover: |
||
97 | Name: Binomial crossover |
||
98 | |||
99 | :math:`\mathbf{x}_{i, G+1} = \begin{cases} \mathbf{u}_{i, G+1}, & \text{if $f(\mathbf{u}_{i, G+1}) \leq f(\mathbf{x}_{i, G})$}, \\ \mathbf{x}_{i, G}, & \text{otherwise}. \end{cases}` |
||
100 | |||
101 | Args: |
||
102 | pop (numpy.ndarray[Individual]): Current population. |
||
103 | ic (int): Index of individual being mutated. |
||
104 | x_b (Individual): Current global best individual. |
||
105 | f (float): Scale factor. |
||
106 | cr (float): Crossover probability. |
||
107 | rnd (mtrand.RandomState): Random generator. |
||
108 | *args (list): Additional arguments. |
||
109 | |||
110 | Returns: |
||
111 | numpy.ndarray: mutated and mixed individual. |
||
112 | """ |
||
113 | j = rnd.randint(len(pop[ic])) |
||
114 | p = [1 / (len(pop) - 1.0) if i != ic else 0 for i in range(len(pop))] if len(pop) > 5 else None |
||
115 | r = rnd.choice(len(pop), 5, replace=not len(pop) >= 5, p=p) |
||
116 | x = [pop[r[0]][i] + f * (pop[r[1]][i] - pop[r[2]][i]) + f * (pop[r[3]][i] - pop[r[4]][i]) if rnd.rand() < cr or i == j else pop[ic][i] for i in range(len(pop[ic]))] |
||
117 | return asarray(x) |
||
118 | |||
119 | View Code Duplication | def CrossBest2(pop, ic, x_b, f, cr, rnd=rand, *args): |
|
120 | r"""Mutation strategy with crossover. |
||
121 | |||
122 | Mutation: |
||
123 | Name: de/best/2 |
||
124 | |||
125 | :math:`\mathbf{v}_{i, G} = \mathbf{x}_{best, G} + F \cdot (\mathbf{x}_{r_1, G} - \mathbf{x}_{r_2, G}) + F \cdot (\mathbf{x}_{r_3, G} - \mathbf{x}_{r_4, G})` |
||
126 | where :math:`r_1, r_2, r_3, r_4` are random indexes representing current population individuals. |
||
127 | |||
128 | Crossover: |
||
129 | Name: Binomial crossover |
||
130 | |||
131 | :math:`\mathbf{x}_{i, G+1} = \begin{cases} \mathbf{u}_{i, G+1}, & \text{if $f(\mathbf{u}_{i, G+1}) \leq f(\mathbf{x}_{i, G})$}, \\ \mathbf{x}_{i, G}, & \text{otherwise}. \end{cases}` |
||
132 | |||
133 | Args: |
||
134 | pop (numpy.ndarray[Individual]): Current population. |
||
135 | ic (int): Index of individual being mutated. |
||
136 | x_b (Individual): Current global best individual. |
||
137 | f (float): Scale factor. |
||
138 | cr (float): Crossover probability. |
||
139 | rnd (mtrand.RandomState): Random generator. |
||
140 | *args (list): Additional arguments. |
||
141 | |||
142 | Returns: |
||
143 | numpy.ndarray: mutated and mixed individual. |
||
144 | """ |
||
145 | j = rnd.randint(len(pop[ic])) |
||
146 | p = [1 / (len(pop) - 1.0) if i != ic else 0 for i in range(len(pop))] if len(pop) > 4 else None |
||
147 | r = rnd.choice(len(pop), 4, replace=not len(pop) >= 4, p=p) |
||
148 | x = [x_b[i] + f * (pop[r[0]][i] - pop[r[1]][i]) + f * (pop[r[2]][i] - pop[r[3]][i]) if rnd.rand() < cr or i == j else pop[ic][i] for i in range(len(pop[ic]))] |
||
149 | return asarray(x) |
||
150 | |||
151 | View Code Duplication | def CrossCurr2Rand1(pop, ic, x_b, f, cr, rnd=rand, *args): |
|
152 | r"""Mutation strategy with crossover. |
||
153 | |||
154 | Mutation: |
||
155 | Name: de/curr2rand/1 |
||
156 | |||
157 | :math:`\mathbf{v}_{i, G} = \mathbf{x}_{i, G} + F \cdot (\mathbf{x}_{r_1, G} - \mathbf{x}_{r_2, G}) + F \cdot (\mathbf{x}_{r_3, G} - \mathbf{x}_{r_4, G})` |
||
158 | where :math:`r_1, r_2, r_3, r_4` are random indexes representing current population individuals |
||
159 | |||
160 | Crossover: |
||
161 | Name: Binomial crossover |
||
162 | |||
163 | :math:`\mathbf{x}_{i, G+1} = \begin{cases} \mathbf{u}_{i, G+1}, & \text{if $f(\mathbf{u}_{i, G+1}) \leq f(\mathbf{x}_{i, G})$}, \\ \mathbf{x}_{i, G}, & \text{otherwise}. \end{cases}` |
||
164 | |||
165 | Args: |
||
166 | pop (numpy.ndarray[Individual]): Current population. |
||
167 | ic (int): Index of individual being mutated. |
||
168 | x_b (Individual): Current global best individual. |
||
169 | f (float): Scale factor. |
||
170 | cr (float): Crossover probability. |
||
171 | rnd (mtrand.RandomState): Random generator. |
||
172 | *args (list): Additional arguments. |
||
173 | |||
174 | Returns: |
||
175 | numpy.ndarray: mutated and mixed individual. |
||
176 | """ |
||
177 | j = rnd.randint(len(pop[ic])) |
||
178 | p = [1 / (len(pop) - 1.0) if i != ic else 0 for i in range(len(pop))] if len(pop) > 4 else None |
||
179 | r = rnd.choice(len(pop), 4, replace=not len(pop) >= 4, p=p) |
||
180 | x = [pop[ic][i] + f * (pop[r[0]][i] - pop[r[1]][i]) + f * (pop[r[2]][i] - pop[r[3]][i]) if rnd.rand() < cr or i == j else pop[ic][i] for i in range(len(pop[ic]))] |
||
181 | return asarray(x) |
||
182 | |||
183 | def CrossCurr2Best1(pop, ic, x_b, f, cr, rnd=rand, **kwargs): |
||
184 | r"""Mutation strategy with crossover. |
||
185 | |||
186 | Mutation: |
||
187 | Name: de/curr-to-best/1 |
||
188 | |||
189 | :math:`\mathbf{v}_{i, G} = \mathbf{x}_{i, G} + F \cdot (\mathbf{x}_{r_1, G} - \mathbf{x}_{r_2, G}) + F \cdot (\mathbf{x}_{r_3, G} - \mathbf{x}_{r_4, G})` |
||
190 | where :math:`r_1, r_2, r_3, r_4` are random indexes representing current population individuals |
||
191 | |||
192 | Crossover: |
||
193 | Name: Binomial crossover |
||
194 | |||
195 | :math:`\mathbf{x}_{i, G+1} = \begin{cases} \mathbf{u}_{i, G+1}, & \text{if $f(\mathbf{u}_{i, G+1}) \leq f(\mathbf{x}_{i, G})$}, \\ \mathbf{x}_{i, G}, & \text{otherwise}. \end{cases}` |
||
196 | |||
197 | Args: |
||
198 | pop (numpy.ndarray[Individual]): Current population. |
||
199 | ic (int): Index of individual being mutated. |
||
200 | x_b (Individual): Current global best individual. |
||
201 | f (float): Scale factor. |
||
202 | cr (float): Crossover probability. |
||
203 | rnd (mtrand.RandomState): Random generator. |
||
204 | *args (list): Additional arguments. |
||
205 | |||
206 | Returns: |
||
207 | numpy.ndarray: mutated and mixed individual. |
||
208 | """ |
||
209 | j = rnd.randint(len(pop[ic])) |
||
210 | p = [1 / (len(pop) - 1.0) if i != ic else 0 for i in range(len(pop))] if len(pop) > 3 else None |
||
211 | r = rnd.choice(len(pop), 3, replace=not len(pop) >= 3, p=p) |
||
212 | x = [pop[ic][i] + f * (x_b[i] - pop[r[0]][i]) + f * (pop[r[1]][i] - pop[r[2]][i]) if rnd.rand() < cr or i == j else pop[ic][i] for i in range(len(pop[ic]))] |
||
213 | return asarray(x) |
||
214 | |||
215 | class DifferentialEvolution(Algorithm): |
||
216 | r"""Implementation of Differential evolution algorithm. |
||
217 | |||
218 | Algorithm: |
||
219 | Differential evolution algorithm |
||
220 | |||
221 | Date: |
||
222 | 2018 |
||
223 | |||
224 | Author: |
||
225 | Uros Mlakar and Klemen Berkovič |
||
226 | |||
227 | License: |
||
228 | MIT |
||
229 | |||
230 | Reference paper: |
||
231 | Storn, Rainer, and Kenneth Price. "Differential evolution - a simple and efficient heuristic for global optimization over continuous spaces." Journal of global optimization 11.4 (1997): 341-359. |
||
232 | |||
233 | Attributes: |
||
234 | Name (List[str]): List of string of names for algorithm. |
||
235 | F (float): Scale factor. |
||
236 | CR (float): Crossover probability. |
||
237 | CrossMutt (Callable[numpy.ndarray, int, numpy.ndarray, float, float, mtrand.RandomState, Dict[str, Any]]): crossover and mutation strategy. |
||
238 | |||
239 | See Also: |
||
240 | * :class:`NiaPy.algorithms.Algorithm` |
||
241 | """ |
||
242 | Name = ['DifferentialEvolution', 'DE'] |
||
243 | |||
244 | @staticmethod |
||
245 | def algorithmInfo(): |
||
246 | r"""Get basic information of algorithm. |
||
247 | |||
248 | Returns: |
||
249 | str: Basic information of algorithm. |
||
250 | |||
251 | See Also: |
||
252 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
253 | """ |
||
254 | return r"""Storn, Rainer, and Kenneth Price. "Differential evolution - a simple and efficient heuristic for global optimization over continuous spaces." Journal of global optimization 11.4 (1997): 341-359.""" |
||
255 | |||
256 | @staticmethod |
||
257 | def typeParameters(): |
||
258 | r"""Get dictionary with functions for checking values of parameters. |
||
259 | |||
260 | Returns: |
||
261 | Dict[str, Callable]: |
||
262 | * F (Callable[[Union[float, int]], bool]): Check for correct value of parameter. |
||
263 | * CR (Callable[[float], bool]): Check for correct value of parameter. |
||
264 | |||
265 | See Also: |
||
266 | * :func:`NiaPy.algorithms.Algorithm.typeParameters` |
||
267 | """ |
||
268 | d = Algorithm.typeParameters() |
||
269 | d.update({ |
||
270 | 'F': lambda x: isinstance(x, (float, int)) and 0 < x <= 2, |
||
271 | 'CR': lambda x: isinstance(x, float) and 0 <= x <= 1 |
||
272 | }) |
||
273 | return d |
||
274 | |||
275 | def setParameters(self, NP=50, F=1, CR=0.8, CrossMutt=CrossRand1, **ukwargs): |
||
276 | r"""Set the algorithm parameters. |
||
277 | |||
278 | Arguments: |
||
279 | NP (Optional[int]): Population size. |
||
280 | F (Optional[float]): Scaling factor. |
||
281 | CR (Optional[float]): Crossover rate. |
||
282 | CrossMutt (Optional[Callable[[numpy.ndarray, int, numpy.ndarray, float, float, mtrand.RandomState, list], numpy.ndarray]]): Crossover and mutation strategy. |
||
283 | ukwargs (Dict[str, Any]): Additional arguments. |
||
284 | |||
285 | See Also: |
||
286 | * :func:`NiaPy.algorithms.Algorithm.setParameters` |
||
287 | """ |
||
288 | Algorithm.setParameters(self, NP=NP, InitPopFunc=ukwargs.pop('InitPopFunc', defaultIndividualInit), itype=ukwargs.pop('itype', Individual), **ukwargs) |
||
289 | self.F, self.CR, self.CrossMutt = F, CR, CrossMutt |
||
290 | if ukwargs: logger.info('Unused arguments: %s' % (ukwargs)) |
||
291 | |||
292 | def evolve(self, pop, xb, task, **kwargs): |
||
293 | r"""Evolve population. |
||
294 | |||
295 | Args: |
||
296 | pop (numpy.ndarray[Individual]): Current population. |
||
297 | xb (Individual): Current best individual. |
||
298 | task (Task): Optimization task. |
||
299 | **kwargs (Dict[str, Any]): Additional arguments. |
||
300 | |||
301 | Returns: |
||
302 | numpy.ndarray[Individual]: New evolved populations. |
||
303 | """ |
||
304 | return objects2array([self.itype(x=self.CrossMutt(pop, i, xb, self.F, self.CR, self.Rand), task=task, rnd=self.Rand, e=True) for i in range(len(pop))]) |
||
305 | |||
306 | def selection(self, pop, npop, **kwargs): |
||
307 | r"""Operator for selection. |
||
308 | |||
309 | Args: |
||
310 | pop (numpy.ndarray[Individual]): Current population. |
||
311 | npop (numpy.ndarray[Individual]): New Population. |
||
312 | **kwargs (Dict[str, Any]): Additional arguments. |
||
313 | |||
314 | Returns: |
||
315 | numpy.ndarray[Individual]: New selected individuals. |
||
316 | """ |
||
317 | return objects2array([e if e.f < pop[i].f else pop[i] for i, e in enumerate(npop)]) |
||
318 | |||
319 | def postSelection(self, pop, task, xb=None, **kwargs): |
||
320 | r"""Apply additional operation after selection. |
||
321 | |||
322 | Args: |
||
323 | pop (numpy.ndarray[Individual]): Current population. |
||
324 | task (Task): Optimization task. |
||
325 | xb (Optional[Individual]): Global best solution. |
||
326 | **kwargs (Dict[str, Any]): Additional arguments. |
||
327 | |||
328 | Returns: |
||
329 | numpy.ndarray[Individual]: New population. |
||
330 | """ |
||
331 | return pop |
||
332 | |||
333 | def runIteration(self, task, pop, fpop, xb, fxb, **dparams): |
||
334 | r"""Core function of Differential Evolution algorithm. |
||
335 | |||
336 | Args: |
||
337 | task (Task): Optimization task. |
||
338 | pop (numpy.ndarray[Initialized]): Current population. |
||
339 | fpop (numpy.ndarray[float]): Current populations fitness/function values. |
||
340 | xb (Individual): Current best individual. |
||
341 | fxb (float): Current best individual function/fitness value. |
||
342 | **dparams (Dict[str, Any]): Additional arguments. |
||
343 | |||
344 | Returns: |
||
345 | Tuple[numpy.ndarray[Individual], numpy.ndarray[float], Dict[str, Any]]: |
||
346 | 1. New population. |
||
347 | 2. New population fitness/function values. |
||
348 | 3. Additional arguments. |
||
349 | |||
350 | See Also: |
||
351 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.evolve` |
||
352 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.selection` |
||
353 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.postSelection` |
||
354 | """ |
||
355 | npop = self.evolve(pop, xb, task) |
||
356 | pop = self.selection(pop, npop, task=task) |
||
357 | pop = self.postSelection(pop, task, xb=xb) |
||
358 | return pop, asarray([x.f for x in pop]), {} |
||
359 | |||
360 | class CrowdingDifferentialEvolution(DifferentialEvolution): |
||
361 | r"""Implementation of Differential evolution algorithm with multiple mutation strateys. |
||
362 | |||
363 | Algorithm: |
||
364 | Implementation of Differential evolution algorithm with multiple mutation strateys |
||
365 | |||
366 | Date: |
||
367 | 2018 |
||
368 | |||
369 | Author: |
||
370 | Klemen Berkovič |
||
371 | |||
372 | License: |
||
373 | MIT |
||
374 | |||
375 | Attributes: |
||
376 | Name (List[str]): List of strings representing algorithm name. |
||
377 | CrowPop (float): Proportion of range for cowding. |
||
378 | |||
379 | See Also: |
||
380 | * :class:`NiaPy.algorithms.basic.DifferentialEvolution` |
||
381 | """ |
||
382 | Name = ['CrowdingDifferentialEvolution', 'CDE'] |
||
383 | |||
384 | @staticmethod |
||
385 | def algorithmInfo(): |
||
386 | r"""Get basic information of algorithm. |
||
387 | |||
388 | Returns: |
||
389 | str: Basic information of algorithm. |
||
390 | |||
391 | See Also: |
||
392 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
393 | """ |
||
394 | return r"""No New""" |
||
395 | |||
396 | def setParameters(self, CrowPop=0.1, **ukwargs): |
||
397 | r"""Set core parameters of algorithm. |
||
398 | |||
399 | Args: |
||
400 | CrowPop (Optional[float]): Crowding distance. |
||
401 | **ukwargs: Additional arguments. |
||
402 | |||
403 | See Also: |
||
404 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.setParameters` |
||
405 | """ |
||
406 | DifferentialEvolution.setParameters(self, **ukwargs) |
||
407 | self.CrowPop = CrowPop |
||
408 | |||
409 | def selection(self, pop, npop, **kwargs): |
||
410 | r"""Operator for selection of individuals. |
||
411 | |||
412 | Args: |
||
413 | pop (numpy.ndarray[Individual]): Current population. |
||
414 | npop (numpy.ndarray[Individual]): New population. |
||
415 | kwargs (Dict[str, Any]): Additional arguments. |
||
416 | |||
417 | Returns: |
||
418 | numpy.ndarray[Individual]: New population. |
||
419 | """ |
||
420 | P = [] |
||
421 | for e in npop: |
||
422 | i = argmin([euclidean(e, f) for f in pop]) |
||
423 | P.append(pop[i] if pop[i].f < e.f else e) |
||
424 | return asarray(P) |
||
425 | |||
426 | class DynNpDifferentialEvolution(DifferentialEvolution): |
||
427 | r"""Implementation of Dynamic poulation size Differential evolution algorithm. |
||
428 | |||
429 | Algorithm: |
||
430 | Dynamic poulation size Differential evolution algorithm |
||
431 | |||
432 | Date: |
||
433 | 2018 |
||
434 | |||
435 | Author: |
||
436 | Klemen Berkovič |
||
437 | |||
438 | License: |
||
439 | MIT |
||
440 | |||
441 | Attributes: |
||
442 | Name (List[str]): List of strings representing algorithm names. |
||
443 | pmax (int): Number of population reductions. |
||
444 | rp (int): Small non-negative number which is added to value of generations. |
||
445 | |||
446 | See Also: |
||
447 | * :class:`NiaPy.algorithms.basic.DifferentialEvolution` |
||
448 | """ |
||
449 | Name = ['DynNpDifferentialEvolution', 'dynNpDE'] |
||
450 | |||
451 | @staticmethod |
||
452 | def algorithmInfo(): |
||
453 | r"""Get basic information of algorithm. |
||
454 | |||
455 | Returns: |
||
456 | str: Basic information of algorithm. |
||
457 | |||
458 | See Also: |
||
459 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
460 | """ |
||
461 | return r"""No info""" |
||
462 | |||
463 | @staticmethod |
||
464 | def typeParameters(): |
||
465 | r"""Get dictionary with functions for checking values of parameters. |
||
466 | |||
467 | Returns: |
||
468 | Dict[str, Callable]: |
||
469 | * rp (Callable[[Union[float, int]], bool]) |
||
470 | * pmax (Callable[[int], bool]) |
||
471 | |||
472 | See Also: |
||
473 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.typeParameters` |
||
474 | """ |
||
475 | r = DifferentialEvolution.typeParameters() |
||
476 | r['rp'] = lambda x: isinstance(x, (float, int)) and x > 0 |
||
477 | r['pmax'] = lambda x: isinstance(x, int) and x > 0 |
||
478 | return r |
||
479 | |||
480 | def setParameters(self, pmax=50, rp=3, **ukwargs): |
||
481 | r"""Set the algorithm parameters. |
||
482 | |||
483 | Arguments: |
||
484 | pmax (Optional[int]): umber of population reductions. |
||
485 | rp (Optional[int]): Small non-negative number which is added to value of generations. |
||
486 | |||
487 | See Also: |
||
488 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.setParameters` |
||
489 | """ |
||
490 | DifferentialEvolution.setParameters(self, **ukwargs) |
||
491 | self.pmax, self.rp = pmax, rp |
||
492 | if ukwargs: logger.info('Unused arguments: %s' % (ukwargs)) |
||
493 | |||
494 | def postSelection(self, pop, task, **kwargs): |
||
495 | r"""Post selection operator. |
||
496 | |||
497 | In this algorithm the post selection operator decrements the population at specific iterations/generations. |
||
498 | |||
499 | Args: |
||
500 | pop (numpy.ndarray[Individual]): Current population. |
||
501 | task (Task): Optimization task. |
||
502 | kwargs (Dict[str, Any]): Additional arguments. |
||
503 | |||
504 | Returns: |
||
505 | numpy.ndarray[Individual]: Changed current population. |
||
506 | """ |
||
507 | Gr = task.nFES // (self.pmax * len(pop)) + self.rp |
||
508 | nNP = len(pop) // 2 |
||
509 | if task.Iters == Gr and len(pop) > 3: pop = objects2array([pop[i] if pop[i].f < pop[i + nNP].f else pop[i + nNP] for i in range(nNP)]) |
||
510 | return pop |
||
511 | |||
512 | def proportional(Lt_min, Lt_max, mu, x_f, avg, **args): |
||
513 | r"""Proportional calculation of age of individual. |
||
514 | |||
515 | Args: |
||
516 | Lt_min (int): Minimal life time. |
||
517 | Lt_max (int): Maximal life time. |
||
518 | mu (float): Median of life time. |
||
519 | x_f (float): Individuals function/fitness value. |
||
520 | avg (float): Average fitness/function value of current population. |
||
521 | *args (list): Additional arguments. |
||
522 | |||
523 | Returns: |
||
524 | int: Age of individual. |
||
525 | """ |
||
526 | return min(Lt_min + mu * avg / x_f, Lt_max) |
||
527 | |||
528 | def linear(Lt_min, mu, x_f, x_gw, x_gb, **args): |
||
529 | r"""Linear calculation of age of individual. |
||
530 | |||
531 | Args: |
||
532 | Lt_min (int): Minimal life time. |
||
533 | Lt_max (int): Maximal life time. |
||
534 | mu (float): Median of life time. |
||
535 | x_f (float): Individual function/fitness value. |
||
536 | avg (float): Average fitness/function value. |
||
537 | x_gw (float): Global worst fitness/function value. |
||
538 | x_gb (float): Global best fitness/function value. |
||
539 | *args (list): Additional arguments. |
||
540 | |||
541 | Returns: |
||
542 | int: Age of individual. |
||
543 | """ |
||
544 | return Lt_min + 2 * mu * (x_f - x_gw) / (x_gb - x_gw) |
||
545 | |||
546 | def bilinear(Lt_min, Lt_max, mu, x_f, avg, x_gw, x_gb, **args): |
||
547 | r"""Bilinear calculation of age of individual. |
||
548 | |||
549 | Args: |
||
550 | Lt_min (int): Minimal life time. |
||
551 | Lt_max (int): Maximal life time. |
||
552 | mu (float): Median of life time. |
||
553 | x_f (float): Individual function/fitness value. |
||
554 | avg (float): Average fitness/function value. |
||
555 | x_gw (float): Global worst fitness/function value. |
||
556 | x_gb (float): Global best fitness/function value. |
||
557 | *args (list): Additional arguments. |
||
558 | |||
559 | Returns: |
||
560 | int: Age of individual. |
||
561 | """ |
||
562 | if avg < x_f: return Lt_min + mu * (x_f - x_gw) / (x_gb - x_gw) |
||
563 | return 0.5 * (Lt_min + Lt_max) + mu * (x_f - avg) / (x_gb - avg) |
||
564 | |||
565 | class AgingIndividual(Individual): |
||
566 | r"""Individual with aging. |
||
567 | |||
568 | Attributes: |
||
569 | age (int): Age of individual. |
||
570 | |||
571 | See Also: |
||
572 | * :class:`NiaPy.algorithms.Individual` |
||
573 | """ |
||
574 | age = 0 |
||
575 | |||
576 | def __init__(self, **kwargs): |
||
577 | r"""Init Aging Individual. |
||
578 | |||
579 | Args: |
||
580 | **kwargs (Dict[str, Any]): Additional arguments sent to parent. |
||
581 | |||
582 | See Also: |
||
583 | * :func:`NiaPy.algorithms.Individual.__init__` |
||
584 | """ |
||
585 | Individual.__init__(self, **kwargs) |
||
586 | self.age = 0 |
||
587 | |||
588 | class AgingNpDifferentialEvolution(DifferentialEvolution): |
||
589 | r"""Implementation of Differential evolution algorithm with aging individuals. |
||
590 | |||
591 | Algorithm: |
||
592 | Differential evolution algorithm with dynamic population size that is defined by the quality of population |
||
593 | |||
594 | Date: |
||
595 | 2018 |
||
596 | |||
597 | Author: |
||
598 | Klemen Berkovič |
||
599 | |||
600 | License: |
||
601 | MIT |
||
602 | |||
603 | Attributes: |
||
604 | Name (List[str]): list of strings representing algorithm names. |
||
605 | Lt_min (int): Minimal age of individual. |
||
606 | Lt_max (int): Maximal age of individual. |
||
607 | delta_np (float): Proportion of how many individuals shall die. |
||
608 | omega (float): Acceptance rate for individuals to die. |
||
609 | mu (int): Mean of individual max and min age. |
||
610 | age (Callable[[int, int, float, float, float, float, float], int]): Function for calculation of age for individual. |
||
611 | |||
612 | See Also: |
||
613 | * :class:`NiaPy.algorithms.basic.DifferentialEvolution` |
||
614 | """ |
||
615 | Name = ['AgingNpDifferentialEvolution', 'ANpDE'] |
||
616 | |||
617 | @staticmethod |
||
618 | def algorithmInfo(): |
||
619 | r"""Get basic information of algorithm. |
||
620 | |||
621 | Returns: |
||
622 | str: Basic information of algorithm. |
||
623 | |||
624 | See Also: |
||
625 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
626 | """ |
||
627 | return r"""No info""" |
||
628 | |||
629 | @staticmethod |
||
630 | def typeParameters(): |
||
631 | r"""Get dictionary with functions for checking values of parameters. |
||
632 | |||
633 | Returns: |
||
634 | Dict[str, Callable]: |
||
635 | * Lt_min (Callable[[int], bool]) |
||
636 | * Lt_max (Callable[[int], bool]) |
||
637 | * delta_np (Callable[[float], bool]) |
||
638 | * omega (Callable[[float], bool]) |
||
639 | |||
640 | See Also: |
||
641 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.typeParameters` |
||
642 | """ |
||
643 | r = DifferentialEvolution.typeParameters() |
||
644 | r.update({ |
||
645 | 'Lt_min': lambda x: isinstance(x, int) and x >= 0, |
||
646 | 'Lt_max': lambda x: isinstance(x, int) and x >= 0, |
||
647 | 'delta_np': lambda x: isinstance(x, float) and 0 <= x <= 1, |
||
648 | 'omega': lambda x: isinstance(x, float) and 1 >= x >= 0 |
||
649 | }) |
||
650 | return r |
||
651 | |||
652 | def setParameters(self, Lt_min=0, Lt_max=12, delta_np=0.3, omega=0.3, age=proportional, CrossMutt=CrossBest1, **ukwargs): |
||
653 | r"""Set the algorithm parameters. |
||
654 | |||
655 | Arguments: |
||
656 | Lt_min (Optional[int]): Minimum life time. |
||
657 | Lt_max (Optional[int]): Maximum life time. |
||
658 | age (Optional[Callable[[int, int, float, float, float, float, float], int]]): Function for calculation of age for individual. |
||
659 | |||
660 | See Also: |
||
661 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.setParameters` |
||
662 | """ |
||
663 | DifferentialEvolution.setParameters(self, itype=AgingIndividual, **ukwargs) |
||
664 | self.Lt_min, self.Lt_max, self.age, self.delta_np, self.omega = Lt_min, Lt_max, age, delta_np, omega |
||
665 | self.mu = abs(self.Lt_max - self.Lt_min) / 2 |
||
666 | if ukwargs: logger.info('Unused arguments: %s' % (ukwargs)) |
||
667 | |||
668 | def deltaPopE(self, t): |
||
669 | r"""Calculate how many individuals are going to dye. |
||
670 | |||
671 | Args: |
||
672 | t (int): Number of generations made by the algorithm. |
||
673 | |||
674 | Returns: |
||
675 | int: Number of individuals to dye. |
||
676 | """ |
||
677 | return int(self.delta_np * abs(sin(t))) |
||
678 | |||
679 | def deltaPopC(self, t): |
||
680 | r"""Calculate how many individuals are going to be created. |
||
681 | |||
682 | Args: |
||
683 | t (int): Number of generations made by the algorithm. |
||
684 | |||
685 | Returns: |
||
686 | int: Number of individuals to be born. |
||
687 | """ |
||
688 | return int(self.delta_np * abs(cos(t))) |
||
689 | |||
690 | def aging(self, task, pop): |
||
691 | r"""Apply aging to individuals. |
||
692 | |||
693 | Args: |
||
694 | task (Task): Optimization task. |
||
695 | pop (numpy.ndarray[Individual]): Current population. |
||
696 | |||
697 | Returns: |
||
698 | numpy.ndarray[Individual]: New population. |
||
699 | """ |
||
700 | fpop = asarray([x.f for x in pop]) |
||
701 | x_b, x_w = pop[argmin(fpop)], pop[argmax(fpop)] |
||
702 | avg, npop = mean(fpop), [] |
||
703 | for x in pop: |
||
704 | x.age += 1 |
||
705 | Lt = round(self.age(Lt_min=self.Lt_min, Lt_max=self.Lt_max, mu=self.mu, x_f=x.f, avg=avg, x_gw=x_w.f, x_gb=x_b.f)) |
||
706 | if x.age <= Lt: npop.append(x) |
||
707 | if len(npop) == 0: npop = objects2array([self.itype(task=task, rnd=self.Rand, e=True) for _ in range(self.NP)]) |
||
708 | return npop |
||
709 | |||
710 | def popIncrement(self, pop, task): |
||
711 | r"""Increment population. |
||
712 | |||
713 | Args: |
||
714 | pop (numpy.ndarray[Individual]): Current population. |
||
715 | task (Task): Optimization task. |
||
716 | |||
717 | Returns: |
||
718 | numpy.ndarray[Individual]: Increased population. |
||
719 | """ |
||
720 | deltapop = int(round(max(1, self.NP * self.deltaPopE(task.Iters)))) |
||
721 | return objects2array([self.itype(task=task, rnd=self.Rand, e=True) for _ in range(deltapop)]) |
||
722 | |||
723 | def popDecrement(self, pop, task): |
||
724 | r"""Decrement population. |
||
725 | |||
726 | Args: |
||
727 | pop (numpy.ndarray): Current population. |
||
728 | task (Task): Optimization task. |
||
729 | |||
730 | Returns: |
||
731 | numpy.ndarray[Individual]: Decreased population. |
||
732 | """ |
||
733 | deltapop = int(round(max(1, self.NP * self.deltaPopC(task.Iters)))) |
||
734 | if len(pop) - deltapop <= 0: return pop |
||
735 | ni = self.Rand.choice(len(pop), deltapop, replace=False) |
||
736 | npop = [] |
||
737 | for i, e in enumerate(pop): |
||
738 | if i not in ni: npop.append(e) |
||
739 | elif self.rand() >= self.omega: npop.append(e) |
||
740 | return objects2array(npop) |
||
741 | |||
742 | def selection(self, pop, npop, task, **kwargs): |
||
743 | r"""Select operator for individuals with aging. |
||
744 | |||
745 | Args: |
||
746 | pop (numpy.ndarray[Individual]): Current population. |
||
747 | npop (numpy.ndarray[Individual]): New population. |
||
748 | task (Task): Optimization task. |
||
749 | **kwargs (Dict[str, Any]): Additional arguments. |
||
750 | |||
751 | Returns: |
||
752 | numpy.ndarray[Individual]: New population of individuals. |
||
753 | """ |
||
754 | npop = DifferentialEvolution.selection(self, pop, npop) |
||
755 | npop = append(npop, self.popIncrement(pop, task)) |
||
756 | pop = self.aging(task, npop) |
||
757 | return pop |
||
758 | |||
759 | def postSelection(self, pop, task, xb=None, **kwargs): |
||
760 | r"""Post selection operator. |
||
761 | |||
762 | Args: |
||
763 | pop (numpy.ndarray): Current population. |
||
764 | task (Task): Optimization task. |
||
765 | xb (Individual): Global best individual. |
||
766 | **kwargs (Dict[str, Any]): Additional arguments. |
||
767 | |||
768 | Returns: |
||
769 | numpy.ndarray[Individual]: New population. |
||
770 | """ |
||
771 | return self.popDecrement(pop, task) if len(pop) > self.NP else pop |
||
772 | |||
773 | def multiMutations(pop, i, xb, F, CR, rnd, task, itype, strategies, **kwargs): |
||
774 | r"""Mutation strategy that takes more than one strategy and applys them to individual. |
||
775 | |||
776 | Args: |
||
777 | pop (numpy.ndarray[Individual]): Current population. |
||
778 | i (int): Index of current individual. |
||
779 | xb (Individual): Current best individual. |
||
780 | F (float): Scale factor. |
||
781 | CR (float): Crossover probability. |
||
782 | rnd (mtrand.RandomState): Random generator. |
||
783 | task (Task): Optimization task. |
||
784 | IndividualType (Individual): Individual type used in algorithm. |
||
785 | strategies (Iterable[Callable[[numpy.ndarray[Individual], int, Individual, float, float, mtrand.RandomState], numpy.ndarray[Individual]]]): List of mutation strategies. |
||
786 | **kwargs (Dict[str, Any]): Additional arguments. |
||
787 | |||
788 | Returns: |
||
789 | Individual: Best individual from applyed mutations strategies. |
||
790 | """ |
||
791 | L = [itype(x=strategy(pop, i, xb, F, CR, rnd=rnd), task=task, e=True, rnd=rnd) for strategy in strategies] |
||
792 | return L[argmin([x.f for x in L])] |
||
793 | |||
794 | class MultiStrategyDifferentialEvolution(DifferentialEvolution): |
||
795 | r"""Implementation of Differential evolution algorithm with multiple mutation strateys. |
||
796 | |||
797 | Algorithm: |
||
798 | Implementation of Differential evolution algorithm with multiple mutation strateys |
||
799 | |||
800 | Date: |
||
801 | 2018 |
||
802 | |||
803 | Author: |
||
804 | Klemen Berkovič |
||
805 | |||
806 | License: |
||
807 | MIT |
||
808 | |||
809 | Attributes: |
||
810 | Name (List[str]): List of strings representing algorithm names. |
||
811 | strategies (Iterable[Callable[[numpy.ndarray[Individual], int, Individual, float, float, mtrand.RandomState], numpy.ndarray[Individual]]]): List of mutation strategies. |
||
812 | CrossMutt (Callable[[numpy.ndarray[Individual], int, Individual, float, float, Task, Individual, Iterable[Callable[[numpy.ndarray, int, numpy.ndarray, float, float, mtrand.RandomState, Dict[str, Any]], Individual]]], Individual]): Multi crossover and mutation combiner function. |
||
813 | |||
814 | See Also: |
||
815 | * :class:`NiaPy.algorithms.basic.DifferentialEvolution` |
||
816 | """ |
||
817 | Name = ['MultiStrategyDifferentialEvolution', 'MsDE'] |
||
818 | |||
819 | @staticmethod |
||
820 | def algorithmInfo(): |
||
821 | r"""Get basic information of algorithm. |
||
822 | |||
823 | Returns: |
||
824 | str: Basic information of algorithm. |
||
825 | |||
826 | See Also: |
||
827 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
828 | """ |
||
829 | return r"""No info""" |
||
830 | |||
831 | @staticmethod |
||
832 | def typeParameters(): |
||
833 | r"""Get dictionary with functions for checking values of parameters. |
||
834 | |||
835 | Returns: |
||
836 | Dict[str, Callable]: Testing functions for parameters. |
||
837 | |||
838 | See Also: |
||
839 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.typeParameters` |
||
840 | """ |
||
841 | r = DifferentialEvolution.typeParameters() |
||
842 | r.pop('CrossMutt', None) |
||
843 | r.update({'strategies': lambda x: callable(x)}) |
||
844 | return r |
||
845 | |||
846 | def setParameters(self, strategies=(CrossRand1, CrossBest1, CrossCurr2Best1, CrossRand2), **ukwargs): |
||
847 | r"""Set the arguments of the algorithm. |
||
848 | |||
849 | Arguments: |
||
850 | strategies (Optional[Iterable[Callable[[numpy.ndarray[Individual], int, Individual, float, float, mtrand.RandomState], numpy.ndarray[Individual]]]]): List of mutation strategyis. |
||
851 | CrossMutt (Optional[Callable[[numpy.ndarray[Individual], int, Individual, float, float, Task, Individual, Iterable[Callable[[numpy.ndarray, int, numpy.ndarray, float, float, mtrand.RandomState, Dict[str, Any]], Individual]]], Individual]]): Multi crossover and mutation combiner function. |
||
852 | |||
853 | See Also: |
||
854 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.setParameters` |
||
855 | """ |
||
856 | DifferentialEvolution.setParameters(self, CrossMutt=multiMutations, **ukwargs) |
||
857 | self.strategies = strategies |
||
858 | |||
859 | View Code Duplication | def evolve(self, pop, xb, task, **kwargs): |
|
860 | r"""Evolve population with the help multiple mutation strategies. |
||
861 | |||
862 | Args: |
||
863 | pop (numpy.ndarray[Individual]): Current population. |
||
864 | xb (Individual): Current best individual. |
||
865 | task (Task): Optimization task. |
||
866 | **kwargs (Dict[str, Any]): Additional arguments. |
||
867 | |||
868 | Returns: |
||
869 | numpy.ndarray[Individual]: New population of individuals. |
||
870 | """ |
||
871 | return objects2array([self.CrossMutt(pop, i, xb, self.F, self.CR, self.Rand, task, self.itype, self.strategies) for i in range(len(pop))]) |
||
872 | |||
873 | class DynNpMultiStrategyDifferentialEvolution(MultiStrategyDifferentialEvolution, DynNpDifferentialEvolution): |
||
874 | r"""Implementation of Dynamic population size Differential evolution algorithm with dynamic population size that is defined by the quality of population. |
||
875 | |||
876 | Algorithm: |
||
877 | Dynamic population size Differential evolution algorithm with dynamic population size that is defined by the quality of population |
||
878 | |||
879 | Date: |
||
880 | 2018 |
||
881 | |||
882 | Author: |
||
883 | Klemen Berkovič |
||
884 | |||
885 | License: |
||
886 | MIT |
||
887 | |||
888 | Attributes: |
||
889 | Name (List[str]): List of strings representing algorithm name. |
||
890 | |||
891 | See Also: |
||
892 | * :class:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution` |
||
893 | * :class:`NiaPy.algorithms.basic.DynNpDifferentialEvolution` |
||
894 | """ |
||
895 | Name = ['DynNpMultiStrategyDifferentialEvolution', 'dynNpMsDE'] |
||
896 | |||
897 | @staticmethod |
||
898 | def algorithmInfo(): |
||
899 | r"""Get basic information of algorithm. |
||
900 | |||
901 | Returns: |
||
902 | str: Basic information of algorithm. |
||
903 | |||
904 | See Also: |
||
905 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
906 | """ |
||
907 | return r"""No info""" |
||
908 | |||
909 | @staticmethod |
||
910 | def typeParameters(): |
||
911 | r"""Get dictionary with functions for checking values of parameters. |
||
912 | |||
913 | Returns: |
||
914 | Dict[str, Callable]: |
||
915 | * rp (Callable[[Union[float, int]], bool]): TODO |
||
916 | * pmax (Callable[[int], bool]): TODO |
||
917 | |||
918 | See Also: |
||
919 | * :func:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution.typeParameters` |
||
920 | """ |
||
921 | r = MultiStrategyDifferentialEvolution.typeParameters() |
||
922 | r['rp'] = lambda x: isinstance(x, (float, int)) and x > 0 |
||
923 | r['pmax'] = lambda x: isinstance(x, int) and x > 0 |
||
924 | return r |
||
925 | |||
926 | def setParameters(self, **ukwargs): |
||
927 | r"""Set the arguments of the algorithm. |
||
928 | |||
929 | Args: |
||
930 | ukwargs (Dict[str, Any]): Additional arguments. |
||
931 | |||
932 | See Also: |
||
933 | * :func:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution.setParameters` |
||
934 | * :func:`NiaPy.algorithms.basic.DynNpDifferentialEvolution.setParameters` |
||
935 | """ |
||
936 | DynNpDifferentialEvolution.setParameters(self, **ukwargs) |
||
937 | MultiStrategyDifferentialEvolution.setParameters(self, **ukwargs) |
||
938 | |||
939 | def evolve(self, pop, xb, task, **kwargs): |
||
940 | return MultiStrategyDifferentialEvolution.evolve(self, pop, xb, task, **kwargs) |
||
941 | |||
942 | def postSelection(self, pop, task, **kwargs): |
||
943 | r"""Post selection operator. |
||
944 | |||
945 | Args: |
||
946 | pop (numpy.ndarray[Individual]): Current population. |
||
947 | task (Task): Optimization task. |
||
948 | **kwargs (Dict[str, Any]): Additional arguments. |
||
949 | |||
950 | Returns: |
||
951 | numpy.ndarray: New population. |
||
952 | |||
953 | See Also: |
||
954 | * :func:`NiaPy.algorithms.basic.DynNpDifferentialEvolution.postSelection` |
||
955 | """ |
||
956 | return DynNpDifferentialEvolution.postSelection(self, pop, task) |
||
957 | |||
958 | class AgingNpMultiMutationDifferentialEvolution(AgingNpDifferentialEvolution, MultiStrategyDifferentialEvolution): |
||
959 | r"""Implementation of Differential evolution algorithm with aging individuals. |
||
960 | |||
961 | Algorithm: |
||
962 | Differential evolution algorithm with dynamic population size that is defined by the quality of population |
||
963 | |||
964 | Date: |
||
965 | 2018 |
||
966 | |||
967 | Author: |
||
968 | Klemen Berkovič |
||
969 | |||
970 | License: |
||
971 | MIT |
||
972 | |||
973 | Attributes: |
||
974 | Name (List[str]): List of strings representing algorithm names |
||
975 | |||
976 | See Also: |
||
977 | * :class:`NiaPy.algorithms.basic.AgingNpDifferentialEvolution` |
||
978 | * :class:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution` |
||
979 | """ |
||
980 | Name = ['AgingNpMultiMutationDifferentialEvolution', 'ANpMSDE'] |
||
981 | |||
982 | @staticmethod |
||
983 | def algorithmInfo(): |
||
984 | r"""Get basic information of algorithm. |
||
985 | |||
986 | Returns: |
||
987 | str: Basic information of algorithm. |
||
988 | |||
989 | See Also: |
||
990 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
991 | """ |
||
992 | return r"""No info""" |
||
993 | |||
994 | @staticmethod |
||
995 | def typeParameters(): |
||
996 | r"""Get dictionary with functions for checking values of parameters. |
||
997 | |||
998 | Returns: |
||
999 | Dict[str, Callable]: Mappings form parameter names to test functions. |
||
1000 | |||
1001 | See Also: |
||
1002 | * :func:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution.typeParameters` |
||
1003 | * :func:`NiaPy.algorithms.basic.AgingNpDifferentialEvolution.typeParameters` |
||
1004 | """ |
||
1005 | d = AgingNpDifferentialEvolution.typeParameters() |
||
1006 | d.update(MultiStrategyDifferentialEvolution.typeParameters()) |
||
1007 | return d |
||
1008 | |||
1009 | def setParameters(self, **ukwargs): |
||
1010 | r"""Set core parameter arguments. |
||
1011 | |||
1012 | Args: |
||
1013 | **ukwargs (Dict[str, Any]): Additional arguments. |
||
1014 | |||
1015 | See Also: |
||
1016 | * :func:`NiaPy.algorithms.basic.AgingNpDifferentialEvolution.setParameters` |
||
1017 | * :func:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution.setParameters` |
||
1018 | """ |
||
1019 | AgingNpDifferentialEvolution.setParameters(self, **ukwargs) |
||
1020 | MultiStrategyDifferentialEvolution.setParameters(self, stratgeys=(CrossRand1, CrossBest1, CrossCurr2Rand1, CrossRand2), itype=AgingIndividual, **ukwargs) |
||
1021 | |||
1022 | def evolve(self, pop, xb, task, **kwargs): |
||
1023 | r"""Evolve current population. |
||
1024 | |||
1025 | Args: |
||
1026 | pop (numpy.ndarray[Individual]): Current population. |
||
1027 | xb (Individual): Global best individual. |
||
1028 | task (Task): Optimization task. |
||
1029 | **kwargs (Dict[str, Any]): Additional arguments. |
||
1030 | |||
1031 | Returns: |
||
1032 | numpy.ndarray[Individual]: New population of individuals. |
||
1033 | """ |
||
1034 | return MultiStrategyDifferentialEvolution.evolve(self, pop, xb, task, **kwargs) |
||
1035 | |||
1037 |