PSO粒子群算法

代码整理于《MATLAB优化算法案例分析与应用》-余胜威编著;在此感谢

粒子群算法改进

PSO算法改进研究为两个方面:
1.将各种先进理论引入到PSO算法,研究各种改进和PSO算法;
2.将PSO算法和其他智能优化算法相结合,研究各种混合优化算法,达到取长补短、改善算法某方面性能的效果。
(1)PSO算法的惯性权重模型,通过引入惯性权重,提高算法的全局搜索能力。
(2)带邻域操作的PSO模型,克服了PSO模型在优化搜索后期随迭代次数增加搜索结果无明显改变的缺点。
(3)将拉伸技术用于PSO最小化问题的求解,避免了PSO算法易陷于局部最小值的缺点。
(4)用适应度定标的方法对PSO算法进行改进,在算法收敛的前提下能够提高粒子间适应度的差异;在每次迭代中,依据杂交概率选取指定数量的粒子放入一个池中的粒子随机地两两杂交,产生同样数目的孩子粒子,并用孩子粒子代替父母粒子,以保持种群的粒子数目不变。
(5)协同PSO算法,基本思想是用K个相互独立的粒子群分别在D维的目标搜索空间中的不同维度方向上进行搜索。
总结:PSO算法对于求解极值最优问题应用较为广泛,根据约束范围内的所有可能粒子,计算适应度值,通过迭代,最终得到相应的的极值最优解。PSO算法简单,需要调节的参数不多,其次,算法采用实数编码,可直接取目标函数本身作为适应度函数,根据目标函数值进行迭代搜索。且各粒子具有记忆性,算法搜索速度快。

加快PSO算法效率

由于PSO中粒子向自身历史最佳位置和邻域或群体历史最佳位置聚集,形成粒子种群的快速趋同效应,容易出现陷入局部极值、早熟收敛或停止现象。PSO算法主要依赖粒子个数、惯性权重、学习因子以及添加压缩因子等参数。

带惯性权重的PSO算法

常见:线性递减权重、自适应权重和随机权重算法等
1.自适应惯性权重的PSO算法
一般wmax=0.9;wmin=0.6

function[xm,fv] = SAPSO(fitness,N,c1,c2,wmax,wmin,M,D)
%fitness适应度函数;N种群个数;
%c1、c2学习因子;wmax\wmin最大最小惯性权重
%M迭代次数;D种群中个体个数
format long;
%初始化种群的个体
for i=1:N
   for j=1:D
      x(i,j)=randn; %随机初始化位置
      v(i,j)=randn; %随机初始化速度
   end
end
%计算各个粒子的适应度
for i =1;N
    p(i) = fitness(x(i,:));
    y(i,:) = x(i,:);
end
pg = x(N,:); %pg为全局最优
for i = 1:(N-1)
    if  fitness(x(i,:))<fitness(pg) % 注意这里是求最小
        pg = x(i,:);
    end
end
%进入主循环
for t =1:M
    for j = 1:N
        fv(j) = fitness(x(j,:));
    end
    favg = sum(fv)/N;
    fmin = min(fv);
    for i =1:N
        if fv(i) <=favg
            w = wmin+(fv(i)-fmin)*(wmax-wmin)/(favg-fmin);
        else 
            w = wmax;
        end
        v(i,:) = w*v(i,:)+c1*rand*(y(i,:)-x(i,:))+c2*rand*(pg-x(i,:));
        x(i,:) = x(i,:)+v(i,:);
        if fitness(x(i,:))<p(i)
           p(i) = fitness(x(i,:));
           y(i,:) = x(i,:);
        end
        if p(i)<fitness(pg)
           pg = y(i,:);
        end
    end
    pbest(t) = fitness(pg);
end
r=[1:1:100];
plot(r,pbest,'r--');
xlabel('迭代次数')
ylabel('适应度值')
title('改进的PSO算法收敛曲线')
legend('权重自适应PSO算法')
hold on 
xm = pg';
fv = fitness(pg);
end

2.惯性权重线性递减的PSO算法
一般wmax=0.9;wmin=0.4

