Skip to content

Commit c40f404

Browse files
committed
Add GSA(A Gravitational Search Algorithm);
After the comparision between this code and GSA code(https://github.com/ravexina/GSA/blob/master/GSA.py), I found that the avg is 0.05 vs. 0.04 and the std is 0.04 vs 0.05 after 100 computation.
1 parent fe019c6 commit c40f404

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

GSA.py

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# !usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
# Time : 2022/10/19 20:32
4+
# @Author : LucXiong
5+
# @Project : Model
6+
# @File : GSA.py
7+
8+
'''
9+
Ref:https://github.com/ravexina/GSA/blob/master/GSA.py
10+
Ref:Rashedi E., Nezamabadi-Pour H., Saryazdi S. GSA: A Gravitational Search Algorithm[J]. Information Sciences, 2009, 179(13): 2232-48.
11+
'''
12+
13+
import numpy as np
14+
import matplotlib.pyplot as plt
15+
import math
16+
import test_function
17+
18+
class GSA():
19+
def __init__(self, func, n_dim=None, pop=40, max_iter=150, lb=-1e5, ub=1e5, alpha=0.1, G=0.9):
20+
self.func = func
21+
self.alpha = alpha
22+
self.G = G
23+
self.pop = pop # number of particles
24+
self.n_dim = n_dim # dimension of particles, which is the number of variables of func
25+
self.max_iter = max_iter # max iter
26+
27+
self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim)
28+
assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True'
29+
assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound'
30+
31+
self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim))
32+
v_high = (self.ub - self.lb) # 速度设置为区间长度的一半
33+
self.V = np.random.uniform(low=-v_high, high=v_high, size=(self.pop, self.n_dim)) # speed of particles
34+
self.Y = [self.func(self.X[i]) for i in range(self.pop)] # y = f(x) for all particles
35+
self.q = [1 for i in range(self.pop)]
36+
self.M = [1 for i in range(self.pop)]
37+
self.f = [[0 for j in range(self.n_dim)] for i in range(self.pop)]
38+
self.a = [[0 for j in range(self.n_dim)] for i in range(self.pop)]
39+
40+
41+
self.pbest_x = self.X.copy() # personal best location of every particle in history
42+
self.pbest_y = [np.inf for i in range(self.pop)] # best image of every particle in history
43+
self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles
44+
self.gbest_y = np.inf # global best y for all particles
45+
self.gbest_y_hist = [] # gbest_y of every iteration
46+
self.update_gbest()
47+
48+
def cal_q_M(self):
49+
best = np.min(self.Y)
50+
worst = np.max(self.Y)
51+
self.q = (self.Y - worst) / best - worst
52+
self.M = self.q / sum(self.q)
53+
54+
def cal_f(self):
55+
for i in range(self.pop):
56+
f = None
57+
for j in range(self.pop):
58+
if j != i:
59+
dividend = float(self.M[i] * self.M[j])
60+
temp = self.X[i] - self.X[j]
61+
sum_temp = [k**2 for k in temp]
62+
divisor = math.sqrt(sum(sum_temp)) + np.finfo('float').eps
63+
if f is None:
64+
f = self.G * (dividend / divisor) * (self.X[j] - self.X[i])
65+
else:
66+
f = f + self.G * (dividend / divisor) * (self.X[j] - self.X[i])
67+
68+
self.f[i] = np.random.uniform(0, 1) * f
69+
70+
def update_gbest(self):
71+
idx_min = self.Y.index(min(self.Y))
72+
if self.gbest_y > self.Y[idx_min]:
73+
self.gbest_x = self.X[idx_min, :].copy()
74+
self.gbest_y = self.Y[idx_min]
75+
76+
def run(self):
77+
for iteration in range(self.max_iter):
78+
79+
self.Y = [self.func(self.X[i]) for i in range(self.pop)]
80+
self.cal_q_M()
81+
self.G = self.G * np.e ** (- self.alpha * (iteration / self.max_iter))
82+
self.cal_f()
83+
self.a = [self.f[i]/self.M[i] for i in range(self.pop)]
84+
self.V = (np.random.uniform(0, 1) * self.V) + self.a
85+
self.update_gbest()
86+
self.X = self.X + self.V
87+
self.gbest_y_hist.append(self.gbest_y)
88+
# print(iteration, self.gbest_x, self.gbest_y)
89+
self.best_x, self.best_y = self.gbest_x, self.gbest_y
90+
return self.best_x, self.best_y
91+
92+
93+
def demo_func(args):
94+
95+
x, y = args[0], args[1]
96+
a = 1
97+
b = 100
98+
return (a - x) ** 2 + b * (y - x ** 2) ** 2
99+
100+
101+
if __name__ == '__main__':
102+
n_dim = 2
103+
lb = [0 for i in range(n_dim)]
104+
ub = [1 for i in range(n_dim)]
105+
# demo_func = test_function.fu2
106+
pop_size = 20
107+
max_iter = 100
108+
res = []
109+
for i in range(100):
110+
pso = GSA(func=demo_func, n_dim=n_dim, pop=pop_size, max_iter=max_iter, lb=lb, ub=ub)
111+
best_x, bext_y = pso.run()
112+
print(f'{i}: {demo_func(pso.gbest_x)}\t{pso.gbest_x}')
113+
res.append(bext_y)
114+
print(sum(res)/len(res))
115+
print(np.std(res))
116+
# plt.plot(pso.gbest_y_hist)
117+
#
118+
# plt.show()

0 commit comments

Comments
 (0)