这个代码是在我上一篇博客遗传算法代码基础上改的,所以注释不一定对上
%遗传算法(求旅行商问题)
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
运行结果:
城市坐标是随机生成的,所以每一次运行结果不一样