PSO
import matplotlib.pyplot as plt
import numpy as np
import random as rd
np.set_printoptions(precision=3,suppress=True)class PSO():"""用于求解最小值"""def __init__(self,pop_scale,dim,maxV,pop_bnd,maxiter):self.pop_scale = pop_scale#种群规模self.dim = dim#X解的维度self.maxiter = maxiter#种群迭代次数self.popx = np.zeros((self.pop_scale,self.dim))#种群位置存储self.popv = np.zeros((self.pop_scale, self.dim))#种群速度存储self.maxV = maxV#速度最大变化值self.pop_bnd = pop_bnd#X的约束范围self.c1 = 2#更新速度所用的参数c1self.c2 = 2#更新速度所用的参数c2self.w = 0.4#0.4/0.9 值不同收敛速度和局部搜索能力不同self.p_history_values = np.zeros((1,self.pop_scale)).reshape(-1)#记录每一个粒子的y变化的最优值self.p_best = np.zeros((self.pop_scale,dim))#记录每一个粒子的y变化的最优位置self.g_history_values = np.zeros((1, 1)).reshape(-1) # 记录全局最优值self.g_best = np.zeros((self.pop_scale, dim)) # 记录全局最优位置self.g_values = []#记录每次迭代的结果self.all_pop = []def y_values(self,X):#目标函数a = np.power(X,2)b = np.ones((1,a.shape[1]))###sum(X^2)return np.dot(a,b.T)
#'——————————————————————————————————初始化————————————————————————————————————————'def inti_pop(self):#初始化种群"""经数据验证初始化初始化程序无误"""self.popx = np.random.uniform(self.pop_bnd[0],self.pop_bnd[1],size=(self.pop_scale,self.dim))#初始化种群位置self.popv = np.random.uniform(0,self.maxV,size=(self.pop_scale,self.dim))#初始化种群速度self.p_history_values = self.y_values(self.popx)#记录种群个体最优值p_yself.p_best = self.popx#记录种群个体位置最优,初次迭代所以等于popxself.g_best = self.p_best[self.p_history_values.tolist().index(self.p_history_values.max())]#全局最优位置self.g_history_values = self.y_values(np.array([self.g_best]))#全局最优位置的函数值g_ydef plot(self):#绘制收敛曲线plt.rcParams['font.sans-serif'] = 'simhei'plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号plt.style.use('ggplot')plt.title("收敛曲线")plt.plot(np.array(self.g_values).reshape(-1),color='blue')plt.ylabel('Value')plt.xlabel('Iteration')plt.savefig('./收敛曲线.png')plt.show()bird = np.array(self.all_pop)fig, [ax1,ax2 ]= plt.subplots(nrows=2, ncols=1)#, figsize=(20, 8)ax1.plot(bird[:, :, 0])ax1.set_ylabel('x-Value')ax1.set_xlabel('x-Iteration')ax2.plot(bird[:, :, 1])ax2.set_ylabel('y-Value')ax2.set_xlabel('y-Iteration')plt.tight_layout(h_pad=2,)plt.savefig('./xy收敛曲线.png')plt.show()def bound(self):#防止X超出约束边界for i in range(self.popx.shape[0]):for j in range(self.popx.shape[1]):if self.popx[i][j] > self.pop_bnd[0]:self.popx[i][j] = self.pop_bnd[0]if self.popx[i][j] < self.pop_bnd[1]:self.popx[i][j] = self.pop_bnd[1]
#'——————————————————————————————————开始迭代计算————————————————————————————————————'def pso(self):for cycle in range(self.maxiter):# 更新速度 ,开始下一种群迭代,产生新种群self.popv = self.w*self.popv + \self.c1*rd.random()*(self.p_best) +\self.c2*rd.random()*(self.g_best*np.ones_like(self.popx)-self.popx)self.popx = self.popx +self.popv#粒子群新的位置##缺少边界约束,# self.bound()value = self.y_values(self.popx) # 新一代粒子群的y值for i in range(self.pop_scale):#更新b_best 和g_bestif self.p_history_values[i]>value[i]:self.p_history_values[i]=value[i]#更新历史最优yself.p_best[i] = self.popx[i]#更新粒子历史最优位置if self.p_history_values[i]<self.g_history_values:self.g_history_values = self.p_history_values[i] #更新全局最优gself.g_best = self.p_best[i]#更新全局最优位置self.g_values.append(self.y_values(np.array([self.g_best])))#记录每次迭代的计算结果值self.all_pop.append(self.popx)self.plot()#收敛曲线if __name__=='__main__':opt = PSO(pop_scale=20,dim=100,maxV=2,pop_bnd=(-2,2),maxiter=100)opt.inti_pop()opt.pso()print(f'最优值f(x):\n {opt.g_history_values}\n')print(f'最优解 x:\n{opt.p_best[-1]}')

对于5个维度以下的解 还算还可以,维度太高,求解不是和精确,
可能与参数选取有关

