粒子群优化算法(PSO)Python实现

参考:
http://yarpiz.com/440/ytea101-particle-swarm-optimization-pso-in-matlab-video-tutorial
https://blog.csdn.net/wang454592297/article/details/80367158#comments

感谢大佬们的代码,希望自己早日出坑,本来想直接MOPSO结果跪了。。

粒子群优化算法(Particle Swarm Optimization,PSO)

属于进化算法的一种,是通过模拟鸟群捕食行为设计的。

设想这样一个场景:一群鸟在随机搜索食物。在这个区域里只有一块食物。所有的鸟都不知道食物在那里。但是他们知道当前的位置离食物还有多远。那么找到食物的最优策略是什么呢。最简单有效的就是搜寻目前离食物最近的鸟的周围区域。

所有的粒子具有以下两个属性:速度、位置。
在每一次迭代中,粒子通过跟踪两个"极值"来更新自己。第一个就是粒子本身所找到的最优解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=wvi+c1rand1(pbestixi)+c2rand2(gbestixi)

位置公式:
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()

运行结果

粒子群优化算法(PSO)Python实现_第1张图片
粒子群优化算法(PSO)Python实现_第2张图片

你可能感兴趣的:(进化计算)