主程序(旅行商问题)
clc;clear;
%模拟退火 旅行商问题
n=20;%城市个数
temp=100*n;%初始温度
G=100;%实验次数(随机搜索)
%随机初始化城市坐标(实际问题时,应该输入实际的每个城市坐标)
city=struct([]);
for i =1:n
city(i).x=floor(1+100*rand());
city(i).y=floor(1+100*rand());
end
l=1;len(l)=computer_tour(city,n);%计算当前路线总长度(即目标函数)
%因为此程序核心是不断改变各城市在city结构组(数组)的位置(行数)
%city中是一行对应一个城市,20个城市共20行,初始状态是城市随机排下来
%类似于一直改变20个城市排序,寻找最佳的排序,让总路线最短
netplot(city,n);%画出当前的旅行路线
while temp>0.001 %停止迭代的温度即当温度低于0.001时,停止运行
for i=1:G %降温之前多次实验
len1=computer_tour(city,n);%计算当前路线总长度
tmp_city=perturb_tour(city,n);%随机置换city中两个城市坐标
len2=computer_tour(tmp_city,n);%计算被随机置换后的路线总长度
d_len=len2-len1;%新的长度减原来长度,它们的差值
if d_len<0 %小于0说明len2小于len1,即新的总长度更短
city=tmp_city;%因为新的城市排序更优,将新路线替代旧路线
else %即大于等于0,即新路线没有旧路线长度短,没有好于旧路线
if exp(-d_len/temp)>rand() %模拟退火算法的核心,一定概率防止陷入局部最优解
%概率选择是否接受新的路线
%当d_len不变,temp温度越低,执行此步骤的概率也就越低,越不太可能接受新路线
%当temp不变,d_len越大,执行此步骤的概率越低,越不太可能接受新路线
city=tmp_city;
end
end
end
l=l+1;%统计while循环迭代次数
len(l)=computer_tour(city,n);%存储每一次迭代的路线总长度
temp=temp*0.99;% while循环每迭代一次,降温一次
end
figure;
netplot(city,n);%画出最终路线
% 因为城市坐标是随机生成的,所以每次运行画出来的图的路线总长度都是不一样的
figure;
plot(len);%画出路线总长度变化趋势
%因为随着while迭代,temp温度会越来越多,“概率选择是否接受新的路线”的可能性也会变得极低,
% 所以不太可能突变了,而是慢慢趋于平稳
辅助function程序
computer_tour.m
function len=computer_tour(city,n)
len=0;
%计算路线总长度,即目标函数,
for i =1:n-1
len=len+sqrt((city(i).x-city(i+1).x)^2+(city(i).y-city(i+1).y)^2);
end
len=len+sqrt((city(n).x-city(1).x)^2+(city(n).y-city(1).y)^2);
%因为此程序核心是不断改变各城市在city结构组(数组)的位置(行数)
%city中是一行对应一个城市,20个城市共20行,初始状态是城市随机排下来
%类似于一直改变20个城市排序,寻找最佳的排序,让总路线最短
end
netplot.m
function netplot(city,n)
hold on
% 可视化路线,将行走路线画出来
for i =1:n-1
plot(city(i).x,city(i).y,"r*");%画出每个城市的点位(散点图)
line([city(i).x city(i+1).x],[city(i).y city(i+1).y]);%用线将每个城市相连接
end
plot(city(n).x,city(n).y,"r*");
line([city(n).x city(1).x],[city(n).y city(1).y]);%%for循环无法将城市起点与终点连接,所以这里另外连接
hold off
end
perturb_tour.m
function city=perturb_tour(city,n)
%随机置换两个不同城市的坐标,p1和p2用来随机选2个不同城市用来置换
p1=floor(1+n*rand());%产生的随机数范围是1~n,为整数,因为共n个城市
p2=floor(1+n*rand());
while p1==p2
p1=floor(1+n*rand());
p2=floor(1+n*rand());%防止无效置换,确保打乱了城市在原city中的顺序
end
tmp=city(p1);%提前储存p1城市坐标,因为到下一行原p1城市坐标会被改变
city(p1)=city(p2);%让p1城市坐标换成p2城市坐标
city(p2)=tmp;%让p2城市坐标换成p1城市坐标
end
运行结果: