Total Complexity | 95 |
Total Lines | 1110 |
Duplicated Lines | 17.3 % |
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 | import logging |
||
3 | import math |
||
4 | |||
5 | from numpy import random as rand, argmin, argmax, mean, cos, asarray, append, sin, isfinite |
||
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 | View Code Duplication | @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 | |||
291 | def getParameters(self): |
||
292 | r"""Get parameters values of the algorithm. |
||
293 | |||
294 | Returns: |
||
295 | Dict[str, Any]: TODO |
||
296 | |||
297 | See Also: |
||
298 | * :func:`NiaPy.algorithms.Algorithm.getParameters` |
||
299 | """ |
||
300 | d = Algorithm.getParameters(self) |
||
301 | d.update({ |
||
302 | 'F': self.F, |
||
303 | 'CR': self.CR, |
||
304 | 'CrossMutt': self.CrossMutt |
||
305 | }) |
||
306 | return d |
||
307 | |||
308 | def evolve(self, pop, xb, task, **kwargs): |
||
309 | r"""Evolve population. |
||
310 | |||
311 | Args: |
||
312 | pop (numpy.ndarray): Current population. |
||
313 | xb (Individual): Current best individual. |
||
314 | task (Task): Optimization task. |
||
315 | **kwargs (Dict[str, Any]): Additional arguments. |
||
316 | |||
317 | Returns: |
||
318 | numpy.ndarray: New evolved populations. |
||
319 | """ |
||
320 | 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))]) |
||
321 | |||
322 | def selection(self, pop, npop, xb, fxb, task, **kwargs): |
||
323 | r"""Operator for selection. |
||
324 | |||
325 | Args: |
||
326 | pop (numpy.ndarray): Current population. |
||
327 | npop (numpy.ndarray): New Population. |
||
328 | xb (numpy.ndarray): Current global best solution. |
||
329 | fxb (float): Current global best solutions fitness/objective value. |
||
330 | task (Task): Optimization task. |
||
331 | **kwargs (Dict[str, Any]): Additional arguments. |
||
332 | |||
333 | Returns: |
||
334 | Tuple[numpy.ndarray, numpy.ndarray, float]: |
||
335 | 1. New selected individuals. |
||
336 | 2. New global best solution. |
||
337 | 3. New global best solutions fitness/objective value. |
||
338 | """ |
||
339 | arr = objects2array([e if e.f < pop[i].f else pop[i] for i, e in enumerate(npop)]) |
||
340 | xb, fxb = self.getBest(arr, asarray([e.f for e in arr]), xb, fxb) |
||
341 | return arr, xb, fxb |
||
342 | |||
343 | def postSelection(self, pop, task, xb, fxb, **kwargs): |
||
344 | r"""Apply additional operation after selection. |
||
345 | |||
346 | Args: |
||
347 | pop (numpy.ndarray): Current population. |
||
348 | task (Task): Optimization task. |
||
349 | xb (numpy.ndarray): Global best solution. |
||
350 | **kwargs (Dict[str, Any]): Additional arguments. |
||
351 | |||
352 | Returns: |
||
353 | Tuple[numpy.ndarray, numpy.ndarray, float]: |
||
354 | 1. New population. |
||
355 | 2. New global best solution. |
||
356 | 3. New global best solutions fitness/objective value. |
||
357 | """ |
||
358 | return pop, xb, fxb |
||
359 | |||
360 | def runIteration(self, task, pop, fpop, xb, fxb, **dparams): |
||
361 | r"""Core function of Differential Evolution algorithm. |
||
362 | |||
363 | Args: |
||
364 | task (Task): Optimization task. |
||
365 | pop (numpy.ndarray): Current population. |
||
366 | fpop (numpy.ndarray): Current populations fitness/function values. |
||
367 | xb (numpy.ndarray): Current best individual. |
||
368 | fxb (float): Current best individual function/fitness value. |
||
369 | **dparams (dict): Additional arguments. |
||
370 | |||
371 | Returns: |
||
372 | Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]: |
||
373 | 1. New population. |
||
374 | 2. New population fitness/function values. |
||
375 | 3. New global best solution. |
||
376 | 4. New global best solutions fitness/objective value. |
||
377 | 5. Additional arguments. |
||
378 | |||
379 | See Also: |
||
380 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.evolve` |
||
381 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.selection` |
||
382 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.postSelection` |
||
383 | """ |
||
384 | npop = self.evolve(pop, xb, task) |
||
385 | pop, xb, fxb = self.selection(pop, npop, xb, fxb, task=task) |
||
386 | pop, xb, fxb = self.postSelection(pop, task, xb, fxb) |
||
387 | fpop = asarray([x.f for x in pop]) |
||
388 | xb, fxb = self.getBest(pop, fpop, xb, fxb) |
||
389 | return pop, fpop, xb, fxb, {} |
||
390 | |||
391 | class CrowdingDifferentialEvolution(DifferentialEvolution): |
||
392 | r"""Implementation of Differential evolution algorithm with multiple mutation strateys. |
||
393 | |||
394 | Algorithm: |
||
395 | Implementation of Differential evolution algorithm with multiple mutation strateys |
||
396 | |||
397 | Date: |
||
398 | 2018 |
||
399 | |||
400 | Author: |
||
401 | Klemen Berkovič |
||
402 | |||
403 | License: |
||
404 | MIT |
||
405 | |||
406 | Attributes: |
||
407 | Name (List[str]): List of strings representing algorithm name. |
||
408 | CrowPop (float): Proportion of range for cowding. |
||
409 | |||
410 | See Also: |
||
411 | * :class:`NiaPy.algorithms.basic.DifferentialEvolution` |
||
412 | """ |
||
413 | Name = ['CrowdingDifferentialEvolution', 'CDE'] |
||
414 | |||
415 | @staticmethod |
||
416 | def algorithmInfo(): |
||
417 | r"""Get basic information of algorithm. |
||
418 | |||
419 | Returns: |
||
420 | str: Basic information of algorithm. |
||
421 | |||
422 | See Also: |
||
423 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
424 | """ |
||
425 | return r"""No New""" |
||
426 | |||
427 | def setParameters(self, CrowPop=0.1, **ukwargs): |
||
428 | r"""Set core parameters of algorithm. |
||
429 | |||
430 | Args: |
||
431 | CrowPop (Optional[float]): Crowding distance. |
||
432 | **ukwargs: Additional arguments. |
||
433 | |||
434 | See Also: |
||
435 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.setParameters` |
||
436 | """ |
||
437 | DifferentialEvolution.setParameters(self, **ukwargs) |
||
438 | self.CrowPop = CrowPop |
||
439 | |||
440 | def selection(self, pop, npop, xb, fxb, task, **kwargs): |
||
441 | r"""Operator for selection of individuals. |
||
442 | |||
443 | Args: |
||
444 | pop (numpy.ndarray): Current population. |
||
445 | npop (numpy.ndarray): New population. |
||
446 | xb (numpy.ndarray): Current global best solution. |
||
447 | fxb (float): Current global best solutions fitness/objective value. |
||
448 | task (Task): Optimization task. |
||
449 | kwargs (Dict[str, Any]): Additional arguments. |
||
450 | |||
451 | Returns: |
||
452 | Tuple[numpy.ndarray, numpy.ndarray, float]: |
||
453 | 1. New population. |
||
454 | 2. New global best solution. |
||
455 | 3. New global best solutions fitness/objective value. |
||
456 | """ |
||
457 | P = [] |
||
458 | for e in npop: |
||
459 | i = argmin([euclidean(e, f) for f in pop]) |
||
460 | P.append(pop[i] if pop[i].f < e.f else e) |
||
461 | return asarray(P), xb, fxb |
||
462 | |||
463 | class DynNpDifferentialEvolution(DifferentialEvolution): |
||
464 | r"""Implementation of Dynamic poulation size Differential evolution algorithm. |
||
465 | |||
466 | Algorithm: |
||
467 | Dynamic poulation size Differential evolution algorithm |
||
468 | |||
469 | Date: |
||
470 | 2018 |
||
471 | |||
472 | Author: |
||
473 | Klemen Berkovič |
||
474 | |||
475 | License: |
||
476 | MIT |
||
477 | |||
478 | Attributes: |
||
479 | Name (List[str]): List of strings representing algorithm names. |
||
480 | pmax (int): Number of population reductions. |
||
481 | rp (int): Small non-negative number which is added to value of generations. |
||
482 | |||
483 | See Also: |
||
484 | * :class:`NiaPy.algorithms.basic.DifferentialEvolution` |
||
485 | """ |
||
486 | Name = ['DynNpDifferentialEvolution', 'dynNpDE'] |
||
487 | |||
488 | @staticmethod |
||
489 | def algorithmInfo(): |
||
490 | r"""Get basic information of algorithm. |
||
491 | |||
492 | Returns: |
||
493 | str: Basic information of algorithm. |
||
494 | |||
495 | See Also: |
||
496 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
497 | """ |
||
498 | return r"""No info""" |
||
499 | |||
500 | @staticmethod |
||
501 | def typeParameters(): |
||
502 | r"""Get dictionary with functions for checking values of parameters. |
||
503 | |||
504 | Returns: |
||
505 | Dict[str, Callable]: |
||
506 | * rp (Callable[[Union[float, int]], bool]) |
||
507 | * pmax (Callable[[int], bool]) |
||
508 | |||
509 | See Also: |
||
510 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.typeParameters` |
||
511 | """ |
||
512 | r = DifferentialEvolution.typeParameters() |
||
513 | r['rp'] = lambda x: isinstance(x, (float, int)) and x > 0 |
||
514 | r['pmax'] = lambda x: isinstance(x, int) and x > 0 |
||
515 | return r |
||
516 | |||
517 | def setParameters(self, pmax=50, rp=3, **ukwargs): |
||
518 | r"""Set the algorithm parameters. |
||
519 | |||
520 | Arguments: |
||
521 | pmax (Optional[int]): umber of population reductions. |
||
522 | rp (Optional[int]): Small non-negative number which is added to value of generations. |
||
523 | |||
524 | See Also: |
||
525 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.setParameters` |
||
526 | """ |
||
527 | DifferentialEvolution.setParameters(self, **ukwargs) |
||
528 | self.pmax, self.rp = pmax, rp |
||
529 | |||
530 | def postSelection(self, pop, task, xb, fxb, **kwargs): |
||
531 | r"""Post selection operator. |
||
532 | |||
533 | In this algorithm the post selection operator decrements the population at specific iterations/generations. |
||
534 | |||
535 | Args: |
||
536 | pop (numpy.ndarray): Current population. |
||
537 | task (Task): Optimization task. |
||
538 | kwargs (Dict[str, Any]): Additional arguments. |
||
539 | |||
540 | Returns: |
||
541 | Tuple[numpy.ndarray, numpy.ndarray, float]: |
||
542 | 1. Changed current population. |
||
543 | 2. New global best solution. |
||
544 | 3. New global best solutions fitness/objective value. |
||
545 | """ |
||
546 | Gr = task.nFES // (self.pmax * len(pop)) + self.rp |
||
547 | nNP = len(pop) // 2 |
||
548 | 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)]) |
||
549 | return pop, xb, fxb |
||
550 | |||
551 | def proportional(Lt_min, Lt_max, mu, x_f, avg, **args): |
||
552 | r"""Proportional calculation of age of individual. |
||
553 | |||
554 | Args: |
||
555 | Lt_min (int): Minimal life time. |
||
556 | Lt_max (int): Maximal life time. |
||
557 | mu (float): Median of life time. |
||
558 | x_f (float): Individuals function/fitness value. |
||
559 | avg (float): Average fitness/function value of current population. |
||
560 | args (list): Additional arguments. |
||
561 | |||
562 | Returns: |
||
563 | int: Age of individual. |
||
564 | """ |
||
565 | proportional_result = Lt_max if math.isinf(avg) else Lt_min + mu * avg / x_f |
||
566 | return min(proportional_result, Lt_max) |
||
567 | |||
568 | def linear(Lt_min, mu, x_f, x_gw, x_gb, **args): |
||
569 | r"""Linear calculation of age of individual. |
||
570 | |||
571 | Args: |
||
572 | Lt_min (int): Minimal life time. |
||
573 | Lt_max (int): Maximal life time. |
||
574 | mu (float): Median of life time. |
||
575 | x_f (float): Individual function/fitness value. |
||
576 | avg (float): Average fitness/function value. |
||
577 | x_gw (float): Global worst fitness/function value. |
||
578 | x_gb (float): Global best fitness/function value. |
||
579 | args (list): Additional arguments. |
||
580 | |||
581 | Returns: |
||
582 | int: Age of individual. |
||
583 | """ |
||
584 | return Lt_min + 2 * mu * (x_f - x_gw) / (x_gb - x_gw) |
||
585 | |||
586 | def bilinear(Lt_min, Lt_max, mu, x_f, avg, x_gw, x_gb, **args): |
||
587 | r"""Bilinear calculation of age of individual. |
||
588 | |||
589 | Args: |
||
590 | Lt_min (int): Minimal life time. |
||
591 | Lt_max (int): Maximal life time. |
||
592 | mu (float): Median of life time. |
||
593 | x_f (float): Individual function/fitness value. |
||
594 | avg (float): Average fitness/function value. |
||
595 | x_gw (float): Global worst fitness/function value. |
||
596 | x_gb (float): Global best fitness/function value. |
||
597 | args (list): Additional arguments. |
||
598 | |||
599 | Returns: |
||
600 | int: Age of individual. |
||
601 | """ |
||
602 | if avg < x_f: return Lt_min + mu * (x_f - x_gw) / (x_gb - x_gw) |
||
603 | return 0.5 * (Lt_min + Lt_max) + mu * (x_f - avg) / (x_gb - avg) |
||
604 | |||
605 | class AgingIndividual(Individual): |
||
606 | r"""Individual with aging. |
||
607 | |||
608 | Attributes: |
||
609 | age (int): Age of individual. |
||
610 | |||
611 | See Also: |
||
612 | * :class:`NiaPy.algorithms.Individual` |
||
613 | """ |
||
614 | age = 0 |
||
615 | |||
616 | def __init__(self, **kwargs): |
||
617 | r"""Init Aging Individual. |
||
618 | |||
619 | Args: |
||
620 | **kwargs (Dict[str, Any]): Additional arguments sent to parent. |
||
621 | |||
622 | See Also: |
||
623 | * :func:`NiaPy.algorithms.Individual.__init__` |
||
624 | """ |
||
625 | Individual.__init__(self, **kwargs) |
||
626 | self.age = 0 |
||
627 | |||
628 | class AgingNpDifferentialEvolution(DifferentialEvolution): |
||
629 | r"""Implementation of Differential evolution algorithm with aging individuals. |
||
630 | |||
631 | Algorithm: |
||
632 | Differential evolution algorithm with dynamic population size that is defined by the quality of population |
||
633 | |||
634 | Date: |
||
635 | 2018 |
||
636 | |||
637 | Author: |
||
638 | Klemen Berkovič |
||
639 | |||
640 | License: |
||
641 | MIT |
||
642 | |||
643 | Attributes: |
||
644 | Name (List[str]): list of strings representing algorithm names. |
||
645 | Lt_min (int): Minimal age of individual. |
||
646 | Lt_max (int): Maximal age of individual. |
||
647 | delta_np (float): Proportion of how many individuals shall die. |
||
648 | omega (float): Acceptance rate for individuals to die. |
||
649 | mu (int): Mean of individual max and min age. |
||
650 | age (Callable[[int, int, float, float, float, float, float], int]): Function for calculation of age for individual. |
||
651 | |||
652 | See Also: |
||
653 | * :class:`NiaPy.algorithms.basic.DifferentialEvolution` |
||
654 | """ |
||
655 | Name = ['AgingNpDifferentialEvolution', 'ANpDE'] |
||
656 | |||
657 | @staticmethod |
||
658 | def algorithmInfo(): |
||
659 | r"""Get basic information of algorithm. |
||
660 | |||
661 | Returns: |
||
662 | str: Basic information of algorithm. |
||
663 | |||
664 | See Also: |
||
665 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
666 | """ |
||
667 | return r"""No info""" |
||
668 | |||
669 | @staticmethod |
||
670 | def typeParameters(): |
||
671 | r"""Get dictionary with functions for checking values of parameters. |
||
672 | |||
673 | Returns: |
||
674 | Dict[str, Callable]: |
||
675 | * Lt_min (Callable[[int], bool]) |
||
676 | * Lt_max (Callable[[int], bool]) |
||
677 | * delta_np (Callable[[float], bool]) |
||
678 | * omega (Callable[[float], bool]) |
||
679 | |||
680 | See Also: |
||
681 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.typeParameters` |
||
682 | """ |
||
683 | r = DifferentialEvolution.typeParameters() |
||
684 | r.update({ |
||
685 | 'Lt_min': lambda x: isinstance(x, int) and x >= 0, |
||
686 | 'Lt_max': lambda x: isinstance(x, int) and x >= 0, |
||
687 | 'delta_np': lambda x: isinstance(x, float) and 0 <= x <= 1, |
||
688 | 'omega': lambda x: isinstance(x, float) and 1 >= x >= 0 |
||
689 | }) |
||
690 | return r |
||
691 | |||
692 | def setParameters(self, Lt_min=0, Lt_max=12, delta_np=0.3, omega=0.3, age=proportional, CrossMutt=CrossBest1, **ukwargs): |
||
693 | r"""Set the algorithm parameters. |
||
694 | |||
695 | Arguments: |
||
696 | Lt_min (Optional[int]): Minimum life time. |
||
697 | Lt_max (Optional[int]): Maximum life time. |
||
698 | age (Optional[Callable[[int, int, float, float, float, float, float], int]]): Function for calculation of age for individual. |
||
699 | |||
700 | See Also: |
||
701 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.setParameters` |
||
702 | """ |
||
703 | DifferentialEvolution.setParameters(self, itype=AgingIndividual, **ukwargs) |
||
704 | self.Lt_min, self.Lt_max, self.age, self.delta_np, self.omega = Lt_min, Lt_max, age, delta_np, omega |
||
705 | self.mu = abs(self.Lt_max - self.Lt_min) / 2 |
||
706 | |||
707 | def deltaPopE(self, t): |
||
708 | r"""Calculate how many individuals are going to dye. |
||
709 | |||
710 | Args: |
||
711 | t (int): Number of generations made by the algorithm. |
||
712 | |||
713 | Returns: |
||
714 | int: Number of individuals to dye. |
||
715 | """ |
||
716 | return int(self.delta_np * abs(sin(t))) |
||
717 | |||
718 | def deltaPopC(self, t): |
||
719 | r"""Calculate how many individuals are going to be created. |
||
720 | |||
721 | Args: |
||
722 | t (int): Number of generations made by the algorithm. |
||
723 | |||
724 | Returns: |
||
725 | int: Number of individuals to be born. |
||
726 | """ |
||
727 | return int(self.delta_np * abs(cos(t))) |
||
728 | |||
729 | def aging(self, task, pop): |
||
730 | r"""Apply aging to individuals. |
||
731 | |||
732 | Args: |
||
733 | task (Task): Optimization task. |
||
734 | pop (numpy.ndarray[Individual]): Current population. |
||
735 | |||
736 | Returns: |
||
737 | numpy.ndarray[Individual]: New population. |
||
738 | """ |
||
739 | fpop = asarray([x.f for x in pop]) |
||
740 | x_b, x_w = pop[argmin(fpop)], pop[argmax(fpop)] |
||
741 | avg, npop = mean(fpop[isfinite(fpop)]), [] |
||
742 | for x in pop: |
||
743 | x.age += 1 |
||
744 | 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)) |
||
745 | if x.age <= Lt: npop.append(x) |
||
746 | if len(npop) == 0: npop = objects2array([self.itype(task=task, rnd=self.Rand, e=True) for _ in range(self.NP)]) |
||
747 | return npop |
||
748 | |||
749 | def popIncrement(self, pop, task): |
||
750 | r"""Increment population. |
||
751 | |||
752 | Args: |
||
753 | pop (numpy.ndarray[Individual]): Current population. |
||
754 | task (Task): Optimization task. |
||
755 | |||
756 | Returns: |
||
757 | numpy.ndarray[Individual]: Increased population. |
||
758 | """ |
||
759 | deltapop = int(round(max(1, self.NP * self.deltaPopE(task.Iters)))) |
||
760 | return objects2array([self.itype(task=task, rnd=self.Rand, e=True) for _ in range(deltapop)]) |
||
761 | |||
762 | def popDecrement(self, pop, task): |
||
763 | r"""Decrement population. |
||
764 | |||
765 | Args: |
||
766 | pop (numpy.ndarray): Current population. |
||
767 | task (Task): Optimization task. |
||
768 | |||
769 | Returns: |
||
770 | numpy.ndarray[Individual]: Decreased population. |
||
771 | """ |
||
772 | deltapop = int(round(max(1, self.NP * self.deltaPopC(task.Iters)))) |
||
773 | if len(pop) - deltapop <= 0: return pop |
||
774 | ni = self.Rand.choice(len(pop), deltapop, replace=False) |
||
775 | npop = [] |
||
776 | for i, e in enumerate(pop): |
||
777 | if i not in ni: npop.append(e) |
||
778 | elif self.rand() >= self.omega: npop.append(e) |
||
779 | return objects2array(npop) |
||
780 | |||
781 | def selection(self, pop, npop, xb, fxb, task, **kwargs): |
||
782 | r"""Select operator for individuals with aging. |
||
783 | |||
784 | Args: |
||
785 | pop (numpy.ndarray): Current population. |
||
786 | npop (numpy.ndarray): New population. |
||
787 | xb (numpy.ndarray): Current global best solution. |
||
788 | fxb (float): Current global best solutions fitness/objective value. |
||
789 | task (Task): Optimization task. |
||
790 | **kwargs (Dict[str, Any]): Additional arguments. |
||
791 | |||
792 | Returns: |
||
793 | Tuple[numpy.ndarray, numpy.ndarray, float]: |
||
794 | 1. New population of individuals. |
||
795 | 2. New global best solution. |
||
796 | 3. New global best solutions fitness/objective value. |
||
797 | """ |
||
798 | npop, xb, fxb = DifferentialEvolution.selection(self, pop, npop, xb, fxb, task) |
||
799 | npop = append(npop, self.popIncrement(pop, task)) |
||
800 | xb, fxb = self.getBest(npop, asarray([e.f for e in npop]), xb, fxb) |
||
801 | pop = self.aging(task, npop) |
||
802 | return pop, xb, fxb |
||
803 | |||
804 | def postSelection(self, pop, task, xb, fxb, **kwargs): |
||
805 | r"""Post selection operator. |
||
806 | |||
807 | Args: |
||
808 | pop (numpy.ndarray): Current population. |
||
809 | task (Task): Optimization task. |
||
810 | xb (Individual): Global best individual. |
||
811 | **kwargs (Dict[str, Any]): Additional arguments. |
||
812 | |||
813 | Returns: |
||
814 | Tuple[numpy.ndarray, numpy.ndarray, float]: |
||
815 | 1. New population. |
||
816 | 2. New global best solution |
||
817 | 3. New global best solutions fitness/objective value |
||
818 | """ |
||
819 | return self.popDecrement(pop, task) if len(pop) > self.NP else pop, xb, fxb |
||
820 | |||
821 | def multiMutations(pop, i, xb, F, CR, rnd, task, itype, strategies, **kwargs): |
||
822 | r"""Mutation strategy that takes more than one strategy and applys them to individual. |
||
823 | |||
824 | Args: |
||
825 | pop (numpy.ndarray[Individual]): Current population. |
||
826 | i (int): Index of current individual. |
||
827 | xb (Individual): Current best individual. |
||
828 | F (float): Scale factor. |
||
829 | CR (float): Crossover probability. |
||
830 | rnd (mtrand.RandomState): Random generator. |
||
831 | task (Task): Optimization task. |
||
832 | IndividualType (Individual): Individual type used in algorithm. |
||
833 | strategies (Iterable[Callable[[numpy.ndarray[Individual], int, Individual, float, float, mtrand.RandomState], numpy.ndarray[Individual]]]): List of mutation strategies. |
||
834 | **kwargs (Dict[str, Any]): Additional arguments. |
||
835 | |||
836 | Returns: |
||
837 | Individual: Best individual from applyed mutations strategies. |
||
838 | """ |
||
839 | L = [itype(x=strategy(pop, i, xb, F, CR, rnd=rnd), task=task, e=True, rnd=rnd) for strategy in strategies] |
||
840 | return L[argmin([x.f for x in L])] |
||
841 | |||
842 | class MultiStrategyDifferentialEvolution(DifferentialEvolution): |
||
843 | r"""Implementation of Differential evolution algorithm with multiple mutation strateys. |
||
844 | |||
845 | Algorithm: |
||
846 | Implementation of Differential evolution algorithm with multiple mutation strateys |
||
847 | |||
848 | Date: |
||
849 | 2018 |
||
850 | |||
851 | Author: |
||
852 | Klemen Berkovič |
||
853 | |||
854 | License: |
||
855 | MIT |
||
856 | |||
857 | Attributes: |
||
858 | Name (List[str]): List of strings representing algorithm names. |
||
859 | strategies (Iterable[Callable[[numpy.ndarray[Individual], int, Individual, float, float, mtrand.RandomState], numpy.ndarray[Individual]]]): List of mutation strategies. |
||
860 | 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. |
||
861 | |||
862 | See Also: |
||
863 | * :class:`NiaPy.algorithms.basic.DifferentialEvolution` |
||
864 | """ |
||
865 | Name = ['MultiStrategyDifferentialEvolution', 'MsDE'] |
||
866 | |||
867 | @staticmethod |
||
868 | def algorithmInfo(): |
||
869 | r"""Get basic information of algorithm. |
||
870 | |||
871 | Returns: |
||
872 | str: Basic information of algorithm. |
||
873 | |||
874 | See Also: |
||
875 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
876 | """ |
||
877 | return r"""No info""" |
||
878 | |||
879 | @staticmethod |
||
880 | def typeParameters(): |
||
881 | r"""Get dictionary with functions for checking values of parameters. |
||
882 | |||
883 | Returns: |
||
884 | Dict[str, Callable]: Testing functions for parameters. |
||
885 | |||
886 | See Also: |
||
887 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.typeParameters` |
||
888 | """ |
||
889 | r = DifferentialEvolution.typeParameters() |
||
890 | r.pop('CrossMutt', None) |
||
891 | r.update({'strategies': lambda x: callable(x)}) |
||
892 | return r |
||
893 | |||
894 | def setParameters(self, strategies=(CrossRand1, CrossBest1, CrossCurr2Best1, CrossRand2), **ukwargs): |
||
895 | r"""Set the arguments of the algorithm. |
||
896 | |||
897 | Arguments: |
||
898 | strategies (Optional[Iterable[Callable[[numpy.ndarray[Individual], int, Individual, float, float, mtrand.RandomState], numpy.ndarray[Individual]]]]): List of mutation strategyis. |
||
899 | 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. |
||
900 | |||
901 | See Also: |
||
902 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.setParameters` |
||
903 | """ |
||
904 | DifferentialEvolution.setParameters(self, CrossMutt=multiMutations, **ukwargs) |
||
905 | self.strategies = strategies |
||
906 | |||
907 | def getParameters(self): |
||
908 | r"""Get parameters values of the algorithm. |
||
909 | |||
910 | Returns: |
||
911 | Dict[str, Any]: TODO. |
||
912 | |||
913 | See Also: |
||
914 | * :func:`NiaPy.algorithms.basic.DifferentialEvolution.getParameters` |
||
915 | """ |
||
916 | d = DifferentialEvolution.getParameters(self) |
||
917 | d.update({'strategies': self.strategies}) |
||
918 | return d |
||
919 | |||
920 | View Code Duplication | def evolve(self, pop, xb, task, **kwargs): |
|
921 | r"""Evolve population with the help multiple mutation strategies. |
||
922 | |||
923 | Args: |
||
924 | pop (numpy.ndarray): Current population. |
||
925 | xb (numpy.ndarray): Current best individual. |
||
926 | task (Task): Optimization task. |
||
927 | **kwargs (Dict[str, Any]): Additional arguments. |
||
928 | |||
929 | Returns: |
||
930 | numpy.ndarray: New population of individuals. |
||
931 | """ |
||
932 | return objects2array([self.CrossMutt(pop, i, xb, self.F, self.CR, self.Rand, task, self.itype, self.strategies) for i in range(len(pop))]) |
||
933 | |||
934 | class DynNpMultiStrategyDifferentialEvolution(MultiStrategyDifferentialEvolution, DynNpDifferentialEvolution): |
||
935 | r"""Implementation of Dynamic population size Differential evolution algorithm with dynamic population size that is defined by the quality of population. |
||
936 | |||
937 | Algorithm: |
||
938 | Dynamic population size Differential evolution algorithm with dynamic population size that is defined by the quality of population |
||
939 | |||
940 | Date: |
||
941 | 2018 |
||
942 | |||
943 | Author: |
||
944 | Klemen Berkovič |
||
945 | |||
946 | License: |
||
947 | MIT |
||
948 | |||
949 | Attributes: |
||
950 | Name (List[str]): List of strings representing algorithm name. |
||
951 | |||
952 | See Also: |
||
953 | * :class:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution` |
||
954 | * :class:`NiaPy.algorithms.basic.DynNpDifferentialEvolution` |
||
955 | """ |
||
956 | Name = ['DynNpMultiStrategyDifferentialEvolution', 'dynNpMsDE'] |
||
957 | |||
958 | @staticmethod |
||
959 | def algorithmInfo(): |
||
960 | r"""Get basic information of algorithm. |
||
961 | |||
962 | Returns: |
||
963 | str: Basic information of algorithm. |
||
964 | |||
965 | See Also: |
||
966 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
967 | """ |
||
968 | return r"""No info""" |
||
969 | |||
970 | @staticmethod |
||
971 | def typeParameters(): |
||
972 | r"""Get dictionary with functions for checking values of parameters. |
||
973 | |||
974 | Returns: |
||
975 | Dict[str, Callable]: |
||
976 | * rp (Callable[[Union[float, int]], bool]): TODO |
||
977 | * pmax (Callable[[int], bool]): TODO |
||
978 | |||
979 | See Also: |
||
980 | * :func:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution.typeParameters` |
||
981 | """ |
||
982 | r = MultiStrategyDifferentialEvolution.typeParameters() |
||
983 | r['rp'] = lambda x: isinstance(x, (float, int)) and x > 0 |
||
984 | r['pmax'] = lambda x: isinstance(x, int) and x > 0 |
||
985 | return r |
||
986 | |||
987 | def setParameters(self, **ukwargs): |
||
988 | r"""Set the arguments of the algorithm. |
||
989 | |||
990 | Args: |
||
991 | ukwargs (Dict[str, Any]): Additional arguments. |
||
992 | |||
993 | See Also: |
||
994 | * :func:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution.setParameters` |
||
995 | * :func:`NiaPy.algorithms.basic.DynNpDifferentialEvolution.setParameters` |
||
996 | """ |
||
997 | DynNpDifferentialEvolution.setParameters(self, **ukwargs) |
||
998 | MultiStrategyDifferentialEvolution.setParameters(self, **ukwargs) |
||
999 | |||
1000 | def evolve(self, pop, xb, task, **kwargs): |
||
1001 | r"""Evolve the current population. |
||
1002 | |||
1003 | Args: |
||
1004 | pop (numpy.ndarray): Current population. |
||
1005 | xb (numpy.ndarray): Global best solution. |
||
1006 | task (Task): Optimization task. |
||
1007 | **kwargs (dict): Additional arguments. |
||
1008 | |||
1009 | Returns: |
||
1010 | numpy.ndarray: Evolved new population. |
||
1011 | """ |
||
1012 | return MultiStrategyDifferentialEvolution.evolve(self, pop, xb, task, **kwargs) |
||
1013 | |||
1014 | def postSelection(self, pop, task, xb, fxb, **kwargs): |
||
1015 | r"""Post selection operator. |
||
1016 | |||
1017 | Args: |
||
1018 | pop (numpy.ndarray): Current population. |
||
1019 | task (Task): Optimization task. |
||
1020 | **kwargs (Dict[str, Any]): Additional arguments. |
||
1021 | |||
1022 | Returns: |
||
1023 | Tuple[numpy.ndarray, numpy.ndarray, float]: |
||
1024 | 1. New population. |
||
1025 | 2. New global best solution. |
||
1026 | 3. New global best solutions fitness/objective value. |
||
1027 | |||
1028 | See Also: |
||
1029 | * :func:`NiaPy.algorithms.basic.DynNpDifferentialEvolution.postSelection` |
||
1030 | """ |
||
1031 | return DynNpDifferentialEvolution.postSelection(self, pop, task, xb, fxb) |
||
1032 | |||
1033 | class AgingNpMultiMutationDifferentialEvolution(AgingNpDifferentialEvolution, MultiStrategyDifferentialEvolution): |
||
1034 | r"""Implementation of Differential evolution algorithm with aging individuals. |
||
1035 | |||
1036 | Algorithm: |
||
1037 | Differential evolution algorithm with dynamic population size that is defined by the quality of population |
||
1038 | |||
1039 | Date: |
||
1040 | 2018 |
||
1041 | |||
1042 | Author: |
||
1043 | Klemen Berkovič |
||
1044 | |||
1045 | License: |
||
1046 | MIT |
||
1047 | |||
1048 | Attributes: |
||
1049 | Name (List[str]): List of strings representing algorithm names |
||
1050 | |||
1051 | See Also: |
||
1052 | * :class:`NiaPy.algorithms.basic.AgingNpDifferentialEvolution` |
||
1053 | * :class:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution` |
||
1054 | """ |
||
1055 | Name = ['AgingNpMultiMutationDifferentialEvolution', 'ANpMSDE'] |
||
1056 | |||
1057 | @staticmethod |
||
1058 | def algorithmInfo(): |
||
1059 | r"""Get basic information of algorithm. |
||
1060 | |||
1061 | Returns: |
||
1062 | str: Basic information of algorithm. |
||
1063 | |||
1064 | See Also: |
||
1065 | * :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
||
1066 | """ |
||
1067 | return r"""No info""" |
||
1068 | |||
1069 | @staticmethod |
||
1070 | def typeParameters(): |
||
1071 | r"""Get dictionary with functions for checking values of parameters. |
||
1072 | |||
1073 | Returns: |
||
1074 | Dict[str, Callable]: Mappings form parameter names to test functions. |
||
1075 | |||
1076 | See Also: |
||
1077 | * :func:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution.typeParameters` |
||
1078 | * :func:`NiaPy.algorithms.basic.AgingNpDifferentialEvolution.typeParameters` |
||
1079 | """ |
||
1080 | d = AgingNpDifferentialEvolution.typeParameters() |
||
1081 | d.update(MultiStrategyDifferentialEvolution.typeParameters()) |
||
1082 | return d |
||
1083 | |||
1084 | def setParameters(self, **ukwargs): |
||
1085 | r"""Set core parameter arguments. |
||
1086 | |||
1087 | Args: |
||
1088 | **ukwargs (Dict[str, Any]): Additional arguments. |
||
1089 | |||
1090 | See Also: |
||
1091 | * :func:`NiaPy.algorithms.basic.AgingNpDifferentialEvolution.setParameters` |
||
1092 | * :func:`NiaPy.algorithms.basic.MultiStrategyDifferentialEvolution.setParameters` |
||
1093 | """ |
||
1094 | AgingNpDifferentialEvolution.setParameters(self, **ukwargs) |
||
1095 | MultiStrategyDifferentialEvolution.setParameters(self, stratgeys=(CrossRand1, CrossBest1, CrossCurr2Rand1, CrossRand2), itype=AgingIndividual, **ukwargs) |
||
1096 | |||
1097 | def evolve(self, pop, xb, task, **kwargs): |
||
1098 | r"""Evolve current population. |
||
1099 | |||
1100 | Args: |
||
1101 | pop (numpy.ndarray): Current population. |
||
1102 | xb (numpy.ndarray): Global best individual. |
||
1103 | task (Task): Optimization task. |
||
1104 | **kwargs (Dict[str, Any]): Additional arguments. |
||
1105 | |||
1106 | Returns: |
||
1107 | numpy.ndarray: New population of individuals. |
||
1108 | """ |
||
1109 | return MultiStrategyDifferentialEvolution.evolve(self, pop, xb, task, **kwargs) |
||
1110 | |||
1112 |