粒子群算法原理及Matlab实现(PSO — Particle Swarm Optimization)

1 前言

       在计算机科学中,粒子群优化(PSO)是一种计算方法,可以通过迭代来改进候选方案的优化问题。它通过粒子的位置和速度根据数学公式得到一组候选解决方案,并在搜索空间中移动这些粒子来解决问题。每个粒子的运动不仅受到它局部最佳位置的影响,而且全局最优解也会引导这些粒子到最佳位置。

       PSO是由Kennedy和Eberhart共同提出,最初用于模拟社会行为,作为鸟群或鱼群中有机体运动的形式化表示。自然界中各种生物体均具有一定的群体行为,Kennedy和Eberhart的主要研究方向之一是探索自然界生物的群体行为,从而在计算机上构建其群体模型。PSO是一种元启发式算法,因为它很少或没有对被优化的问题作出假设,并且能够对非常大候选解决方案空间进行搜索。

2 算法原理

      PSO算法初始化为一群随机的粒子,然后通过多次迭代找到最优解。每一次的迭代过程中,粒子通过本身所找到的最优解(被成为个体极值)和整个种群目前找到的最优解(被称为全局极值)来更新自己。也可以使用粒子本身的邻居(被称为局部极值)的极值来更新自己。

      假设在一个N维的目标搜索空间中,有M个粒子组成一个种群,其中第i个粒子表示为一个N维的向量,Pi表示第i个粒子的位置。

                                                                     

第i个粒子移动速度是一个N维的向量。

                                    

第i个粒子目前搜索到的最优位置称谓个体极值。

                                    

整个粒子群搜索到的全局最优位置。

                                    

使用个体极值和全局最优值结合下面的公式来更新粒子的速度和位置。

其中,C1、C2是加速常数,或者成为学习率,W是惯性常量,R1、R2是[0,1]范围内的随机数。

算法流程图如下所示。

·

      3 实验和结果

     选择Ackley函数作为适应度函数。函数基本形式如下。

函数的图像如下。

PSO程序如下。

% POS主程序
c1=1;%学习率
c2=1;%学习率
Dimension=20;
Size=30;
Tmax=600;
V_max=200;%粒子最大速度

F_n=3;%测试函数名

Fun_Ub=800;%函数上下界
Fun_Lb=-800;
Position=zeros(Dimension,Size);%粒子位置
Velocity=zeros(Dimension,Size);%粒子速度
Vmax(1:Dimension)=V_max;%粒子速度上下界
Vmin(1:Dimension)=-V_max;
Xmax(1:Dimension)=Fun_Ub;%粒子位置上下界,即函数自变量的上下界
Xmin(1:Dimension)=Fun_Lb;
[Position,Velocity]=Initial_position_velocity(Dimension,Size,Xmax,Xmin,Vmax,Vmin);

Ebest_Pos=Position;%粒子的历史最优位置,初始值为粒子的起始位置,存储每个粒子的历史最优位置
Gbest_position=zeros(Dimension,1);%全局最优的那个粒子所在位置,初始值认为是第1个粒子

for j=1:Size
    Pos=Position(:,j);%取第j列,即第j个粒子的位置
    fz(j)=Fitness_Function(Pos,F_n,Dimension);%计算第j个粒子的适应值
end
[Gbest_Fitness,I]=min(fz);%求出所有适应值中最小的那个适应值,并获得该粒子的位置
Gbest_position=Position(:,I);%取最小适应值的那个粒子的位置,即I列

for itrtn=1:Tmax
    time(itrtn)=itrtn;
    
    Weight=1;
    r1=rand(1);
    r2=rand(1);
    for i=1:Size
        Velocity(:,i)=Weight*Velocity(:,i)+c1*r1*(Ebest_Pos(:,i)-Position(:,i))+c2*r2*(Gbest_position-Position(:,i));
    end
    %限制速度边界
    for i=1:Size
        for row=1:Dimension
            if Velocity(row,i)>Vmax(row)
                Veloctity(row,i)=Vmax(row);
            elseif Velocity(row,i)<Vmin(row)
                Veloctity(row,i)=Vmin(row);
            else
            end
        end
    end
    
    Position=Position+Velocity;
    
    %限制位置边界
    for i=1:Size
        for row=1:Dimension
            if Position(row,i)>Xmax(row)
                Position(row,i)=Xmax(row);
            elseif Position(row,i)<Xmin(row)
                Position(row,i)=Xmin(row);
            else
            end
        end
    end
    
    for j=1:Size
        P_position=Position(:,j)';%取一个粒子的位置
        fitness_p(j)=Fitness_Function(P_position,F_n,Dimension);
        if fitness_p(j)< fz(j) %粒子的适应值比运动之前的适应值要好,更新原来的适应值
            Ebest_Pos(:,j)=Position(:,j);
            fz(j)=fitness_p(j);
        end
        if fitness_p(j)<Gbest_Fitness
            Gbest_Fitness=fitness_p(j);
        end
    end
    [Gbest_Fitness_new,I]=min(fz);% 更新后的所有粒子的适应值,取最小的那个,并求出其编号
    Best_fitness(itrtn)=Gbest_Fitness_new; % 记录每一代的最好适应值
    Gbest_position=Ebest_Pos(:,I);% 最好适应值对应的个体所在位置
end
plot(time,Best_fitness);
xlabel('迭代的次数');ylabel('适应度值F');

% ------------------------------------------------------------------------------%
% 适应度函数,本程序使用的是第三个适应度函数Ackley
function Fitness = Fitness_Function(Pos,F_n,Dimension)
 switch F_n
    case 1
        Func_Sphere=Pos(:)'*Pos(:);
        Fitness=Func_Sphere;
    % Griewank函数
    case 2
        res1 = Pos(:)'*Pos(:)/4000;
        res2 = 1;
        for row = 1:Dimension
            res2 = res2 * cos(Pos(row) / sqrt(row));
        end
        Func_Griewank = res1 - res2 + 1;
        Fitness = Func_Griewank;
     case 3
        %Ackley 函数  
        %输入x,给出相应的y值,在x=(0,0,…,0) 处有全局极小点0,为得到最大值,返回值取相反数  
        %编制人:  
        %编制日期:
        [row,col]=size(Pos');   
        Fitness = -20*exp(-0.2*sqrt((1/col)*(sum(Pos'.^2))))-exp((1/col)*sum(cos(2*pi.*Pos')))+exp(1)+20;  
        Fitness = -Fitness;  
        
end

%--------------------------------------------------------------%
% 初始化函数
function [Position,Velocity] = Initial_position_velocity(Dimension,Size,Xmax,Xmin,Vmax,Vmin)
  for i=1:Dimension
      % 产生合理范围内的随机位置,rand(1,Size)用于产生一行Size个随机数
      Position(i,:)=Xmin(i)+(Xmax(i)-Xmin(i))*rand(1,Size);
      Velocity(i,:)=Vmin(i)+(Vmax(i)-Vmin(i))*rand(1,Size);
  end
end

测试结果。

猜你喜欢

转载自blog.csdn.net/tan_handsome/article/details/81087570