-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathGWO.py
144 lines (127 loc) · 4.3 KB
/
GWO.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2022/9/28 12:26
# @Author : Xavier Ma
# @Email : [email protected]
# @File : GWO.py
# @Statement : The grey wolf optimizer
# @Reference : Mirjalili S, Mirjalili S M, Lewis A. Grey wolf optimizer[J]. Advances in Engineering Software, 2014, 69: 46-61.
import random
import math
import matplotlib.pyplot as plt
def obj(x):
"""
The objective function of reservoir
:param x:
:return:
"""
x1 = x[0]
x2 = x[1]
x3 = x[2]
x4 = x[3]
g1 = -x1 + 0.0193 * x3
g2 = -x2 + 0.00954 * x3
g3 = -math.pi * x3 ** 2 - 4 * math.pi * x3 ** 3 / 3 + 1296000
g4 = x4 - 240
if g1 <= 0 and g2 <= 0 and g3 <= 0 and g4 <= 0:
return 0.6224 * x1 * x3 * x4 + 1.7781 * x2 * x3 ** 2 + 3.1661 * x1 ** 2 * x4 + 19.84 * x1 ** 2 * x3
else:
return 1e10
def boundary_check(x, lb, ub, dim):
"""
Check the boundary
:param x: a candidate solution
:param lb: lower bound
:param ub: upper bound
:param dim: dimension
:return:
"""
for i in range(dim):
if x[i] < lb[i]:
x[i] = lb[i]
elif x[i] > ub[i]:
x[i] = ub[i]
return x
def main(pop, lb, ub, iter):
"""
The main function of GWO
:param pop: the number of wolves
:param lb: the lower bound (list)
:param ub: the upper bound (list)
:param iter: the iteration number
:return:
"""
# Step 1. Initialization
dim = len(ub) # dimension
pos = []
score = []
iter_best = [] # the best ever value of each iteration
for _ in range(pop):
temp_pos = [random.uniform(lb[i], ub[i]) for i in range(dim)]
temp_score = obj(temp_pos)
pos.append(temp_pos)
score.append(temp_score)
sorted_score = sorted(score)
alpha_score = sorted_score[0]
alpha_pos = pos[score.index(alpha_score)].copy()
beta_score = sorted_score[1]
beta_pos = pos[score.index(beta_score)].copy()
delta_score = sorted_score[2]
delta_pos = pos[score.index(delta_score)].copy()
iter_best.append(alpha_score)
# Step 2. The main loop
for t in range(iter):
a = 2 - 2 * (t + 1) / iter
for i in range(pop):
for j in range(dim):
# Calculate the distance between alpha
r1 = random.random()
r2 = random.random()
A1 = 2 * a * r1 - a
C1 = 2 * r2
D_alpha = abs(C1 * alpha_pos[j] - pos[i][j])
X1 = alpha_pos[j] - A1 * D_alpha
# Calculate the distance between beta
r1 = random.random()
r2 = random.random()
A2 = 2 * a * r1 - a
C2 = 2 * r2
D_alpha = abs(C2 * beta_pos[j] - pos[i][j])
X2 = beta_pos[j] - A2 * D_alpha
# Calculate the distance between delta
r1 = random.random()
r2 = random.random()
A3 = 2 * a * r1 - a
C3 = 2 * r2
D_alpha = abs(C3 * delta_pos[j] - pos[i][j])
X3 = delta_pos[j] - A3 * D_alpha
pos[i][j] = (X1 + X2 + X3) / 3
# Check the boundary
pos[i] = boundary_check(pos[i], lb, ub, dim)
# Update the score
score[i] = obj(pos[i])
if score[i] < alpha_score:
alpha_score = score[i]
alpha_pos = pos[i].copy()
elif score[i] < beta_score:
beta_score = score[i]
beta_pos = pos[i].copy()
elif score[i] < delta_score:
delta_score = score[i]
delta_pos = pos[i].copy()
iter_best.append(alpha_score)
# Step 3. Sort the results
x = [i for i in range(iter + 1)]
plt.figure()
plt.plot(x, iter_best, linewidth=2, color='blue')
plt.ticklabel_format(scilimits=(0, 0))
plt.xlabel('Iteration number')
plt.ylabel('So-far best value')
plt.show()
return {'best solution': alpha_pos, 'best score': alpha_score}
if __name__ == '__main__':
pop = 10
lb = [0, 0, 10, 10]
ub = [100, 100, 100, 100]
iter = 1000
print(main(pop, lb, ub, iter))