Example2:
求解:np.arctan(X)/(np.sin(X)+1.1) 可以看出 收敛值在pi/2 *10 左右 约为15.70
import matplotlib.pyplot as plt
import numpy as np
import random as rd
# np.set_printoptions(precision=3,suppress=True)class PSO():"""用于求解最小值"""def __init__(self,pop_scale,dim,maxV,pop_bnd,maxiter):self.pop_scale = pop_scale#种群规模self.dim = dim#X解的维度self.maxiter = maxiter#种群迭代次数self.popx = np.zeros((self.pop_scale,self.dim))#种群位置存储self.popv = np.zeros((self.pop_scale, self.dim))#种群速度存储self.maxV = maxV#速度最大变化值self.pop_bnd = pop_bnd#X的约束范围self.c1 = 2#更新速度所用的参数c1self.c2 = 2#更新速度所用的参数c2self.w = 0.4#0.4/0.9 值不同收敛速度和局部搜索能力不同self.p_history_values = np.zeros((1,self.pop_scale)).reshape(-1)#记录每一个粒子的y变化的最优值self.p_best = np.zeros((self.pop_scale,dim))#记录每一个粒子的y变化的最优位置self.g_history_values = np.zeros((1, 1)).reshape(-1) # 记录全局最优值self.g_best = np.zeros((self.pop_scale, dim)) # 记录全局最优位置self.g_values = []#记录每次迭代的结果self.all_pop = []def y_values(self,X):#目标函数# a = np.power(X,1)*(X-2)# b = np.ones((1,a.shape[1]))# return np.dot(a,b.T)return np.arctan(X)/(np.sin(X)+1.1)
#'——————————————————————————————————初始化————————————————————————————————————————'def inti_pop(self):#初始化种群"""经数据验证初始化初始化程序无误"""self.popx = np.random.uniform(self.pop_bnd[0],self.pop_bnd[1],size=(self.pop_scale,self.dim))#初始化种群位置self.popv = np.random.uniform(0,self.maxV,size=(self.pop_scale,self.dim))#初始化种群速度self.p_history_values = self.y_values(self.popx)#记录种群个体最优值p_yself.p_best = self.popx#记录种群个体位置最优,初次迭代所以等于popxself.g_best = self.p_best[self.p_history_values.tolist().index(self.p_history_values.max())]#全局最优位置self.g_history_values = self.y_values(np.array([self.g_best]))#全局最优位置的函数值g_ydef plot(self):#绘制收敛曲线plt.rcParams['font.sans-serif'] = 'simhei'plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号plt.style.use('ggplot')plt.title("收敛曲线")plt.plot(np.array(self.g_values).reshape(-1),color='blue')plt.ylabel('Value')plt.xlabel('Iteration')plt.savefig('./收敛曲线.png')plt.show()# bird = np.array(self.all_pop)# fig, [ax1,ax2 ]= plt.subplots(nrows=2, ncols=1)#, figsize=(20, 8)# ax1.plot(bird[:, :, 0])# ax1.set_ylabel('x-Value')# ax1.set_xlabel('x-Iteration')# ax2.plot(bird[:, :, 1])# ax2.set_ylabel('y-Value')# ax2.set_xlabel('y-Iteration')# plt.tight_layout(h_pad=2,)# plt.savefig('./xy收敛曲线.png')# plt.show()def bound(self):#防止X超出约束边界for i in range(self.popx.shape[0]):for j in range(self.popx.shape[1]):if self.popx[i][j] > self.pop_bnd[0]:self.popx[i][j] = self.pop_bnd[0]if self.popx[i][j] < self.pop_bnd[1]:self.popx[i][j] = self.pop_bnd[1]
#'——————————————————————————————————开始迭代计算————————————————————————————————————'def pso(self):gg_value = self.g_history_valuesfor cycle in range(self.maxiter):# 更新速度 ,开始下一种群迭代,产生新种群self.popv = self.w*self.popv + \self.c1*rd.random()*(self.p_best) +\self.c2*rd.random()*(self.g_best*np.ones_like(self.popx)-self.popx)self.popx = self.popx +self.popv#粒子群新的位置##缺少边界约束,# self.bound()value = self.y_values(self.popx) # 新一代粒子群的y值for i in range(self.pop_scale):#更新b_best 和g_bestif self.p_history_values[i]>value[i]:self.p_history_values[i]=value[i]#更新历史最优yself.p_best[i] = self.popx[i]#更新粒子历史最优位置if self.p_history_values[i]<self.g_history_values:self.g_history_values = self.p_history_values[i] #更新全局最优gself.g_best = self.p_best[i]#更新全局最优位置self.g_values.append(self.y_values(np.array([self.g_best])))#记录每次迭代的计算结果值# self.all_pop.append(self.popx)self.plot()#收敛曲线if __name__=='__main__':opt = PSO(pop_scale=10,dim=1,maxV=2,pop_bnd=(-9,9),maxiter=4000)opt.inti_pop()opt.pso()print(f'最优值f(x):\n {opt.g_history_values}\n')print(f'最优解 x:\n{opt.p_best[-1]}')print(np.pi/2)

200次以内就已经收敛了,
但是
对于解集中的任意一个Xi来说并没有收敛,这是一个问题
存在问题:
- 维度过高时,计算不是很准确,存在1-5范围内的误差
- 改进:限制后期的速度变化。参考模拟退火T逐渐下降
- X的边界约束限制问题。这里没有约束限制,约束方法需要进一步确定















