模拟退火代码超通俗解释(MATLAB)

主程序(旅行商问题)

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

运行结果:

 

你可能感兴趣的:(matlab,算法,模拟退火算法)