function[xm,fv] = SAPSO(fitness,N,c1,c2,wmax,wmin,M,D)
%fitness适应度函数;N种群个数;
%c1、c2学习因子;wmax\wmin最大最小惯性权重
%M迭代次数;D种群中个体个数
format long;
%初始化种群的个体
for i=1:N
   for j=1:D
      x(i,j)=randn; % 随机初始化位置
      v(i,j)=randn; % 随机初始化速度
   end
end
%计算各个粒子的适应度
for i =1;N
    p(i) = fitness(x(i,:));
    y(i,:) = x(i,:);
end
pg = x(N,:); %pg为全局最优
for i = 1:(N-1)
    if  fitness(x(i,:))<fitness(pg) % 注意这里是求最小
        pg = x(i,:);
    end
end
%进入主循环
for t =1:M
    for i =1:N
        w = wmax-(t-1)*(wmax-wmin)/(M-1);
        v(i,:) = w*v(i,:)+c1*rand*(y(i,:)-x(i,:))+c2*rand*(pg-x(i,:));
        x(i,:) = x(i,:)+v(i,:);
        if fitness(x(i,:))<p(i)
           p(i) = fitness(x(i,:));
           y(i,:) = x(i,:);
        end
        if p(i)<fitness(pg)
           pg = y(i,:);
        end
    end
    pbest(t) = fitness(pg);
end
r=[1:1:100];
plot(r,pbest,'r--');
xlabel('迭代次数')
ylabel('适应度值')
title('改进的PSO算法收敛曲线')
legend('惯性权重线性递减PSO算法')
hold on 
grid on 
xm = pg';
fv = fitness(pg);
end

线性递减权重的PSO可以调节算法的全局和局部搜索能力,但有两个缺点:
1.迭代初期局部搜索能力较弱,即使初始粒子已接近于全局最优点,也往往错过,迭代后期,因全局搜索能力变弱,易陷入局部最优值;
2.最大迭代次数较难预测,从而将影响算法的调节功能。

3.随机权重策略的PSO算法
一般mean_max=0.8;mean_min=0.5;sigma =0.2

function[xm,fv] = SAPSO(fitness,N,c1,c2,mean_max,mean_min,sigma,M,D)
%fitness适应度函数;N种群个数;
%c1、c2学习因子;wmax\wmin最大最小惯性权重
%M迭代次数;D种群中个体个数
format long;
%初始化种群的个体
for i=1:N
   for j=1:D
      x(i,j)=randn; % 随机初始化位置
      v(i,j)=randn; % 随机初始化速度
   end
end
%计算各个粒子的适应度
for i =1;N
    p(i) = fitness(x(i,:));
    y(i,:) = x(i,:);
end
pg = x(N,:); %pg为全局最优
for i = 1:(N-1)
    if  fitness(x(i,:))<fitness(pg) % 注意这里是求最小
        pg = x(i,:);
    end
end
%进入主循环
for t =1:M
    for i =1:N
        miu = mean_min+(mean_max-mean_min)*rand();
        w = miu+sigma*randn();
        v(i,:) = w*v(i,:)+c1*rand*(y(i,:)-x(i,:))+c2*rand*(pg-x(i,:));
        x(i,:) = x(i,:)+v(i,:);
        if fitness(x(i,:))<p(i)
           p(i) = fitness(x(i,:));
           y(i,:) = x(i,:);
        end
        if p(i)<fitness(pg)
           pg = y(i,:);
        end
    end
    pbest(t) = fitness(pg);
end
r=[1:1:100];
plot(r,pbest,'r--');
xlabel('迭代次数')
ylabel('适应度值')
title('改进的PSO算法收敛曲线')
legend('随机权重PSO算法')
hold on 
grid on 
xm = pg';
fv = fitness(pg);
end

4.增加收缩因子的PSO算法
设置c1较大,会使粒子过多的在局部范围内徘徊,较大的c2,则又会促使粒子过早收敛到局部最小值。压缩因子比惯性权重系数,能更有效的控制约束粒子的飞行速度,同时增强了算法的局部搜索能力。惯性因子一般递减,后期会失去探索新区域的能力,而压缩因子则不存在此不足。

