matlab新手快速上手4(人工蜂群算法)

        本文用经典人工蜂群算法框架模板,对matlab新手友好,快速上手看懂matlab代码,快速应用实践,源代码在文末给出。

基本原理:

        人工蜂群算法(Artificial Bee Colony Algorithm,ABC)是一种启发式算法,受到蜜蜂觅食行为的启发而提出的一种优化算法。它模拟了蜜蜂在寻找花朵采集花粉的过程中的行为,通过不断地调整蜜蜂的搜索策略来寻找最优解。

        人工蜂群算法的基本思想是将候选解空间中的点看作花朵,并将搜索过程看作蜜蜂在不同花朵之间搜索的过程。在算法的执行过程中,蜜蜂分为三类:雇佣蜜蜂、观察蜜蜂和侦查蜜蜂。

  1. 雇佣蜜蜂:雇佣蜜蜂负责在当前位置附近的解空间中搜索,并评估候选解的质量。它们根据花粉量的多少(即解的适应度)来选择候选解,并将信息传递给其他蜜蜂。

  2. 观察蜜蜂:观察蜜蜂根据雇佣蜜蜂的信息进行选择,并尝试在当前位置附近进行搜索。它们通过观察雇佣蜜蜂找到的解来确定自己的搜索方向。

  3. 侦查蜜蜂:侦查蜜蜂负责在整个解空间中进行全局搜索,以寻找可能的新解。它们以一定的概率选择随机位置进行探索,并在搜索过程中更新最优解。

        通过不断地雇佣、观察和侦查过程,人工蜂群算法能够在解空间中搜索到较优解。该算法具有较好的全局搜索能力和较快的收敛速度,适用于解决各种复杂的优化问题,如函数优化、参数优化等。

本文编程思想:

本编程将观察蜂于侦察蜂统一,称为侦察蜂,将雇佣蜜蜂称为采蜜蜂

编程思想为:采蜜蜂进行随机采蜜,侦察蜂根据采蜜蜂的适应度大小进行跟随,适应度越高证明蜜源越好,越接近正确解,侦察蜂在采蜜蜂周围进行随机侦察,侦察到更好的蜜源后(也就是适应度越好的个体),那么将采蜜蜂更新到此位置,进而吸引更多的侦察蜂侦察,实现快速收敛。

开始编程:

参数与子函数定义:

%---------------------------------- 程序正文 -------------------------------
function ABC
%---------------------------------- 参数设置 -------------------------------
NP1=20;                            %种群规模
NP2=20;                            %种群规模
D=10;                              %变量个数
MinX=-D^2;                         %范围下限
MaxX=D^2;                          %范围上限
Limit=50;                          %次数阈值
Search=zeros(1,NP1);               %采蜜搜次
Error=1.0;                         %限定精度
Max_N=1000;                        %限定代数
flagc=[0,Max_N];                   %收敛标志
%---------------------- 粒子位置初始化 ----------------------
for i=1:1:D
    X(:,i)=MinX+(MaxX-MinX)*rand(NP1+NP2,1);
end
%----------------------- 计算函数值 -------------------------
F=fun(X);
%---------------------------- 子函数1:目标函数 ----------------------------
function F=fun(X)
[M,N]=size(X);
for i=1:1:M
    for j=1:1:N
        x(j)=X(i,j);
    end
    F(i)=N*(N+4)*(N-1)/6+sum((x-1).^2)-sum(x(2:N).*x(1:N-1));
end
%----------------------- 建采蜜蜂群 -------------------------
[Bestf,Indexf]=sort(F,2);
for i=1:1:NP1
    X1(i,:)=X(Indexf(i),:);
    F1(i)=F(Indexf(i));
end
CX1=X1;CF1=F1;

 参数定义:

NP1和NP2分别为采蜜蜂和侦察蜂。D为变量个数

X矩阵为D列,NP1+NP2行的矩阵,也就是40行,10列的矩阵。每一行代表一个蜜蜂个体,元素范围为(-100,100)

