NiaPy.algorithms.basic.de   F
last analyzed

Complexity

Total Complexity 95

Size/Duplication

Total Lines 1110
Duplicated Lines 17.3 %

Importance

Changes 0
Metric Value
eloc 239
dl 192
loc 1110
rs 2
c 0
b 0
f 0
wmc 95

10 Functions

Rating   Name   Duplication   Size   Complexity  
A CrossBest1() 33 33 4
A CrossBest2() 31 31 4
A CrossCurr2Rand1() 31 31 4
A CrossCurr2Best1() 0 31 4
A CrossRand2() 33 33 4
A CrossRand1() 33 33 4
A linear() 0 17 1
A multiMutations() 0 20 1
A bilinear() 0 18 2
A proportional() 0 16 2

40 Methods

Rating   Name   Duplication   Size   Complexity  
A DifferentialEvolution.algorithmInfo() 0 11 1
A DifferentialEvolution.setParameters() 0 15 1
A CrowdingDifferentialEvolution.setParameters() 0 12 1
A DifferentialEvolution.postSelection() 0 16 1
A DifferentialEvolution.getParameters() 0 16 1
A CrowdingDifferentialEvolution.algorithmInfo() 0 11 1
A DifferentialEvolution.selection() 0 20 2
A DifferentialEvolution.runIteration() 0 30 1
A CrowdingDifferentialEvolution.selection() 0 22 3
A DynNpDifferentialEvolution.algorithmInfo() 0 11 1
A DynNpDifferentialEvolution.postSelection() 0 20 4
A DifferentialEvolution.typeParameters() 18 18 3
A DifferentialEvolution.evolve() 0 13 1
A DynNpDifferentialEvolution.typeParameters() 0 16 3
A DynNpDifferentialEvolution.setParameters() 0 12 1
A MultiStrategyDifferentialEvolution.getParameters() 0 12 1
A AgingNpDifferentialEvolution.deltaPopC() 0 10 1
A AgingNpDifferentialEvolution.popDecrement() 0 18 5
A AgingNpDifferentialEvolution.deltaPopE() 0 10 1
A AgingNpDifferentialEvolution.postSelection() 0 16 2
A AgingNpMultiMutationDifferentialEvolution.algorithmInfo() 0 11 1
A MultiStrategyDifferentialEvolution.evolve() 13 13 1
A MultiStrategyDifferentialEvolution.algorithmInfo() 0 11 1
A AgingNpDifferentialEvolution.algorithmInfo() 0 11 1
A DynNpMultiStrategyDifferentialEvolution.algorithmInfo() 0 11 1
A MultiStrategyDifferentialEvolution.typeParameters() 0 14 2
A AgingNpDifferentialEvolution.popIncrement() 0 12 1
A AgingNpDifferentialEvolution.aging() 0 19 4
A DynNpMultiStrategyDifferentialEvolution.evolve() 0 13 1
A AgingNpDifferentialEvolution.setParameters() 0 14 1
A DynNpMultiStrategyDifferentialEvolution.postSelection() 0 18 1
A AgingNpDifferentialEvolution.typeParameters() 0 22 5
A MultiStrategyDifferentialEvolution.setParameters() 0 12 1
A AgingNpMultiMutationDifferentialEvolution.setParameters() 0 12 1
A AgingNpDifferentialEvolution.selection() 0 22 1
A DynNpMultiStrategyDifferentialEvolution.setParameters() 0 12 1
A DynNpMultiStrategyDifferentialEvolution.typeParameters() 0 16 3
A AgingNpMultiMutationDifferentialEvolution.evolve() 0 13 1
A AgingIndividual.__init__() 0 11 1
A AgingNpMultiMutationDifferentialEvolution.typeParameters() 0 14 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

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:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

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):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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
1111
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
1112