function[xm,fv] = YSPSO(fitness,N,c1,c2,M,D)
%fitness适应度函数;N种群个数;
%c1、c2学习因子;wmax\wmin最大最小惯性权重
%M迭代次数;D种群中个体个数
phi = c1+c2;
if phi <= 4
   disp('c1与c2的和必须大于4!');
   xm = NaN;
   fv = NaN;
   return;
end
format long;
%初始化种群的个体
for i=1:N
   for j=1:D
      x(i,j)=randn; % 随机初始化位置
      v(i,j)=randn; % 随机初始化速度
   end
end
%计算各个粒子的适应度
for i =1;N
    p(i) = fitness(x(i,:));
    y(i,:) = x(i,:);
end
pg = x(N,:); %pg为全局最优
for i = 1:(N-1)
    if  fitness(x(i,:))<fitness(pg) % 注意这里是求最小
        pg = x(i,:);
    end
end
%进入主循环
for t =1:M
    for i =1:N
        ksi = 2/abs(2-phi-sqrt(phi^2-4*phi));
        v(i,:) = w*v(i,:)+c1*rand*(y(i,:)-x(i,:))+c2*rand*(pg-x(i,:));
        v(i,:) = ksi*v(i,:);
        x(i,:) = x(i,:)+v(i,:);
        if fitness(x(i,:))<p(i)
           p(i) = fitness(x(i,:));
           y(i,:) = x(i,:);
        end
        if p(i)<fitness(pg)
           pg = y(i,:);
        end
    end
    pbest(t) = fitness(pg);
end
r=[1:1:100];
plot(r,pbest,'r--');
xlabel('迭代次数')
ylabel('适应度值')
title('改进的PSO算法收敛曲线')
legend('带压缩因子的PSO算法')
hold on 
grid on 
xm = pg';
fv = fitness(pg);

GA-PSO
PSO计算函数极值时,常出现早熟现象,遗传算法对函数采用选择、交叉、变异算子操作,直接以目标函数作为搜索信息,以一种概率的方式来进行,增强了PSO算法的全局寻优能力,加快算法进化速度,提高收敛精度。

%粒子群算法+遗传算法
%PSO常常出现早熟现象,导致求解函数极值存在较大的偏差,
%GA对于函数寻优采用选择、交叉、变异算子操作,直接以目标函数作为搜索信息,
%以一种概率的方式来进行,增强了PSO的全局寻优能力,加快算法的进化速度,提高收敛精度。
clc;
clear
close all
%%参数初始化
lencrom = 3; %字符串长度(个体长度),染色体编码长度
pc = 0.7;% 设置交叉概率,可为定值,也可用表达式
pm = 0.3; %设置变异概率,也可设置为变化的

% PSO的两个参数
c1 = 1.49445;
c2 = 1.49445;

maxgen = 100; % 进化次数
popsize = 30; %种群规模
% 粒子更新速度
vmax = 1;
vmin = -1;
% 种群
popmax = 15;
popmin = 0;

% 变量取值范围
bound = [popmin popmax;popmin popmax;popmin popmax;];% 变量范围
% 优化粒子数目
par_num = 3;

%%产生初始粒子和速度
for i = 1:popsize
    % 随机产生一个种群
    pop(i,:)=3*abs(rands(1,par_num));
    v(i,:) = rands(1,par_num);
    %计算适应度
    fitness(i) = fun2(pop(i,:));%染色体的适应度
end
%找最好的染色体
[bestfitness bestindex] = min(fitness);
zbest = pop(bestindex,:);
gbest = pop;
fitnessgbest = fitness;
fitnesszbest = bestfitness;