子函数定义

fun(x)为子函数,子函数中,M,N分别代表为X的行数和列数,这里的子函数也是目标函数,具体的数学函数如下,最终算法目标也就是求这个数学函数值小于1的解。N \left( N + 4 \right) \left( \frac{N - 1}{6} \right) + \sum_{i=1}^{N} \left( x_i - 1 \right)^2-\sum_{i=1}^{N-1} x_i x_{i+1}

建立采蜜蜂群:

        如上述代码所示,sort(F,2)表示按F的第二维度进行排序,也就是按列排序,也就是对F的每一行进行排序,由于F只有1行,那么也可以去掉这个参数,F一行的第i个参数也就是第i个蜜蜂的适应度,这里的排序就相当于按照每个蜜蜂的适应度进行排序,然后根据for循环挑选出NP1个蜜蜂作为采蜜蜂,CX1,CF1表示复制一份值。

开始主循环:

%--------------------- 程序主循环开始 ----------------------
for gen=1:1:Max_N
    time(gen)=gen;
    %----------------- 作采蜜蜂群搜索 ----------------------
    for i=1:1:NP1
        flag1=ceil(rand*NP1);
        while(flag1==i)
            flag1=ceil(rand*NP1);
        end
        flag2=ceil(rand*D);
        X1(i,flag2)=X1(i,flag2)+rands(1)*(X1(i,flag2)-X1(flag1,flag2));
    end
    %----------------- 计算采蜜函数值 ----------------------
    F1=fun(X1);
    %----------------- 采蜜蜂贪婪搜索 ----------------------
    for i=1:1:NP1
        if F1(i)>=CF1(i)
            Search(i)=Search(i)+1;
            X1(i,:)=CX1(i,:);
            F1(i)=CF1(i);
        else
            Search(i)=0;
        end
    end
    %----------------- 跟踪蜂选择概率 ----------------------
    temp=(1./(1+F1))/sum(1./(1+F1));
    %P=cumsum((1./(1+F1))/sum(1./(1+F1)));
    for i=1:1:NP1
        P(i)=sum(temp(1:i));
    end
    %----------------- 跟踪蜂蜜源搜索 ----------------------
    for i=1:1:NP2
        %------------- 跟踪蜂选择蜜源 ----------------------
        rnd=rand;
        for flag=1:1:NP1
            if rnd<P(flag)
                Genzong(i)=flag;
                break;
            end
        end
        X2(i,:)=X1(flag,:);
        %------------- 跟踪蜂搜索蜜源 ----------------------
        flag1=ceil(rand*NP1);
        while(flag1==flag)
            flag1=ceil(rand*NP1);
        end
        flag2=ceil(rand*D);
        X2(i,flag2)=X1(flag,flag2)+rands(1)*(X1(flag,flag2)-X1(flag1,flag2));
    end
    %----------------- 计算跟踪函数值 ----------------------
    F2=fun(X2);
    %----------------- 跟踪蜂蜜源计数 ----------------------
    for i=1:1:NP2
        if F2(i)>=F1(Genzong(i))
            Search(Genzong(i))=Search(Genzong(i))+1;
        else
            Search(Genzong(i))=0;
            X1(Genzong(i),:)=X2(i,:);
            F1(Genzong(i))=F2(i);
        end
    end
    %----------------- 检验采蜜蜂蜜源 ----------------------
    for i=1:1:NP1
        if Search(i)>Limit
            Search(i)=0;
            if i~=Indexf(1)
                X1(i,:)=MinX+(MaxX-MinX)*rand(1,D);
                F1=fun(X1);
            end
        end
    end
    %----------------- 迭代更新 ---------------------------
    CF1=F1;CX1=X1;
    %----------------- 求最优解 ---------------------------
    [Bestf,Indexf]=sort(F1,2);     %对NP1个函数值排序
    gBestf=Bestf(1);
    gX=X1(Indexf(1),:);
    %----------------------------- 记录结果 --------------------------------
    result(gen)=gBestf;
    if mod(gen,10)==0
        disp(sprintf('代数:%d -------- 结果:%f',gen,gBestf));
        plot(time,result,'r');axis([1,Max_N,0,10000]);
        xlabel('迭代步数');ylabel('优化结果');drawnow;pause(0.1);
    end
    if gBestf<Error break;end
