#麻雀算法
此篇是我自己学习优化算法的一些代码,为了方便自己以后使用
初始化阶段
def __init__(self, func, n_dim=None, pop_size=20, max_iter=50, lb=-512, ub=512, verbose=False):
self.func = func
self.n_dim = n_dim # dimension of particles, which is the number of variables of func
self.pop = pop_size # number of particles
P_percent = 0.2 # # 生产者的人口规模占总人口规模的20%
D_percent = 0.1 # 预警者的人口规模占总人口规模的10%
self.pNum = round(self.pop * P_percent) # 生产者的人口规模占总人口规模的20%
self.warn = round(self.pop * D_percent) # 预警者的人口规模占总人口规模的10%
self.max_iter = max_iter # max iter
self.verbose = verbose # print the result of each iter or not
self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim)
assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True'
assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound'
self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim))
self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles
self.pbest_x = self.X.copy() # personal best location of every particle in history
self.pbest_y = [np.inf for i in range(self.pop)] # best image of every particle in history
self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles
self.gbest_y = np.inf # global best y for all particles
self.gbest_y_hist = [] # gbest_y of every iteration
self.update_pbest()
self.update_gbest()
#
# record verbose values
self.record_mode = False
self.record_value = {'X': [], 'V': [], 'Y': []}
self.best_x, self.best_y = self.gbest_x, self.gbest_y # history reasons, will be deprecated
self.idx_max = 0
self.x_max = self.X[self.idx_max, :]
self.y_max = self.Y[self.idx_max]
更新发现者
def update_finder(self):
r2 = np.random.rand(1) # 预警值
self.idx = sorted(enumerate(self.Y), key=lambda x: x[1])
self.idx = [self.idx[i][0] for i in range(len(self.idx))]
# 这一部位为发现者(探索者)的位置更新
if r2 < 0.8: # 预警值较小,说明没有捕食者出现
for i in range(self.pNum):
r1 = np.random.rand(1)
self.X[self.idx[i], :] = self.X[self.idx[i], :] * np.exp(-(i) / (r1 * self.max_iter)) # 对自变量做一个随机变换
self.X = np.clip(self.X, self.lb, self.ub) # 对超过边界的变量进行去除
# X[idx[i], :] = Bounds(X[idx[i], :], lb, ub) # 对超过边界的变量进行去除
# fit[sortIndex[0, i], 0] = func(X[sortIndex[0, i], :]) # 算新的适应度值
elif r2 >= 0.8: # 预警值较大,说明有捕食者出现威胁到了种群的安全,需要去其它地方觅食
for i in range(self.pNum):
Q = np.random.rand(1) # 也可以替换成 np.random.normal(loc=0, scale=1.0, size=1)
self.X[self.idx[i], :] = self.X[self.idx[i], :] + Q * np.ones((1, self.n_dim)) # Q是服从正态分布的随机数。L表示一个1×d的矩阵
self.X = np.clip(self.X, self.lb, self.ub) # 对超过边界的变量进行去除
# X[idx[i], :] = Bounds(X[sortIndex[0, i], :], lb, ub)
# fit[sortIndex[0, i], 0] = func(X[sortIndex[0, i], :])
self.cal_y(0, self.pNum)
更新追随者的位置
def update_follower(self):
# 这一部位为加入者(追随者)的位置更新
for ii in range(self.pop - self.pNum):
i = ii + self.pNum
A = np.floor(np.random.rand(1, self.n_dim) * 2) * 2 - 1
best_idx = self.Y[0:self.pNum].index(min(self.Y[0:self.pNum]))
bestXX = self.X[best_idx, :]
if i > self.pop/2:
Q = np.random.rand(1)
self.X[self.idx[i],:] = Q*np.exp((self.x_max-self.X[self.idx[i],:])/np.square(i))
else:
self.X[self.idx[i],:] = bestXX+np.dot(np.abs(self.X[self.idx[i],:]-bestXX),1/(A.T*np.dot(A,A.T)))*np.ones((1, self.n_dim))
self.X = np.clip(self.X, self.lb, self.ub) # 对超过边界的变量进行去除
self.cal_y(self.pNum, self.pop)