%迭代寻优
for i =1:maxgen
    i
    for j =1:popsize
        %速度更新pso
        v(j,:) = v(j,:)+c1*rand*(gbest(j,:)-pop(j,:))+c2*rand*(zbest-pop(j,:));
        v(j,find(v(j,:)>vmax))=vmax;
        v(j,find(v(j,:)<vmin))=vmin;
        % 种群更新PSO
        pop(j,:)=pop(j,:)+0.5*v(j,:);
        pop(j,find(pop(j,:)>popmax))=popmax;
        pop(j,find(pop(j,:)<popmin))=popmin;
        % 交叉操作GA
        GApop = Cross(pc,lenchrom,pop,popsize,bound);
        %变异操作GA
        GApop = Mutation(pm,lenchrom,GApop,popsize,[i maxgen],bound);
        pop = GApop;% GApop-->PSO pop
        %适应度值--》约束条件
        if 1.0*pop(j,1)-1.0*pop(j,2)+1.0*pop(j,3)<=20
           if 3*pop(j,1)+2*pop(j,2)+4*pop(j,3)<=42
               if 3*pop(j,1)+2*pop(j,2)<=30
                    fitness(j) = fun2(pop(j,:));
               end
           end
        end
        % 个体最优更新
        if fitness(j)< fitnessgbest(j)
           gbest(j,:) = pop(j,:);
           fitnessgbest(j) = fitness(j);
        end
        % 群体最优更新
        if fitness(j)< fitnesszbest
           zbest = pop(j,:);
           fitnesszbest = fitness(j);
        end
    end
    yy(i) = fitnesszbest;
end
%结果
zbest
plot(yy,'linewidth',2);
grid on
title(['适应度曲线' ‘终止代数=num2str(maxgen)]);
xlabel('进化代数')ylabel('适应度')
 

遗传算法GA

%%GA
clc
clear all;
close all;
%% 参数初始化
popsize = 100 %种群规模
lenchrom = 3; % 变量字串长度
pc = 0.7;%设置交叉概率
pm = 0.3;% 设置变异概率
maxgen = 100% 进化次数
%种群
popmax = 50;
popmin = 0;
bound = [popmin popmax;popmin popmax; popmin popmax; popmin];%变量范围
%%产生初始粒子和速度
for i = 1:popsize 
    %随机产生一个种群
    GApop(i,:) = Code(lenchrom,bound); %随机产生个体
    %计算适应度
    fitness(i) = fun(GApop(i,:)); %染色体的适应度
end
%找最好的染色体
[bestfitness bestindex] = min(fitness);
zbest = GApop(bestindex,:); %全局最佳
gbest = GApop; % 个体最佳
fitnessgbest = fitness; % 个体最佳适应度值
fitnesszbest = bestfitness; %全局最佳适应度值
%%迭代寻优
for i = 1:maxgen 
      i
      %种群更新 GA
      GApop = Select2(GApop,fitness,popsize);
      %交叉操作GA
      GApop = Cross(pc,lenchrom,GApop,popsize,bound);
      pop = GApop;
      for j =1:popsize
        %适应度值
          if 1.0*pop(j,1)-1.0*pop(j,2)+1.0*pop(j,3)<=20
             if 3*pop(j,1)+2*pop(j,2)+4*pop(j,3)<=42
                if 3*pop(j,1)+2*pop(j,2)<=30
                   fitness(j) = fun2(pop(j,:));
                end
             end
          end
          %个体最优更新
          if fitness(j) < fitnessgbest(j)
              gbest(j,:) = pop(j,:);
              fitnessgbest(j) = fitness(j);
          end
          %群体最优更新
          if fitness(j) < fitnesszbest
              zbest(j,:) = pop(j,:);
              fitnesszbest(j) = fitness(j);
          end  
     end
     yy(i) = fitnesszbest;
end
%结果
zbest
plot(yy,'linewidth',2);
grid on
title(['适应度曲线' ‘终止代数=num2str(maxgen)]);
xlabel('进化代数')ylabel('适应度') 

%% 子函数:染色体编码算法
function ret = Code(lenchrom,bound)
%本函数将变量编码成染色体,用于随机初始化一个种群
%lenchrom:染色体的长度;bound 变量的取值范围;ret 染色体的编码值
flag =0;
while flag == 0
   pick = rand(1,lenchrom);
   ret = bound(:,1)'+(bound(:,2)-bound(:,1))'.*pick; %线性插值
   flag = test(lenchrom,bound,ret);% 检验染色体的可行性
end

