1
|
|
|
# encoding=utf8 |
2
|
|
|
|
3
|
|
|
import numpy as np |
4
|
|
|
|
5
|
|
|
from NiaPy.algorithms.algorithm import Algorithm |
6
|
|
|
|
7
|
|
|
__all__ = ['GreyWolfOptimizer'] |
8
|
|
|
|
9
|
|
|
class GreyWolfOptimizer(Algorithm): |
10
|
|
|
r"""Implementation of Grey wolf optimizer. |
11
|
|
|
|
12
|
|
|
Algorithm: |
13
|
|
|
Grey wolf optimizer |
14
|
|
|
|
15
|
|
|
Date: |
16
|
|
|
2018 |
17
|
|
|
|
18
|
|
|
Author: |
19
|
|
|
Iztok Fister Jr. and Klemen Berkovič |
20
|
|
|
|
21
|
|
|
License: |
22
|
|
|
MIT |
23
|
|
|
|
24
|
|
|
Reference paper: |
25
|
|
|
* Mirjalili, Seyedali, Seyed Mohammad Mirjalili, and Andrew Lewis. "Grey wolf optimizer." Advances in engineering software 69 (2014): 46-61. |
26
|
|
|
* Grey Wold Optimizer (GWO) source code version 1.0 (MATLAB) from MathWorks |
27
|
|
|
|
28
|
|
|
Attributes: |
29
|
|
|
Name (List[str]): List of strings representing algorithm names. |
30
|
|
|
|
31
|
|
|
See Also: |
32
|
|
|
* :class:`NiaPy.algorithms.Algorithm` |
33
|
|
|
""" |
34
|
|
|
Name = ['GreyWolfOptimizer', 'GWO'] |
35
|
|
|
|
36
|
|
|
@staticmethod |
37
|
|
|
def algorithmInfo(): |
38
|
|
|
r"""Get algorithm information. |
39
|
|
|
|
40
|
|
|
Returns: |
41
|
|
|
str: Algorithm information. |
42
|
|
|
|
43
|
|
|
See Also: |
44
|
|
|
* :func:`NiaPy.algorithms.Algorithm.algorithmInfo` |
45
|
|
|
""" |
46
|
|
|
return r"""Mirjalili, Seyedali, Seyed Mohammad Mirjalili, and Andrew Lewis. "Grey wolf optimizer." Advances in engineering software 69 (2014): 46-61.""" |
47
|
|
|
|
48
|
|
|
@staticmethod |
49
|
|
|
def typeParameters(): return { |
50
|
|
|
'NP': lambda x: isinstance(x, int) and x > 0 |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
def setParameters(self, NP=25, **ukwargs): |
54
|
|
|
r"""Set the algorithm parameters. |
55
|
|
|
|
56
|
|
|
Arguments: |
57
|
|
|
NP (int): Number of individuals in population |
58
|
|
|
|
59
|
|
|
See Also: |
60
|
|
|
* :func:`NiaPy.algorithms.Algorithm.setParameters` |
61
|
|
|
""" |
62
|
|
|
Algorithm.setParameters(self, NP=NP, **ukwargs) |
63
|
|
|
|
64
|
|
|
def initPopulation(self, task): |
65
|
|
|
r"""Initialize population. |
66
|
|
|
|
67
|
|
|
Args: |
68
|
|
|
task (Task): Optimization task. |
69
|
|
|
|
70
|
|
|
Returns: |
71
|
|
|
Tuple[numpy.ndarray, numpy.ndarray, Dict[str, Any]]: |
72
|
|
|
1. Initialized population. |
73
|
|
|
2. Initialized populations fitness/function values. |
74
|
|
|
3. Additional arguments: |
75
|
|
|
* A (): TODO |
76
|
|
|
|
77
|
|
|
See Also: |
78
|
|
|
* :func:`NiaPy.algorithms.Algorithm.initPopulation` |
79
|
|
|
""" |
80
|
|
|
pop, fpop, d = Algorithm.initPopulation(self, task) |
81
|
|
|
si = np.argsort(fpop) |
82
|
|
|
A, A_f, B, B_f, D, D_f = np.copy(pop[si[0]]), fpop[si[0]], np.copy(pop[si[1]]), fpop[si[1]], np.copy(pop[si[2]]), fpop[si[2]] |
83
|
|
|
d.update({'A': A, 'A_f': A_f, 'B': B, 'B_f': B_f, 'D': D, 'D_f': D_f}) |
84
|
|
|
return pop, fpop, d |
85
|
|
|
|
86
|
|
|
def runIteration(self, task, pop, fpop, xb, fxb, A, A_f, B, B_f, D, D_f, **dparams): |
87
|
|
|
r"""Core funciton of GreyWolfOptimizer algorithm. |
88
|
|
|
|
89
|
|
|
Args: |
90
|
|
|
task (Task): Optimization task. |
91
|
|
|
pop (numpy.ndarray): Current population. |
92
|
|
|
fpop (numpy.ndarray): Current populations function/fitness values. |
93
|
|
|
xb (numpy.ndarray): |
94
|
|
|
fxb (float): |
95
|
|
|
A (numpy.ndarray): |
96
|
|
|
A_f (float): |
97
|
|
|
B (numpy.ndarray): |
98
|
|
|
B_f (float): |
99
|
|
|
D (numpy.ndarray): |
100
|
|
|
D_f (float): |
101
|
|
|
**dparams (Dict[str, Any]): Additional arguments. |
102
|
|
|
|
103
|
|
|
Returns: |
104
|
|
|
Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, float, Dict[str, Any]]: |
105
|
|
|
1. New population |
106
|
|
|
2. New population fitness/function values |
107
|
|
|
3. Additional arguments: |
108
|
|
|
* A (): TODO |
109
|
|
|
""" |
110
|
|
|
a = 2 - task.Evals * (2 / task.nFES) |
111
|
|
|
for i, w in enumerate(pop): |
112
|
|
|
A1, C1 = 2 * a * self.rand(task.D) - a, 2 * self.rand(task.D) |
113
|
|
|
X1 = A - A1 * np.fabs(C1 * A - w) |
114
|
|
|
A2, C2 = 2 * a * self.rand(task.D) - a, 2 * self.rand(task.D) |
115
|
|
|
X2 = B - A2 * np.fabs(C2 * B - w) |
116
|
|
|
A3, C3 = 2 * a * self.rand(task.D) - a, 2 * self.rand(task.D) |
117
|
|
|
X3 = D - A3 * np.fabs(C3 * D - w) |
118
|
|
|
pop[i] = task.repair((X1 + X2 + X3) / 3, self.Rand) |
119
|
|
|
fpop[i] = task.eval(pop[i]) |
120
|
|
|
for i, f in enumerate(fpop): |
121
|
|
|
if f < A_f: A, A_f = pop[i].copy(), f |
122
|
|
|
elif A_f < f < B_f: B, B_f = pop[i].copy(), f |
123
|
|
|
elif B_f < f < D_f: D, D_f = pop[i].copy(), f |
124
|
|
|
xb, fxb = self.getBest(A, A_f, xb, fxb) |
125
|
|
|
return pop, fpop, xb, fxb, {'A': A, 'A_f': A_f, 'B': B, 'B_f': B_f, 'D': D, 'D_f': D_f} |
126
|
|
|
|