编程语言
首页 > 编程语言> > 求解旅行商问题的离散人工萤火虫算法-matlab代码

求解旅行商问题的离散人工萤火虫算法-matlab代码

作者:互联网

一、萤火虫算法

        旅行商问题(TSP)是运筹学以及最优化理论等领域中的一个经典问题,它广泛应用于各行各业,如电路板钻孔、货物配送路线和车间调度安排等问题均可转化为 TSP,因此 TSP 的求解成为国内外学者研究的点.对于规模比较小的 TSP,可以应用分支定界法、贪婪法和割平面法等精确算法求解,但对于规模较大的 TSP,应用以上精确算法求解时计算量太大,在目前的条件下很难实现,而智能优化算法的出现为其求解开辟了新的途径.

        萤火虫算法(Firefly Algorithm)是一种启发式算法,灵感来自于萤火虫闪烁的行为。萤火虫的闪光,其主要目的是作为一个信号系统,以吸引其他的萤火虫。剑桥大学的Xin-She Yang教授提出了萤火虫算法,其假设为: 萤火虫不分性别,这样一个萤火虫将会吸引到所有其他的萤火虫;吸引力与它们的亮度成正比,对于任何两个萤火虫,不那么明亮的萤火虫被吸引,因此移动到更亮的一个,然而,亮度又随着其距离的增加而减少;如果没有比一个给定的萤火虫更亮的萤火虫,它会随机移动。亮度应与目标函数联系起来。萤火虫算法是以自然为灵感的启发式优化算法。

        自然界中的萤火虫会发出荧光信号,从生物学角度,其作用有时是为了吸引异性关注,求得交配机会,繁衍后代;有时是为了捕食;有时是因处于危险境地而将其作为警戒信号.人工萤火虫算法中仅考虑萤火虫利用发出荧光信号在一定范围内吸引同伴, 最终使大多数萤火虫聚集在一个或者多个位置上,即实现位置优化.萤火虫吸引同伴主要取决于荧光亮度和吸引度.其中,荧光亮度取决于自身所在位置的目标值,目标值越佳,亮度越高;吸引度和亮度紧密相关,越亮的萤火虫也拥有越高的吸引度,可以在一定范围内吸引亮度比其弱的萤火虫向自己移动 . 另外,在人工萤火虫算法中,考虑到萤火中发光的物理特性,亮度和吸引度都与萤火虫之间的距离成反比,即随着距离的增大,荧光亮度和吸引度逐渐减小.萤火虫在移动过程中主要遵循如下原则:

       ①萤火虫移动方向由荧光亮度决定,总是向比自身荧光亮度高的萤火虫移动;

       ②萤火虫移动距离由吸引度决定 . 文中对萤火虫荧光亮度和吸引度进行如下定义。

        

        

        

二、TSP离散问题的求解

        求解连续变量的优化问题时,萤火虫间的空间距离可采用欧式距离进行计算;当求解 TSP 时,解向量为离散变量,其空间距离不能按欧式距离公式进行计算。定义萤火虫间的空间距离为

        

       其中基本交换序的定义为

        

        在求解连续变量的优化问题时,萤火虫移动距离可根据吸引度进行计算,但当求解 TSP 时,萤火虫的移动距离不应是连续变量,位置更新为

        

        基于变邻域搜索(VNS)算法的思想,定义了离散变量的扰动机制.在搜索过程中采用多种邻域结构形式进行搜索,系统地改变其邻域,从而拓展搜索范围,增强算法跳出局部最优的能力.

        

三、应用离散萤火虫算法求解 TSP 的步骤

        

四、代码

clc
clear
close all
%% 输入城市坐标 初始化参数
X=[114 50 99 30 60 26 29 7 53 40 102 3 32 12 100];
Y=[228 70 146 171 150 262 220 29 246 275  175 48 52 227 99];
city=[X',Y'];
N=size(X,2);
n=50;%萤火虫数目
gamma=0.1;%光强吸收系数
T_max=100;%最大迭代次数
K=50;%混沌迭代次数
ew=0.2;%选取精英比例
%% 初始化种群
for i=1:n
    popus.order(i,:)=randperm(N);%初始每只
    POP=[popus.order(i,:),popus.order(i,1)];%每只萤火虫数值
    dis=0;
    for j=1:N%距离求和的倒数(距离越短越好)
        dis=dis+sqrt((X(POP(j+1))-X(POP(j)))^2+(Y(POP(j+1))-Y(POP(j)))^2);
    end
    popus.P(i)=1/dis;                           %计算目标函数