%% 选择算子程序
function ret = Select(individuals,fitness,sizepop)
%本函数对每一代种群中的染色体进行选择,以进行后面的交叉和变异
%individuals 种群信息;fitness 适应度;sizepop 种群规模
%opts 选择方法的选择;ret经过选择后的种群
fitness = 1./(fitness);
sumfitness = sum(fitness);
sumf = fitness./sumfitness;
index=[];
for i = 1:sizepop %转sizepop次轮盘
    pick =rand;
    while pick ==0
        pick = rand;
    end
    for j =1:sizepop
        pick = pick -sumf(j);
        if pick <0
           index = [index j];
           break; %寻找落入的区间,此次转轮盘选中了染色体i,注:转的过程中,可能重复选择染色体
             end
     end
end
individuals = individuals(index,:);
fitness = fitness(index);
ret = individuals;

%% 交叉算子
function  ret = Cross(pcross,lenchrom,chrom,sizepop,bound)
%本函数完成交叉操作
%pcorss 交叉概率;lenchrom 染色体的长度;chrom 染色体群
%sizepop 种群规模;ret 交叉后的染色体
for i=1:sizepop
    % 随机选择两个染色体进行交叉
    pick = rand(1,2);
    while prod(pick)==0
         pick = rand(1,2);
    end
    index = ceil(pick.*sizepop);
    %交叉概率决定是否进行交叉
    pick = rand;
    while prod(pick)==0
         pick = rand;
    end
    if  pick >pcross
        continue;
    end
    flag =0;
    while flag ==0
         %随机选择交叉位置
         pick = rand;
         while pick ==0
              pick =rand;
         end
         pos = ceil(pick.*sum(lenchrom));%随机选择进行交叉的位置,即选择第几个变量进行交叉
         pick = rand; %交叉开始
         v1 = chrom(index(1),pos);
         v2 = chrom(index(2),pos);
         chrom(index(1),pos) = pick*v2+(1-pick)*v1;
         chrom(index(2),pos) = pick*v1+(1-pick)*v2; %交叉结束
         flag1 = test(lenchrom,bound,chrom(index(1),:));%检验染色体1的可行性
         flag2 = test(lenchrom,bound,chrom(index(2),:));%检验染色体2的可行性 
         if  flag1*flag2==0
             f;lag =0;
         else flag =1;
         end   %如果两个染色体不是都可行,则重新交叉
     end
end
ret = chrom;

%%检验染色体可行性
function flag = test(lenchrom,bound,code)
%lenchrom 染色体长度;bound 变量的取值范围;code 染色体的编码值
%初始变量
flag = 1;
[n,m] =size(code);
for i =1:n
    if code(i)<bound(i,1) || code(i)>bound(i,2)
       flag =0;
    end
end

%%变异算子程序
function ret Mutation(pmutation,lenchrom,chrom,sizepop,pop,bound)
%本函数完成变异操作
%pcorss 变异概率;lenchrom 染色体长度;chrom 染色体群
%sizepop 种群规模 pop当前种群的进化代数和最大的进化代数信息
%ret 变异后的染色体
for i =1:sizepop
    % 随机选择一个染色体进行变异
    pick = rand;
    while pick ==0
          pick =rand;
    end
    index =ceil(pick*sizepop);
    %变异概率决定该论循环是否进行变异
    pick = rand;
    if pick >pmutation
        continue;
    end
    flag =0;
    while flag ==0
        %变异位置
        pick =rand;
        while pick ==0
             pick =rand;
         end
         pos = ceil(pick*sum(lenchrom));%随机选择了染色体变异的位置,即选择了第pos个变量进行变异
         v= chrom(i,pos);
         v1 = v-bound(pos,1);
         v2 = bound(pos,2)-v;
         pick =rand; %变异开始
         if pick >0.5
            delta = v2*(1-pick^((1-pop(1)/pop(2))^2));
            chrom(i,pos) = v +delta;
         else
            delta = v1*(1-pick^((1-pop(1)/pop(2))^2));
            chrom(i,pos) = v +delta;         
         end %变异结束
         flag = test(lenchrom.bound,chrom(i,:)); %检验染色体的可行性
     end
end
ret = chrom;

注:以上代码均是求最小,如求最大,修改适应度值的不等式运算符号即可。

猜你喜欢

转载自blog.csdn.net/qq_41175681/article/details/130699836