end
%disp(' ');
disp(sprintf('迭代步数:%d -------- 优化结果:%f',gen,gBestf));

外层循环:

最外层循环表示迭代次数,表示进行Max_N次迭代,time记录迭代到第几次,做采蜜蜂群搜索代码中,ceil表示向上取整,表示[1,NP1]范围的随机整数。while循环内表示此整数不能等于当前迭代次数,也就是防止下一段代码中X1的参数未被修改。

F1 = fun(X1)表示计算采蜜蜂群的适应度并存储在F1矩阵中。

采蜜蜂贪婪搜索:

当更新后F1的适应度比之前差,那么把对应的个体记录到search中,并把没更新之前的值赋值给X1和F1。

跟踪蜂选择概率:

这个选择方法是轮盘赌选择,具体原理和流程见主页遗传算法中。这里Genzong数组里记录了每个跟踪蜂跟踪第几个采蜜蜂,X2矩阵中存储跟踪蜂选择的采蜜蜂个体。蜜源越大也就是适应度越好,跟踪蜂越多。

跟踪蜂搜索蜜源:

flag1表示[1,NP1]的随机值,与上面的采蜜蜂搜索蜜源相似,做随机搜索,随机改变10个变量中的一个,循环结束使用F2进行跟踪蜂适应度计算。

跟踪蜜源计数:

这个for循环中,遍历每个跟踪蜂的适应度,如果跟踪蜂的适应度比它跟踪的采蜜蜂的适应度差,那么将对应采蜜蜂的search中的值+1,也就是search越大,这个采蜜蜂的适应度越好,如果跟踪蜂的适应度好,将跟踪蜂的值赋值给它跟踪的采蜜蜂,并更新采蜜蜂的对应适应度的值。

检验采蜜蜂蜜源:

这个代码是防止陷入局部最优解的过程,当search超过limit时,表示此采蜜蜂周围没有比他更好的蜜源了,将search设置为0,如果这个采蜜蜂还不是全局最优解,那么将这个采蜜蜂重新分配一个随机蜜源,这就是避免陷入局部最优的过程,如果这个蜜蜂是全局最优解,那么不分配随机蜜源,继续让跟踪蜂寻找。

迭代更新:

迭代更新的CF1记录上一次的采蜜蜂的适应度,CX1记录上一次采蜜蜂的值,计算最优解将适应度排序,寻找最佳的采蜜蜂。

源代码:

%---------------------------------- 程序说明 -------------------------------

%                           该程序实现了基本蜂群算法

%---------------------------------- 程序正文 -------------------------------
function ABC
%---------------------------------- 参数设置 -------------------------------
NP1=20;                            %种群规模
NP2=20;                            %种群规模
D=10;                              %变量个数
MinX=-D^2;                         %范围下限
MaxX=D^2;                          %范围上限
Limit=50;                          %次数阈值
Search=zeros(1,NP1);               %采蜜搜次
Error=1.0;                         %限定精度
Max_N=1000;                        %限定代数
flagc=[0,Max_N];                   %收敛标志
%---------------------- 粒子位置初始化 ----------------------
for i=1:1:D
    X(:,i)=MinX+(MaxX-MinX)*rand(NP1+NP2,1);
end
%X=MinX+(MaxX-MinX)*rand(NP1+NP2,D);
disp(X);
%----------------------- 计算函数值 -------------------------
F=fun(X);
%----------------------- 建采蜜蜂群 -------------------------
[Bestf,Indexf]=sort(F,2);
for i=1:1:NP1
    X1(i,:)=X(Indexf(i),:);
    F1(i)=F(Indexf(i));
