遗传算法解决旅行商问题TSP纯代码(MATLAB)

这个代码是在我上一篇博客遗传算法代码基础上改的,所以注释不一定对上

%遗传算法(求旅行商问题)
clc;clear;
%初始参数
N=300;%初始的随机种群个数
G=200;%总的迭代次数,
r=0.0000000000000000001;%防止pc,pm那里分母为0;
Pc1=0.9;Pc2=0.6;%确定交叉的可能性即确定每一组xy被交叉改变的可能性
Pm1=0.1;Pm2=0.01;%确定变异的可能性即确实每一组xy被变异改变的可能性
n=20;%城市个数
city=struct([]);
for i =1:n
    city(i).x=floor(1+100*rand());
    city(i).y=floor(1+100*rand());%生成城市坐标。实际问题应该输入题目给的坐标
end
E(N,n)=0;
for i =1:N
E(i,:)=randperm(n);
end%随机生成100组x,y自变量,一行为一组
time(1,G)=0;F(1,N)=0;Best_Fit(1,G)=0;temp_E(N,n)=0;%内存预分配
for k =1:G
    time(k)=k;
    for i=1:N
        F(i)=len(city,E(i,:));%计算每一组的目标函数值保存到F
    end
    Best_F=max(F);%找到其中最大的,题目要求是求目标函数极大值
    [now_F,index_F]=sort(F);%升序排序,now_F为排序后的,index_F一一对应原位置
    Best_xy=E(index_F(N),:);%升序排的,所以最后一个(100)为最大值,找到这个最大值是哪一组xy
    Best_Fit(k)=Best_F;%记录这一次迭代的最大目标函数值
    %%复制,带遗传算法中复制规定的公式
    F_sum=sum(F);
    P_num=N*now_F/F_sum;%复制公式
    copynum=floor(P_num);%取整,确定这100组中每一组是否复制,复制多少次,续下
    %这里你会发现让目标函数值越大的xy组,被复制的次数越多(因为本题是求极大值)
    k=1;
    for i =1:N
        for j=1:copynum(i)
            temp_E(k,:)=E(index_F(i),:);%进行"复制"后的新的x,y自变量
            k=k+1;
        end
    end
    for i=k:N
        temp_E(i,:)=Best_xy;%把E后面几组还没有被复制替换的这些,均替换成最优的那组xy
    end
    %%复制过程完成,接下来是交叉
    for i =1:N
        rand_point=round((n-1)*rand()+1);%随机选定一个开始交叉的位置,这里E一行有20列,可选的交叉位置有20个
        rand_xy=round((N-1)*rand()+1);%随机选定E的一行即随机选定一组xy作为交叉替换的数
        temp_Pc=rand;
        f_pc=max(len(city,temp_E(i,:)),len(city,temp_E(rand_xy,:)));
        if (max(F)-mean(F))/(mean(F)-min(F)+r)<1
        Pc=0.8*(max(F)-mean(F))/(mean(F)-min(F)+r);
        else
        Pc=Pc1-(Pc1-Pc2)*(f_pc-min(F))/(max(F)-min(F));%改进的IAGA算法让Pc自行调整
        end
        if Pc>temp_Pc
            for j=rand_point:n
                tmpp1=temp_E(i,j);
                tmpp2=temp_E(rand_xy,j);
                temp_E(i,j)=tmpp2;%若rand_point为10,为第10开始到第20个数都交叉替换成rand_xy10到20对应的值
                temp_E(rand_xy,j)=tmpp1;
            end
            T1=tabulate(temp_E(i,:));
            T2=tabulate(temp_E(rand_xy,:));
            w1=find(T1(:,2)==2);
            w2=find(T2(:,2)==2);
            if ~isempty(w2)
            for kkk=1:length(w1)
            aa1=find(temp_E(i,:)==w1(kkk));
            bb1=find(temp_E(rand_xy,:)==w2(kkk));
            temp_E(i,aa1(1))=w2(kkk);
            temp_E(rand_xy,bb1(1))=w1(kkk);% 防止元素相同
            end
            end
            
        end
    end
    temp_E(N,:)=Best_xy;%把最后一行还是固定为之前的最优xy组
    %%交叉结果,变异开始
    for i=1:N
        for j=1:n
            temp_Pm=rand;
            f_pie=len(city,temp_E(i,:));
            if (max(F)-mean(F))/(mean(F)-min(F)+r)<1
            Pm=0.1*(max(F)-mean(F))/(mean(F)-min(F)+r);
            else
            Pm=Pm1-(Pm1-Pm2)*(f_pie-min(F))/(max(F)-min(F));%改进的IAGA算法让Pm自行调整
            end
            if Pm>temp_Pm
                randd=floor(1+n*rand());
                tem=temp_E(i,j);
                temp_E(i,j)=temp_E(i,randd);
                temp_E(i,randd)=tem;%变异每一组xy内部进行,按变异概率改变二进制xy的值
            end
        end
    end
    E=temp_E;%把经历了一轮复制、交叉、变异的100组xy给E,以便继续对其进行新一轮复制、交叉、变异
end
 plot(time,Best_Fit);%查看目标函数最大值收敛情况
figure;GAplot(city,Best_xy);

用到的function函数有

len.m

function len=len(city,x)
len=0;
n=length(x);
%计算路线总长度,即目标函数,
for i =1:n-1
    len=len+sqrt((city(x(i)).x-city(x(i+1)).x)^2+(city(x(i)).y-city(x(i+1)).y)^2);
end
len=len+sqrt((city(x(n)).x-city(x(1)).x)^2+(city(x(n)).y-city(x(1)).y)^2);
len=2000-len;
if len<0
    len=0;
end
end

GAplot.m

function GAplot(city,x)
hold on 
n=length(x);
% 可视化路线,将行走路线画出来
for i =1:n-1
    plot(city(x(i)).x,city(x(i)).y,"r*");%画出每个城市的点位(散点图)
    line([city(x(i)).x city(x(i+1)).x],[city(x(i)).y city(x(i+1)).y]);%用线将每个城市相连接
end
plot(city(x(n)).x,city(x(n)).y,"r*");
line([city(x(n)).x city(x(1)).x],[city(x(n)).y city(x(1)).y]);%%for循环无法将城市起点与终点连接,所以这里另外连接
hold off
end

运行结果:

城市坐标是随机生成的,所以每一次运行结果不一样

 

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PlatinumA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值