粒子群算法
- 推荐看b站的这个视频:粒子群算法入门
粒子群算法流程图
仿真实例
f ( x ) = ∑ i = 1 n x i 2 ( − 20 ⩽ x i ⩽ 20 ) \large f(x)=\sum_{i=1}^{n} x_{i}^{2}\left(-20 \leqslant x_{i} \leqslant 20\right) f(x)=i=1∑nxi2(−20⩽xi⩽20)
Python代码
import numpy as np
from numpy import random
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rcParams['font.family'] = 'Kaiti'
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
class PSO:
def __init__(self,N,D,T,E,c1,c2,w,Xmax,Xmin,Vmax,Vmin):
'''
:param N: 种群规模
:param D: 解维度
:param T: 迭代次数
:param E: 解的精度
:param c1: 学习因子1
:param c2: 学习因子2
:param w: 惯性权重
:param Xmax: 解上限
:param Xmin: 解下限
:param Vmax: 速度上限
:param Vmin: 速度下限
'''
self.n = N
self.d = D
self.t = T
self.e = E
self.c1 = c1
self.c2 = c2
self.w = w
self.xmax = Xmax
self.xmin = Xmin
self.vmax = Vmax
self.vmin = Vmin
def func(self, x):
return sum(x ** 2)
def boundary(self,u): # boundary边界
# 边界条件处理
a = sum(u[u<self.xmin])# 下限
b = sum(u[u>self.xmax]) #上限
k = a + b
while k > 0:
if a > 0:
u[u < self.xmin] = random.rand()*(self.xmax-self.xmin)+self.xmin
elif b > 0:
u[u > self.xmax] = random.rand()*(self.xmax-self.xmin)+self.xmin
a = sum(u[u < self.xmin]) # 下限
b = sum(u[u > self.xmax]) # 上限
k = a + b
return u
def pso(self):
# 初始化种群
x = random.rand(self.n,self.d)*(self.xmax-self.xmin)+self.xmin
# 为每一个粒子极其方向分配速度
v = random.rand(self.n,self.d)*(self.vmax-self.vmin)+self.vmin
# 初始化个体最优位置、最优适应度
p = x.copy() # 初始化的解x认为是每个个体所在最优位置
pbest = self.func(x.T)
# 初始化全局最后位置、最优适应度
gbest = min(pbest)
gk = np.where(pbest==min(pbest))[0][0]
g = p[gk]
# 按照公式迭代寻优
gb = [] # 用来记录每一次迭代的最优适应度值
plt.ion()
fig = plt.figure(figsize=(10,5.5),dpi=100)
for i in range(self.t):
# 更新个体最优位置、最优值
y = self.func(x.T)
yk = np.where(y<pbest)[0]
if sum(yk)>0:
p[yk] = x[yk]
pbest[yk] = y[yk]
# 更新全局最优位置、最优值
if min(pbest)<gbest:
gk = np.where(pbest == min(pbest))[0][0]
g = p[gk]
gbest = min(pbest)
# 更新位置和速度
r1 = random.rand(self.n,self.d)
r2 = random.rand(self.n,self.d)
v = self.w*v + self.c1*r1*(p-x) + self.c2*r2*(g-x)
x = x + v
# 边界条件处理
x = self.boundary(x)
v = self.boundary(v)
# 保存最优值
gb.append(gbest)
# if gbest<self.e:
# break
# 输出
self.draw(gb,i)
plt.show()
def draw(self,y,n):
plt.rc('legend', fontsize=16)
CK = ['b', 'y', 'g', 'r', 'k', 'c', 'm']
k = np.random.randint(0, len(CK), 1)
plt.clf()
plt.plot(y, '%s:d' % CK[k.item()], markerfacecolor='red',
markersize=5, linewidth=1.8, label='粒子群算法求函数极小值')
plt.xlabel('迭代次数', fontproperties='Kaiti', fontsize=14) # 坐标轴标签设置
plt.ylabel('适应度变化曲线', fontproperties='Kaiti', fontsize=14)
plt.title(r'粒子群算法解$Min:f(x)=\sum_{i=1}^{n}x_{i}^{2}\left(-20\leqslant x_{i}\leqslant 20\right)$(%d)'%(n+1),
fontproperties='Kaiti', fontsize=14)
plt.annotate('最小值为:%.6f'%y[-1],xy=(len(y)-1,y[-1]),xytext=(len(y)-0.09*(n+1),y[-1]+100),
fontproperties='Kaiti',
fontsize=12, arrowprops=dict(facecolor='green', shrink=1.5, width=1.5, headwidth=5)
)
plt.grid(True)
plt.legend()
plt.pause(0.05)
plt.ioff()
# plt.show()
pso = PSO(100,10,150,1e-6,1.5,1.5,0.8,20,-20,10,-10)
pso.pso()
实验结果分析
适应度变化过程: