Passed
Pull Request — master (#233)
by
unknown
01:19
created

NiaPy.algorithms.basic.kh.KrillHerd.crossover()   A

Complexity

Conditions 2

Size

Total Lines 12
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nop 4
dl 0
loc 12
rs 10
c 0
b 0
f 0
1
# encoding=utf8
2
# pylint: disable=mixed-indentation, trailing-whitespace, multiple-statements, attribute-defined-outside-init, logging-not-lazy, arguments-differ, line-too-long, redefined-builtin, singleton-comparison, no-self-use, bad-continuation
3
import logging
4
from scipy.spatial.distance import euclidean as ed
5
from numpy import apply_along_axis, argmin, argmax, sum, full, inf, asarray, mean, where, sqrt
6
from NiaPy.util import fullArray
7
from NiaPy.algorithms.algorithm import Algorithm
8
9
logging.basicConfig()
10
logger = logging.getLogger('NiaPy.algorithms.basic')
11
logger.setLevel('INFO')
12
13
__all__ = ['KrillHerdV1', 'KrillHerdV2', 'KrillHerdV3', 'KrillHerdV4', 'KrillHerdV11']
14
15
class KrillHerd(Algorithm):
16
	r"""Implementation of krill herd algorithm.
17
18
	Algorithm:
19
		Krill Herd Algorithm
20
21
	Date:
22
		2018
23
24
	Authors:
25
		Klemen Berkovič
26
27
	License:
28
		MIT
29
30
	Reference URL:
31
		http://www.sciencedirect.com/science/article/pii/S1007570412002171
32
33
	Reference paper:
34
		Amir Hossein Gandomi, Amir Hossein Alavi, Krill herd: A new bio-inspired optimization algorithm, Communications in Nonlinear Science and Numerical Simulation, Volume 17, Issue 12, 2012, Pages 4831-4845, ISSN 1007-5704, https://doi.org/10.1016/j.cnsns.2012.05.010.
35
36
	Attributes:
37
		Name (List[str]): List of strings representing algorithm names..
38
		NP (int): Number of krill herds in population.
39
		N_max (float): Maximum induced speed.
40
		V_f (float): Foraging speed.
41
		D_max (float): Maximum diffusion speed.
42
		C_t (float): Constant :math:`\in [0, 2]`
43
		W_n (Union[int, float, numpy.ndarray]): Interta weights of the motion induced from neighbors :math:`\in [0, 1]`.
44
		W_f (Union[int, float, numpy.ndarray]): Interta weights of the motion induced from foraging :math`\in [0, 1]`.
45
		d_s (float): Maximum euclidean distance for neighbors.
46
		nn (int): Maximum neighbors for neighbors effect.
47
		Cr (float): Crossover probability.
48
		Mu (float): Mutation probability.
49
		epsilon (float): Small numbers for division.
50
51
	See Also:
52
		* :class:`NiaPy.algorithms.algorithm.Algorithm`
53
	"""
54
	Name = ['KrillHerd', 'KH']
55
56
	@staticmethod
57
	def typeParameters():
58
		r"""Get dictionary with functions for checking values of parameters.
59
60
		Returns:
61
			Dict[str, Callable]:
62
				* N_max (Callable[[Union[int, float]], bool])
63
				* V_f (Callable[[Union[int, float]], bool])
64
				* D_max (Callable[[Union[int, float]], bool])
65
				* C_t (Callable[[Union[int, float]], bool])
66
				* W_n (Callable[[Union[int, float]], bool])
67
				* W_f (Callable[[Union[int, float]], bool])
68
				* d_s (Callable[[Union[int, float]], boool])
69
				* nn (Callable[[int], bool])
70
				* Cr (Callable[[float], bool])
71
				* Mu (Callable[[float], bool])
72
				* epsilon (Callable[[float], bool])
73
74
		See Also:
75
			* :func:`NiaPy.algorithms.algorithm.Algorithm`
76
		"""
77
		d = Algorithm.typeParameters()
78
		d.update({
79
			'N_max': lambda x: isinstance(x, (int, float)) and x > 0,
80
			'V_f': lambda x: isinstance(x, (int, float)) and x > 0,
81
			'D_max': lambda x: isinstance(x, (int, float)) and x > 0,
82
			'C_t': lambda x: isinstance(x, (int, float)) and x > 0,
83
			'W_n': lambda x: isinstance(x, (int, float)) and x > 0,
84
			'W_f': lambda x: isinstance(x, (int, float)) and x > 0,
85
			'd_s': lambda x: isinstance(x, (int, float)) and x > 0,
86
			'nn': lambda x: isinstance(x, int) and x > 0,
87
			'Cr': lambda x: isinstance(x, float) and 0 <= x <= 1,
88
			'Mu': lambda x: isinstance(x, float) and 0 <= x <= 1,
89
			'epsilon': lambda x: isinstance(x, float) and 0 < x < 1
90
		})
91
		return d
92
93
	def setParameters(self, NP=50, N_max=0.01, V_f=0.02, D_max=0.002, C_t=0.93, W_n=0.42, W_f=0.38, d_s=2.63, nn=5, Cr=0.2, Mu=0.05, epsilon=1e-31, **ukwargs):
94
		r"""Set the arguments of an algorithm.
95
96
		Arguments:
97
			NP (Optional[int]): Number of krill herds in population.
98
			N_max (Optional[float]): Maximum induced speed.
99
			V_f (Optional[float]): Foraging speed.
100
			D_max (Optional[float]): Maximum diffusion speed.
101
			C_t (Optional[float]): Constant $\in [0, 2]$.
102
			W_n (Optional[Union[int, float, numpy.ndarray]]): Intera weights of the motion induced from neighbors :math:`\in [0, 1]`.
103
			W_f (Optional[Union[int, float, numpy.ndarray]]): Intera weights of the motion induced from foraging :math:`\in [0, 1]`.
104
			d_s (Optional[float]): Maximum euclidean distance for neighbors.
105
			nn (Optional[int]): Maximum neighbors for neighbors effect.
106
			Cr (Optional[float]): Crossover probability.
107
			Mu (Optional[float]): Mutation probability.
108
			epsilon (Optional[float]): Small numbers for division.
109
110
		See Also:
111
			* :func:`NiaPy.algorithms.algorithm.Algorithm.setParameters`
112
		"""
113
		Algorithm.setParameters(self, NP=NP, **ukwargs)
114
		self.N_max, self.V_f, self.D_max, self.C_t, self.W_n, self.W_f, self.d_s, self.nn, self._Cr, self._Mu, self.epsilon = N_max, V_f, D_max, C_t, W_n, W_f, d_s, nn, Cr, Mu, epsilon
115
116
	def getParameters(self):
117
		r"""Get parameter values for the algorithm.
118
119
		Returns:
120
			Dict[str, Any]: TODO.
121
		"""
122
		d = Algorithm.getParameters(self)
123
		d.update({
124
			'N_max': self.N_max,
125
			'V_f': self.V_f,
126
			'D_max': self.D_max,
127
			'C_t': self.C_t,
128
			'W_n': self.W_n,
129
			'W_f': self.W_f,
130
			'd_s': self.d_s,
131
			'nn': self.nn,
132
			'Cr': self.Cr,
133
			'Mu': self.Mu,
134
			'epsilon': self.epsilon
135
		})
136
		return d
137
138
	def initWeights(self, task):
139
		r"""Initialize weights.
140
141
		Args:
142
			task (Task): Optimization task.
143
144
		Returns:
145
			Tuple[numpy.ndarray, numpy.ndarray]:
146
				1. Weights for neighborhood.
147
				2. Weights for foraging.
148
		"""
149
		return fullArray(self.W_n, task.D), fullArray(self.W_f, task.D)
150
151
	def sensRange(self, ki, KH):
152
		r"""Calculate sense range for selected individual.
153
154
		Args:
155
			ki (int): Selected individual.
156
			KH (numpy.ndarray): Krill heard population.
157
158
		Returns:
159
			float: Sense range for krill.
160
		"""
161
		return sum([ed(KH[ki], KH[i]) for i in range(self.NP)]) / (self.nn * self.NP)
162
163
	def getNeighbours(self, i, ids, KH):
164
		r"""Get neighbours.
165
166
		Args:
167
			i (int): Individual looking for neighbours.
168
			ids (float): Maximal distance for being a neighbour.
169
			KH (numpy.ndarray): Current population.
170
171
		Returns:
172
			numpy.ndarray: Neighbours of krill heard.
173
		"""
174
		N = list()
175
		for j in range(self.NP):
176
			if j != i and ids > ed(KH[i], KH[j]): N.append(j)
177
		if not N: N.append(self.randint(self.NP))
178
		return asarray(N)
179
180
	def funX(self, x, y):
181
		r"""Get x values.
182
183
		Args:
184
			x (numpy.ndarray): First krill/individual.
185
			y (numpy.ndarray): Second krill/individual.
186
187
		Returns:
188
			numpy.ndarray: --
189
		"""
190
		return ((y - x) + self.epsilon) / (ed(y, x) + self.epsilon)
191
192
	def funK(self, x, y, b, w):
193
		r"""Get k values.
194
195
		Args:
196
			x (numpy.ndarray): First krill/individual.
197
			y (numpy.ndarray): Second krill/individual.
198
			b (numpy.ndarray): Best krill/individual.
199
			w (numpy.ndarray): Worst krill/individual.
200
201
		Returns:
202
			numpy.ndarray: --
203
		"""
204
		return ((x - y) + self.epsilon) / ((w - b) + self.epsilon)
205
206
	def induceNeighborsMotion(self, i, n, W, KH, KH_f, ikh_b, ikh_w, task):
207
		r"""Induced neighbours motion operator.
208
209
		Args:
210
			i (int): Index of individual being applied with operator.
211
			n:
212
			W (numpy.ndarray[float]): Wights for this operator.
213
			KH (numpy.ndarray): Current heard/population.
214
			KH_f (numpy.ndarray[float]): Current populations/heard function/fitness values.
215
			ikh_b (int): Current best krill in heard/population.
216
			ikh_w (int): Current worst krill in heard/population.
217
			task (Task): Optimization task.
218
219
		Returns:
220
			numpy.ndarray: Moved krill.
221
		"""
222
		Ni = self.getNeighbours(i, self.sensRange(i, KH), KH)
223
		Nx, Nf, f_b, f_w = KH[Ni], KH_f[Ni], KH_f[ikh_b], KH_f[ikh_w]
224
		alpha_l = sum(asarray([self.funK(KH_f[i], j, f_b, f_w) for j in Nf]) * asarray([self.funX(KH[i], j) for j in Nx]).T)
225
		alpha_t = 2 * (1 + self.rand() * task.Iters / task.nGEN)
226
		return self.N_max * (alpha_l + alpha_t) + W * n
227
228
	def induceForagingMotion(self, i, x, x_f, f, W, KH, KH_f, ikh_b, ikh_w, task):
229
		r"""Induced foraging motion operator.
230
231
		Args:
232
			i (int): Index of current krill being operated.
233
			x (numpy.ndarray): Position of food.
234
			x_f (float): Fitness/function values of food.
235
			f:
236
			W (numpy.ndarray[float]): Weights for this operator.
237
			KH (numpy.ndarray):  Current population/heard.
238
			KH_f (numpy.ndarray[float]): Current heard/populations function/fitness values.
239
			ikh_b (int): Index of current best krill in heard.
240
			ikh_w (int): Index of current worst krill in heard.
241
			task (Task): Optimization task.
242
243
		Returns:
244
			numpy.ndarray: Moved krill.
245
		"""
246
		beta_f = 2 * (1 - task.Iters / task.nGEN) * self.funK(KH_f[i], x_f, KH_f[ikh_b], KH_f[ikh_w]) * self.funX(KH[i], x) if KH_f[ikh_b] < KH_f[i] else 0
247
		beta_b = self.funK(KH_f[i], KH_f[ikh_b], KH_f[ikh_b], KH_f[ikh_w]) * self.funX(KH[i], KH[ikh_b])
248
		return self.V_f * (beta_f + beta_b) + W * f
249
250
	def inducePhysicalDiffusion(self, task):
251
		r"""Induced physical diffusion operator.
252
253
		Args:
254
			task (Task): Optimization task.
255
256
		Returns:
257
			numpy.ndarray:
258
		"""
259
		return self.D_max * (1 - task.Iters / task.nGEN) * self.uniform(-1, 1, task.D)
260
261
	def deltaT(self, task):
262
		r"""Get new delta for all dimensions.
263
264
		Args:
265
			task (Task): Optimization task.
266
267
		Returns:
268
			numpy.ndarray: --
269
		"""
270
		return self.C_t * sum(task.bRange)
271
272
	def crossover(self, x, xo, Cr):
273
		r"""Crossover operator.
274
275
		Args:
276
			x (numpy.ndarray): Krill/individual being applied with operator.
277
			xo (numpy.ndarray): Krill/individual being used in conjunction within operator.
278
			Cr (float): Crossover probability.
279
280
		Returns:
281
			numpy.ndarray: Crossoverd krill/individual.
282
		"""
283
		return [xo[i] if self.rand() < Cr else x[i] for i in range(len(x))]
284
285
	def mutate(self, x, x_b, Mu):
286
		r"""Mutate operator.
287
288
		Args:
289
			x (numpy.ndarray): Individual being mutated.
290
			x_b (numpy.ndarray): Global best individual.
291
			Mu (float): Probability of mutations.
292
293
		Returns:
294
			numpy.ndarray: Mutated krill.
295
		"""
296
		return [x[i] if self.rand() < Mu else (x_b[i] + self.rand()) for i in range(len(x))]
297
298
	def getFoodLocation(self, KH, KH_f, task):
299
		r"""Get food location for krill heard.
300
301
		Args:
302
			KH (numpy.ndarray): Current heard/population.
303
			KH_f (numpy.ndarray[float]): Current heard/populations function/fitness values.
304
			task (Task): Optimization task.
305
306
		Returns:
307
			Tuple[numpy.ndarray, float]:
308
				1. Location of food.
309
				2. Foods function/fitness value.
310
		"""
311
		x_food = task.repair(asarray([sum(KH[:, i] / KH_f) for i in range(task.D)]) / sum(1 / KH_f), rnd=self.Rand)
312
		x_food_f = task.eval(x_food)
313
		return x_food, x_food_f
314
315
	def Mu(self, xf, yf, xf_best, xf_worst):
316
		r"""Get mutation probability.
317
318
		Args:
319
			xf (float):
320
			yf (float):
321
			xf_best (float):
322
			xf_worst (float):
323
324
		Returns:
325
			float: New mutation probability.
326
		"""
327
		return self._Mu / (self.funK(xf, yf, xf_best, xf_worst) + 1e-31)
328
329
	def Cr(self, xf, yf, xf_best, xf_worst):
330
		r"""Get crossover probability.
331
332
		Args:
333
			xf (float):
334
			yf (float):
335
			xf_best (float):
336
			xf_worst (flaot):
337
338
		Returns:
339
			float: New crossover probability.
340
		"""
341
		return self._Cr * self.funK(xf, yf, xf_best, xf_worst)
342
343
	def initPopulation(self, task):
344
		r"""Initialize stating population.
345
346
		Args:
347
			task (Task): Optimization task.
348
349
		Returns:
350
			Tuple[numpy.ndarray, numpy.ndarray, Dict[str, Any]]:
351
				1. Initialized population.
352
				2. Initialized populations function/fitness values.
353
				3. Additional arguments:
354
					* W_n (numpy.ndarray): Weights neighborhood.
355
					* W_f (numpy.ndarray): Weights foraging.
356
					* N (numpy.ndarray): TODO
357
					* F (numpy.ndarray): TODO
358
359
		See Also:
360
			* :func:`NiaPy.algorithms.algorithm.Algorithm.initPopulation`
361
		"""
362
		KH, KH_f, d = Algorithm.initPopulation(self, task)
363
		W_n, W_f = self.initWeights(task)
364
		N, F = full(self.NP, .0), full(self.NP, .0)
365
		d.update({'W_n': W_n, 'W_f': W_f, 'N': N, 'F': F})
366
		return KH, KH_f, d
367
368
	def runIteration(self, task, KH, KH_f, xb, fxb, W_n, W_f, N, F, **dparams):
369
		r"""Core function of KrillHerd algorithm.
370
371
		Args:
372
			task (Task): Optimization task.
373
			KH (numpy.ndarray): Current heard/population.
374
			KH_f (numpy.ndarray[float]): Current heard/populations function/fitness values.
375
			xb (numpy.ndarray): Global best individual.
376
			fxb (float): Global best individuals function fitness values.
377
			W_n (numpy.ndarray):
378
			W_f (numpy.ndarray):
379
			N ():
380
			F ():
381
			**dparams (Dict[str, Any]): Additional arguments.
382
383
		Returns:
384
			Tuple [numpy.ndarray, numpy.ndarray, numpy.ndarray, float Dict[str, Any]]:
385
				1. New herd/population
386
				2. New herd/populations function/fitness values.
387
				3. New global best solution.
388
				4. New global best solutoins fitness/objective value.
389
				5. Additional arguments:
390
					* W_n (numpy.ndarray): --
391
					* W_f (numpy.ndarray): --
392
					* N (numpy.ndarray): --
393
					* F (numpy.ndarray): --
394
		"""
395
		ikh_b, ikh_w = argmin(KH_f), argmax(KH_f)
396
		x_food, x_food_f = self.getFoodLocation(KH, KH_f, task)
397
		if x_food_f < fxb: xb, fxb = x_food, x_food_f  # noqa: F841
398
		N = asarray([self.induceNeighborsMotion(i, N[i], W_n, KH, KH_f, ikh_b, ikh_w, task) for i in range(self.NP)])
399
		F = asarray([self.induceForagingMotion(i, x_food, x_food_f, F[i], W_f, KH, KH_f, ikh_b, ikh_w, task) for i in range(self.NP)])
400
		D = asarray([self.inducePhysicalDiffusion(task) for i in range(self.NP)])
401
		KH_n = KH + (self.deltaT(task) * (N + F + D))
402
		Cr = asarray([self.Cr(KH_f[i], KH_f[ikh_b], KH_f[ikh_b], KH_f[ikh_w]) for i in range(self.NP)])
403
		KH_n = asarray([self.crossover(KH_n[i], KH[i], Cr[i]) for i in range(self.NP)])
404
		Mu = asarray([self.Mu(KH_f[i], KH_f[ikh_b], KH_f[ikh_b], KH_f[ikh_w]) for i in range(self.NP)])
405
		KH_n = asarray([self.mutate(KH_n[i], KH[ikh_b], Mu[i]) for i in range(self.NP)])
406
		KH = apply_along_axis(task.repair, 1, KH_n, rnd=self.Rand)
407
		KH_f = apply_along_axis(task.eval, 1, KH)
408
		xb, fxb = self.getBest(KH, KH_f, xb, fxb)
409
		return KH, KH_f, xb, fxb, {'W_n': W_n, 'W_f': W_f, 'N': N, 'F': F}
410
411
class KrillHerdV4(KrillHerd):
412
	r"""Implementation of krill herd algorithm.
413
414
	Algorithm:
415
		Krill Herd Algorithm
416
417
	Date:
418
		2018
419
420
	Authors:
421
		Klemen Berkovič
422
423
	License:
424
		MIT
425
426
	Reference URL:
427
		http://www.sciencedirect.com/science/article/pii/S1007570412002171
428
429
	Reference paper:
430
		Amir Hossein Gandomi, Amir Hossein Alavi, Krill herd: A new bio-inspired optimization algorithm, Communications in Nonlinear Science and Numerical Simulation, Volume 17, Issue 12, 2012, Pages 4831-4845, ISSN 1007-5704, https://doi.org/10.1016/j.cnsns.2012.05.010.
431
432
	Attributes:
433
		Name (List[str]): List of strings representing algorithm name.
434
	"""
435
	Name = ['KrillHerdV4', 'KHv4']
436
437
	@staticmethod
438
	def typeParameters():
439
		r"""Get dictionary with functions for checking values of parameters.
440
441
		Returns:
442
			Dict[str, Callable]: Dictionary with testing functions for parameters.
443
444
		See Also:
445
			* :func:NiaPy.algorithms.basic.kh.KrillHerd.typeParameters`
446
		"""
447
		d = KrillHerd.typeParameters()
448
		d.pop('Cr', None)
449
		d.pop('Mu', None)
450
		d.pop('epsilon', None)
451
		return d
452
453
	def setParameters(self, NP=50, N_max=0.01, V_f=0.02, D_max=0.002, C_t=0.93, W_n=0.42, W_f=0.38, d_s=2.63, **ukwargs):
454
		r"""Set algorithm core parameters.
455
456
		Args:
457
			NP (int): Number of kills in herd.
458
			N_max (Optional[float]): TODO
459
			V_f (Optional[float]): TODO
460
			D_max (Optional[float]): TODO
461
			C_t (Optional[float]): TODO
462
			W_n (Optional[Union[int, float, numpy.ndarray, list]]): Weights for neighborhood.
463
			W_f (Optional[Union[int, float, numpy.ndarray, list]]): Weights for foraging.
464
			d_s (Optional[float]): TODO
465
			**ukwargs (Dict[str, Any]): Additional arguments.
466
467
		See Also:
468
			* :func:NiaPy.algorithms.basic.kh.KrillHerd.KrillHerd.setParameters`
469
		"""
470
		KrillHerd.setParameters(self, NP=NP, N_max=N_max, V_f=V_f, D_max=D_max, C_t=C_t, W_n=W_n, W_f=W_f, d_s=d_s, nn=4, Cr=0.2, Mu=0.05, epsilon=1e-31, **ukwargs)
471
472
class KrillHerdV1(KrillHerd):
473
	r"""Implementation of krill herd algorithm.
474
475
	Algorithm:
476
		Krill Herd Algorithm
477
478
	Date:
479
		2018
480
481
	Authors:
482
		Klemen Berkovič
483
484
	License:
485
		MIT
486
487
	Reference URL:
488
		http://www.sciencedirect.com/science/article/pii/S1007570412002171
489
490
	Reference paper:
491
		Amir Hossein Gandomi, Amir Hossein Alavi, Krill herd: A new bio-inspired optimization algorithm, Communications in Nonlinear Science and Numerical Simulation, Volume 17, Issue 12, 2012, Pages 4831-4845, ISSN 1007-5704, https://doi.org/10.1016/j.cnsns.2012.05.010.
492
493
	Attributes:
494
		Name (List[str]): List of strings representing algorithm name.
495
496
	See Also:
497
		* :func:NiaPy.algorithms.basic.kh.KrillHerd.KrillHerd`
498
	"""
499
	Name = ['KrillHerdV1', 'KHv1']
500
501
	@staticmethod
502
	def typeParameters():
503
		r"""Get dictionary with functions for checking values of parameters.
504
505
		Returns:
506
			Dict[str, Callable]: Dictionary with testing functions for parameters.
507
508
		See Also:
509
			* :func:NiaPy.algorithms.basic.kh.KrillHerd.typeParameters`
510
		"""
511
		return KrillHerd.typeParameters()
512
513
	def crossover(self, x, xo, Cr):
514
		r"""Preform a crossover operation on individual.
515
516
		Args:
517
			x (numpy.ndarray): Current individual.
518
			xo (numpy.ndarray): New individual.
519
			Cr (float): Crossover probability.
520
521
		Returns:
522
			numpy.ndarray: Crossover individual.
523
		"""
524
		return x
525
526
	def mutate(self, x, x_b, Mu):
527
		r"""Mutate individual.
528
529
		Args:
530
			x (numpy.ndarray): Current individual.
531
			x_b (numpy.ndarray): Global best individual.
532
			Mu (float): Mutation probability.
533
534
		Returns:
535
			numpy.ndarray: Mutated krill.
536
		"""
537
		return x
538
539
class KrillHerdV2(KrillHerd):
540
	r"""Implementation of krill herd algorithm.
541
542
	Algorithm:
543
		Krill Herd Algorithm
544
545
	Date:
546
		2018
547
548
	Authors:
549
		Klemen Berkovič
550
551
	License:
552
		MIT
553
554
	Reference URL:
555
		http://www.sciencedirect.com/science/article/pii/S1007570412002171
556
557
	Reference paper:
558
		Amir Hossein Gandomi, Amir Hossein Alavi, Krill herd: A new bio-inspired optimization algorithm, Communications in Nonlinear Science and Numerical Simulation, Volume 17, Issue 12, 2012, Pages 4831-4845, ISSN 1007-5704, https://doi.org/10.1016/j.cnsns.2012.05.010.
559
560
	Attributes:
561
		Name (List[str]): List of strings representing algorithm name.
562
	"""
563
	Name = ['KrillHerdV2', 'KHv2']
564
565
	@staticmethod
566
	def typeParameters():
567
		r"""Get dictionary with functions for checking values of parameters.
568
569
		Returns:
570
			Dict[str, Callable]: Dictionary with testing functions for algorithms parameters.
571
572
		See Also:
573
			* :func:NiaPy.algorithms.basic.kh.KrillHerd.typeParameters`
574
		"""
575
		d = KrillHerd.typeParameters()
576
		d.pop('Mu', None)
577
		return d
578
579
	def mutate(self, x, x_b, Mu):
580
		r"""Mutate individual.
581
582
		Args:
583
			x (numpy.ndarray): Individual to mutate.
584
			x_b (numpy.ndarray): Global best individual.
585
			Mu (float): Mutation probability.
586
587
		Returns:
588
			numpy.ndarray: Mutated individual.
589
		"""
590
		return x
591
592
class KrillHerdV3(KrillHerd):
593
	r"""Implementation of krill herd algorithm.
594
595
	Algorithm:
596
		Krill Herd Algorithm
597
598
	Date:
599
		2018
600
601
	Authors:
602
		Klemen Berkovič
603
604
	License:
605
		MIT
606
607
	Reference URL:
608
		http://www.sciencedirect.com/science/article/pii/S1007570412002171
609
610
	Reference paper:
611
		Amir Hossein Gandomi, Amir Hossein Alavi, Krill herd: A new bio-inspired optimization algorithm, Communications in Nonlinear Science and Numerical Simulation, Volume 17, Issue 12, 2012, Pages 4831-4845, ISSN 1007-5704, https://doi.org/10.1016/j.cnsns.2012.05.010.
612
	"""
613
	Name = ['KrillHerdV3', 'KHv3']
614
615
	@staticmethod
616
	def typeParameters():
617
		r"""Get dictionary with functions for checking values of parameters.
618
619
		Returns:
620
			Dict[str, Callable]: Dictionary with testing functions for algorithms parameters.
621
622
		See Also:
623
			* :func:NiaPy.algorithms.basic.kh.KrillHerd.typeParameters`
624
		"""
625
		d = KrillHerd.typeParameters()
626
		d.pop('Cr', None)
627
		return d
628
629
	def crossover(self, x, xo, Cr):
630
		r"""Crossover operator.
631
632
		Args:
633
			x (numpy.ndarray): Krill/individual being applied with operator.
634
			xo (numpy.ndarray): Krill/individual being used in operator.
635
			Cr (float): Crossover probability.
636
637
		Returns:
638
			numpy.ndarray: Crossover krill/individual.
639
		"""
640
		return x
641
642
class KrillHerdV11(KrillHerd):
643
	r"""Implementation of krill herd algorithm.
644
645
	Algorithm:
646
		Krill Herd Algorithm
647
648
	Date:
649
		2018
650
651
	Authors:
652
		Klemen Berkovič
653
654
	License:
655
		MIT
656
657
	Reference URL:
658
659
	Reference paper:
660
	"""
661
	Name = ['KrillHerdV11', 'KHv11']
662
663
	def ElitistSelection(self, KH, KH_f, KHo, KHo_f):
664
		r"""Select krills/individuals that are better than odl krills.
665
666
		Args:
667
			KH (numpy.ndarray): Current herd/population.
668
			KH_f (numpy.ndarray[float]): Current herd/populations function/fitness values
669
			KHo (numpy.ndarray): New herd/population.
670
			KHo_f (numpy.ndarray[float]): New herd/populations function/fitness vales.
671
672
		Returns:
673
			Tuple[numpy.ndarray, numpy.numpy[float]]:
674
				1. New herd/population.
675
				2. New herd/populations function/fitness values.
676
		"""
677
		ipb = where(KHo_f >= KH_f)
678
		KHo[ipb], KHo_f[ipb] = KH[ipb], KH_f[ipb]
679
		return KHo, KHo_f
680
681
	def Neighbors(self, i, KH, KH_f, iw, ib, N, W_n, task):
682
		r"""Neighbors operator.
683
684
		Args:
685
			i (int): Index of krill being applied with operator.
686
			KH (numpy.ndarray): Current herd/population.
687
			KH_f (numpy.ndarray[float]): Current herd/populations function/fitness values.
688
			iw (int): Index of worst krill/individual.
689
			ib (int): Index of best krill/individual.
690
			N (): --
691
			W_n (numpy.ndarray): Weights for neighbors operator.
692
			task (Task): Optimization task.
693
694
		Returns:
695
			numpy.ndarray: --
696
		"""
697
		Rgb, RR, Kw_Kgb = KH[ib] - KH[i], KH - KH[i], KH_f[iw] - KH_f[ib]
698
		R = sqrt(sum(RR * RR))
699
		alpha_b = -2 * (1 + self.rand() * task.Iters / task.nGEN) * (KH_f[ib]) / Kw_Kgb / sqrt(sum(Rgb * Rgb)) * Rgb if KH_f[ib] < KH_f[i] else 0
700
		alpah_n, nn, ds = 0.0, 0, mean(R) / 5
701
		for n in range(self.NP):
702
			if R < ds and n != i:
703
				nn += 1
704
				if nn <= 4 and KH_f[i] != KH[n]: alpah_n -= (KH(n) - KH[i]) / Kw_Kgb / R[n] * RR[n]
705
		return W_n * N * self.N_max * (alpha_b + alpah_n)
706
707
	def Foraging(self, KH, KH_f, KHo, KHo_f, W_f, F, KH_wf, KH_bf, x_food, x_food_f, task):
708
		r"""Foraging operator.
709
710
		Args:
711
			KH (numpy.ndarray): Current heard/population.
712
			KH_f (numpy.ndarray[float]): Current herd/populations function/fitness values.
713
			KHo (numpy.ndarray): New heard/population.
714
			KHo_f (numpy.ndarray[float]): New heard/population function/fitness values.
715
			W_f (numpy.ndarray): Weights for foraging.
716
			F (): --
717
			KH_wf (numpy.ndarray): Worst krill in herd/population.
718
			KH_bf (numpy.ndarray): Best krill in herd/population.
719
			x_food (numpy.ndarray): Foods position.
720
			x_food_f (float): Foods function/fitness value.
721
			task (Task): Optimization task.
722
723
		Returns:
724
			numpy.ndarray: --
725
		"""
726
		Rf, Kw_Kgb = x_food - KH, KH_wf - KH_bf
727
		beta_f = -2 * (1 - task.Iters / task.nGEN) * (x_food_f - KH_f) / Kw_Kgb / sqrt(sum(Rf * Rf)) * Rf if x_food_f < KH_f else 0
728
		Rib = KHo - KH
729
		beta_b = -(KHo_f - KH_f) / Kw_Kgb / sqrt(sum(Rib * Rib)) * Rib if KHo_f < KH_f else 0
730
		return W_f * F + self.V_f * (beta_b + beta_f)
731
732
	def Cr(self, KH_f, KHb_f, KHw_f):
733
		r"""Calculate crossover probability.
734
735
		Args:
736
			KH_f (float): Krill/individuals function/fitness value.
737
			KHb_f (float): Best krill/individual function/fitness value.
738
			KHw_f (float): Worst krill/individual function/fitness value.
739
740
		Returns:
741
			float: Crossover probability.
742
		"""
743
		return 0.8 + 0.2 * (KH_f - KHb_f) / (KHw_f - KHb_f)
744
745
	def initPopulation(self, task):
746
		r"""Initialize firt herd/population.
747
748
		Args:
749
			task (Task): Optimization task.
750
751
		Returns:
752
			Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
753
				1. Initialized herd/population.
754
				2. Initialized herd/populations function/fitness values.
755
				3. Additional arguments:
756
					* KHo (): --
757
					* KHo_f (): --
758
					* N (): --
759
					* F (): --
760
					* Dt (): --
761
762
		See Also:
763
			* :func:`NiaPy.algorithms.Algorithm.initPopulation`
764
		"""
765
		KH, KH_f, d = Algorithm.initPopulation(self, task)
766
		KHo, KHo_f = full([self.NP, task.D], task.optType.value * inf), full(self.NP, task.optType.value * inf)
767
		N, F, Dt = full(self.NP, .0), full(self.NP, .0), mean(task.bcRange()) / 2
768
		d.update({'KHo': KHo, 'KHo_f': KHo_f, 'N': N, 'F': F, 'Dt': Dt})
769
		return KH, KH_f, d
770
771
	def runIteration(self, task, KH, KH_f, xb, fxb, KHo, KHo_f, N, F, Dt, **dparams):
772
		r"""Core function of KrillHerdV11 algorithm.
773
774
		Args:
775
			task (Task): Optimization task.
776
			KH (numpy.ndarray): Current herd/population.
777
			KH_f (numpy.ndarray[float]): Current herd/populations function/fitness values.
778
			xb (numpy.ndarray): Global best krill.
779
			fxb (float): Global best krill function/fitness value.
780
			KHo ():
781
			KHo_f ():
782
			N ():
783
			F ():
784
			Dt ():
785
			**dparams (Dict[str, Any]): Additional arguments.
786
787
		Returns:
788
			Tuple[numpy.ndarray, numpy.ndarray[float], Dict[str, Any]]:
789
				1. New herd/population.
790
				2. New herd/populations function/fitness values.
791
				3. Additional arguments:
792
793
		"""
794
		w = full(task.D, 0.1 + 0.8 * (1 - task.Iters / task.nGEN))
795
		ib, iw = argmin(KH_f), argmax(KH_f)
796
		x_food, x_food_f = self.getFoodLocation(KH, KH_f, task)
797
		xb, fxb = self.getBest(x_food, x_food_f, xb, fxb)
798
		N = asarray([self.Neighbors(i, KH, KH_f, iw, ib, N[i], w, task) for i in range(self.NP)])
799
		F = asarray([self.Foraging(KH[i], KH_f[i], KHo[i], KHo_f[i], w, F[i], KH_f[iw], KH_f[ib], x_food, x_food_f, task) for i in range(self.NP)])
800
		Cr = asarray([self.Cr(KH_f[i], KH_f[ib], KH_f[iw]) for i in range(self.NP)])
801
		KH_n = asarray([self.crossover(KH[self.randint(self.NP)], KH[i], Cr[i]) for i in range(self.NP)])
802
		KH_n = KH + Dt * (F + N)
803
		KH = apply_along_axis(task.repair, 1, KH_n, self.Rand)
804
		KH_f = apply_along_axis(task.eval, 1, KH)
805
		KHo, KHo_f = self.ElitistSelection(KH, KH_f, KHo, KHo_f)
806
		xb, fxb = self.getBest(KH, KH_f, xb, fxb)
807
		return KH, KH_f, xb, fxb, {'KHo': KHo, 'KHo_f': KHo_f, 'N': N, 'F': F, 'Dt': Dt}
808
809
# vim: tabstop=3 noexpandtab shiftwidth=3 softtabstop=3
810