end
CX1=X1;CF1=F1;
%--------------------- 程序主循环开始 ----------------------
for gen=1:1:Max_N
    time(gen)=gen;
    %----------------- 作采蜜蜂群搜索 ----------------------
    for i=1:1:NP1
        flag1=ceil(rand*NP1);
        while(flag1==i)
            flag1=ceil(rand*NP1);
        end
        flag2=ceil(rand*D);
        X1(i,flag2)=X1(i,flag2)+rands(1)*(X1(i,flag2)-X1(flag1,flag2));
    end
    %----------------- 计算采蜜函数值 ----------------------
    F1=fun(X1);
    %----------------- 采蜜蜂贪婪搜索 ----------------------
    for i=1:1:NP1
        if F1(i)>=CF1(i)
            Search(i)=Search(i)+1;
            X1(i,:)=CX1(i,:);
            F1(i)=CF1(i);
        else
            Search(i)=0;
        end
    end
    %----------------- 跟踪蜂选择概率 ----------------------
    temp=(1./(2+F1))/sum(1./(2+F1));
    %P=cumsum((1./(1+F1))/sum(1./(1+F1)));
    for i=1:1:NP1
        P(i)=sum(temp(1:i));
    end
    %----------------- 跟踪蜂蜜源搜索 ----------------------
    for i=1:1:NP2
        %------------- 跟踪蜂选择蜜源 ----------------------
        rnd=rand;
        for flag=1:1:NP1
            if rnd<P(flag)
                Genzong(i)=flag;
                break;
            end
        end
        X2(i,:)=X1(flag,:);
        %------------- 跟踪蜂搜索蜜源 ----------------------
        flag1=ceil(rand*NP1);
        while(flag1==flag)
            flag1=ceil(rand*NP1);
        end
        flag2=ceil(rand*D);
        X2(i,flag2)=X1(flag,flag2)+rands(1)*(X1(flag,flag2)-X1(flag1,flag2));
    end
    %----------------- 计算跟踪函数值 ----------------------
    F2=fun(X2);
    %----------------- 跟踪蜂蜜源计数 ----------------------
    for i=1:1:NP2
        if F2(i)>=F1(Genzong(i))
            Search(Genzong(i))=Search(Genzong(i))+1;
        else
            Search(Genzong(i))=0;
            X1(Genzong(i),:)=X2(i,:);
            F1(Genzong(i))=F2(i);
        end
    end
    %----------------- 检验采蜜蜂蜜源 ----------------------
    for i=1:1:NP1
        if Search(i)>Limit
            Search(i)=0;
            if i~=Indexf(1)
                X1(i,:)=MinX+(MaxX-MinX)*rand(1,D);
                disp("reSearch");
                F1=fun(X1);
            end
        end
    end
    %----------------- 迭代更新 ---------------------------
    CF1=F1;CX1=X1;
    %----------------- 求最优解 ---------------------------
    [Bestf,Indexf]=sort(F1,2);     %对NP1个函数值排序
    gBestf=Bestf(1);
    gX=X1(Indexf(1),:);
    %----------------------------- 记录结果 --------------------------------
    result(gen)=gBestf;
    if mod(gen,10)==0
        disp(sprintf('代数:%d -------- 结果:%f',gen,gBestf));
        plot(time,result,'r');axis([1,Max_N,0,10000]);
        xlabel('迭代步数');ylabel('优化结果');drawnow;pause(0.1);
    end
    if gBestf<Error break;end
end
%disp(' ');
disp(sprintf('迭代步数:%d -------- 优化结果:%f',gen,gBestf));
disp(X1(Indexf(1),:));
%---------------------------- 子函数1:目标函数 ----------------------------
function F=fun(X)
[M,N]=size(X);
for i=1:1:M
    for j=1:1:N
        x(j)=X(i,j);
    end
    F(i)=N*(N+4)*(N-1)/6+sum((x-1).^2)-sum(x(2:N).*x(1:N-1));
end

  • 18
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值