end
Mp=mean(popus.P(:));%平均种群距离和的倒数
L(1)=max(popus.P);%记录函数最优值
popus.max_Y=max(popus.P)./popus.P;%荧光强度j=2 k=2
popus.pg=max(popus.P);%最优目标值,作为比较标准,更新迭代
PO=find(popus.P==max(popus.P));%最优种群位置
popus.Popus=popus.order(PO,:);%取出最优种群
%% 算法迭代过程
for im=1:T_max
    sprintf('迭代次数%d',im)
    popus.YY=popus.max_Y;
    r=ones(n,n)*0;
    AA=ones(n,n)*0;
    beta=ones(n,n)*0;
    fd=0;
    oe=(1:N);%初始预存矩阵
    for i=1:n%不同种群
        for j=1:n%种群中的数值
            if i~=j%判断每个种群与另一个种群之间的空间距离(A 为两只萤火虫解向量基本交换序中的交换子个数)
                S=[];
                x=popus.order(i,:);
                y=popus.order(j,:);
                LL=nchoosek(oe,2);
                A=0;
                for k=1:size(LL,1)
                    ec=LL(k,:);
                    if sum(abs(x(LL(k,:))==y([ec(2),ec(1)])))==2%先判断两个位置是否相等,相等就直接交换
                        x(LL(k,:))=y(LL(k,:));
                        A=A+1;
                        S=[S;LL(k,:)];
                    end
                end
                for k=1:N
                    if x(k)~=y(k)%不相等的话就将x中对应y位置的城市移过来,然后将原位置处城市移过去
                        xt=find(x==y(k));
                        x(x==y(k))=x(k);
                        x(k)=y(k);
                        A=A+1;
                        S=[S;[k,xt]];
                        for kk=1:size(LL,1)
                            ec=LL(k,:);
                            if sum(abs(x(LL(kk,:))==y([ec(2),ec(1)])))==2%判断两个位置是否相等,相等就直接交换
                                x(LL(kk,:))=y(LL(kk,:));
                                A=A+1;
                                S=[S;LL(kk,:)];
                            end
                        end
                    end
                end
                SS{i,j}=S;%种群的基本交换序
                AA(i,j)=A;%A 为两只萤火虫解向量基本交换序中的交换子个数
                r(i,j)=A/N;
            end
        end
    end
    choose=ones(1,n);
    for i=1:n
        x=popus.order(i,:);
        for j=1:n
            popus.YY(j)=popus.max_Y(i)*exp(-gamma*r(i,j));%萤火虫荧光强度
        end
        p=popus.YY/sum(popus.YY);%最大荧光强度
        P=p;
        for m=1:size(p,2)%基于轮盘赌选择移向荧光亮度更高的其他个体,确定移动方向
            P(m)=sum(p(1:m));
        end
        num=rand(1);
        for m=1:size(P,2)
            if num<P(m)
                choose(i)=m;
                break
            end
        end
    end
    for i=1:n
        for j=1:n
            if i~=j
                beta(i,j)=randi([0,AA(i,j)]);%确定移动距离
            end
        end
    end
    for i=1:n%根据移动距离和移动方向,对各个萤火虫进行更新
        x=popus.order(i,:);
        Choose=choose(i);
        Sx=SS{i,Choose};
        Num1=beta(i,Choose);
        OD=zeros(1,size(Sx,1));
        OD(randperm(size(Sx,1),Num1))=1;
        Sx(OD==0,:)=[];
        for j=1:size(Sx,1)
            aa=Sx(j,:);
            x([aa(1),aa(2)])=x([aa(2),aa(1)]);
        end
        popus.order(i,:)=x;
    end  
    for i=1:n
        POP=[popus.order(i,:),popus.order(i,1)];
        dis=0;
        for j=1:N
            dis=dis+sqrt((X(POP(j+1))-X(POP(j)))^2+(Y(POP(j+1))-Y(POP(j)))^2);
        end
        popus.P(i)=1/dis;                           %计算目标函数
    end
    
    d_order=zeros(n,1);
    f_t=sort(popus.P,'ascend');%将适应度按升序排列
    for k=1:n
        x=find(popus.P==f_t(k));%升序排列的个体序号
        d_order(k)=x(1);
    end
    NN=ew*n;%选取部分精英进行混沌优化迭代
    N_order=d_order(n-NN+1:n);
    for i=1:NN
        x=popus.order(N_order(i),:);
        xs=x;
        xr=x;
        xs=[xs,xs(1)];
        dis=0;
        for k=1:N
            dis=dis+sqrt((X(xs(k+1))-X(xs(k)))^2+(Y(xs(k+1))-Y(xs(k)))^2);
        end  
        Dis=1/dis;
        for j=1:K
            x=xr;
            numm=randi([1,N],1,2);
            x(numm)=x([numm(2),numm(1)]);
            xe=x;
            x=[x,x(1)];
            dis=0;
            for k=1:N
                dis=dis+sqrt((X(x(k+1))-X(x(k)))^2+(Y(x(k+1))-Y(x(k)))^2);
            end
            Diss=1/dis;
            if Diss>Dis
                Dis=Diss;
                xr=xe;
            end
        end
        popus.order(N_order(i),:)=xr;
    end
    
    M_order=d_order(1:NN);%将目标值最差的部分种群重新随机赋值
    for i=1:NN
        popus.order(M_order(i),:)=randperm(N);
    end
    
    for i=1:n
        POP=[popus.order(i,:),popus.order(i,1)];
        dis=0;
        for j=1:N
            dis=dis+sqrt((X(POP(j+1))-X(POP(j)))^2+(Y(POP(j+1))-Y(POP(j)))^2);
        end
        popus.P(i)=1/dis;                           %计算目标函数
    end
    Mpe=mean(popus.P(:));
    
    if max(popus.P)>popus.pg
        popus.pg=max(popus.P);
        popus.max_Y=max(popus.P)./popus.P;%荧光强度
        PO=find(popus.P==max(popus.P));
        popus.Popus=popus.order(PO(1),:);
        L(im+1)=max(popus.P);
        Mp(im+1)=Mpe;
    else
        L(im+1)=L(im);
        Mp(im+1)=Mpe;
    end
    close all
    plot(X,Y,'.k','LineWidth',5);%标明城市
    hold on
    ex=[popus.Popus,popus.Popus(1)];
    plot(X(ex),Y(ex),'r');%标明城市
    pause(0.1)
end
figure(2)
L2=L;Mp2=Mp;
plot((1:size(L2,2)),1./L2,'r',(1:size(L2,2)),1./Mp2,'g');%迭代过程
xlabel('迭代次数')
ylabel('路径长度')
legend('最优路径长度','种群平均路径长度')
 

五、运行结果

 

标签:popus,end,max,萤火虫,离散,matlab,order,dis
来源: https://blog.csdn.net/weixin_41971010/article/details/113738965