参考:
http://yarpiz.com/440/ytea101-particle-swarm-optimization-pso-in-matlab-video-tutorial
https://blog.csdn.net/wang454592297/article/details/80367158#comments
感谢大佬们的代码,希望自己早日出坑,本来想直接MOPSO结果跪了。。
属于进化算法的一种,是通过模拟鸟群捕食行为设计的。
设想这样一个场景:一群鸟在随机搜索食物。在这个区域里只有一块食物。所有的鸟都不知道食物在那里。但是他们知道当前的位置离食物还有多远。那么找到食物的最优策略是什么呢。最简单有效的就是搜寻目前离食物最近的鸟的周围区域。
所有的粒子具有以下两个属性:速度、位置。
在每一次迭代中,粒子通过跟踪两个"极值"来更新自己。第一个就是粒子本身所找到的最优解pbest。另一个极值是整个种群目前找到的最优解,即全局极值gbest。
速度公式:
v i + 1 = w ∗ v i + c 1 ∗ r a n d 1 ∗ ( p b e s t i − x i ) + c 2 ∗ r a n d 2 ∗ ( g b e s t i − x i ) v_{i+1}=w \ast v_{i} +c_{1} \ast rand_{1} \ast (pbest_{i}-x_{i})+c_{2} \ast rand_{2} \ast (gbest_{i}-x_{i}) vi+1=w∗vi+c1∗rand1∗(pbesti−xi)+c2∗rand2∗(gbesti−xi)
位置公式:
x i = x i + v i + 1 x_{i}=x_{i}+v_{i+1} xi=xi+vi+1
w w w为惯性因子
c 1 c_{1} c1、 c 2 c_{2} c2为学习因子
r a n d 1 rand_{1} rand1、 r a n d 2 rand_{2} rand2为(0,1)之间的随机数
v i v_{i} vi、 x i x_{i} xi表示粒子第i维的速度和位置
p b e s t i pbest_{i} pbesti、 g b e s t i gbest_{i} gbesti表示某个粒子历史最好记录的第i维的值或者可以理解为第i个决策变量or变量,整个种群的最好记录
PS.第二个链接里面有提到惯性衰减系数,没实现;那些参数我也不知道一般应该设多少
class PSO:
def __init__(self,pop,gengeration,x_min,x_max,fitnessFunction,c1=0.1,c2=0.1,w=1):
self.c1=c1
self.c2=c2
self.w=w #惯性因子
#惯性因子衰减系数
self.pop=pop#种群大小
self.x_min=np.array(x_min) #约束
self.x_max=np.array(x_max)
self.generation=generation
self.max_v=(self.x_max-self.x_min)*0.05
self.min_v= -(self.x_max-self.x_min)*0.05
self.fitnessFunction=fitnessFunction
#初始化种群
self.particals=[Partical(self.x_min,self.x_max,self.max_v,self.min_v,self.fitnessFunction) for i in range(self.pop)]
#获得全局最佳的信息
self.gbest=np.zeros(len(x_min))
self.gbestFit=float('Inf')
self.fitness_list=[]#每次的最佳适应值
def init_gbest(self):
for part in self.particals:
if part.getBestFit()<self.gbestFit:
self.gbestFit=part.getBestFit()
self.gbest=part.getPbest
def done(self):
for i in range(self.generation):
for part in self.particals:
part.update(self.w,self.c1,self.c2,self.gbest)
if part.getBestFit()<self.gbestFit:
self.gbestFit=part.getBestFit()
self.gbest=part.getPbest()
self.fitness_list.append(self.gbest)
return self.fitness_list,self.gbest
import numpy as np
class Partical:
#进行粒子的初始化
def __init__(self,x_min,x_max,max_v,min_v,fitness):
self.dim=len(x_min) #获得变量数
self.max_v=max_v
self.min_v=min_v
self.x_min=x_min
self.x_max=x_max
'''为了防止不同的变量约束不同,传进来的都是数组'''
#self.pos=np.random.uniform(x_min,x_max,dim)
self.pos=np.zeros(self.dim)
self.pbest=np.zeros(self.dim)
self.initPos(x_min,x_max)
self._v=np.zeros(self.dim)
self.initV(min_v,max_v)#初始化速度
self.fitness=fitness
self.bestFitness=fitness(self.pos)
def _updateFit(self):
if self.fitness(self.pos)<self.bestFitness:
self.bestFitness=self.fitness(self.pos)
self.pbest=self.pos
def _updatePos(self):
self.pos=self.pos+self._v
for i in range(self.dim):
self.pos[i]=min(self.pos[i],self.x_max[i])
self.pos[i]=max(self.pos[i],self.x_min[i])
def _updateV(self,w,c1,c2,gbest):
'''这里进行的都是数组的运算'''
self._v=w*self._v+c1*np.random.random()*(self.pbest-self.pos)+c2*np.random.random()*(gbest-self.pos)
for i in range(self.dim):
self._v[i]=min(self._v[i],self.max_v[i])
self._v[i]=max(self._v[i],self.min_v[i])
def initPos(self,x_min,x_max):
for i in range(self.dim):
self.pos[i]=np.random.uniform(x_min[i],x_max[i])
self.pbest[i]=self.pos[i]
def initV(self,min_v,max_v):
for i in range(self.dim):
self._v[i]=np.random.uniform(min_v[i],max_v[i])
def getPbest(self):
return self.pbest
def getBestFit(self):
return self.bestFitness
def update(self,w,c1,c2,gbest):
self._updateV(w,c1,c2,gbest)
self._updatePos()
self._updateFit()
pop=300
generation=500
x_min=[-10,-10]
x_max=[10,10]
pso=PSO(pop,generation,x_min,x_max,fit_fun)
fit_list,best_pos=pso.done()