Matlab利用模拟退火算法求解旅行商(TSP)问题

简介

先引入一个例题:

旅行商问题(TSP)

假设有一个旅行商人要拜访n个城市,已知这n个城市的坐标,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。

这种问题被归类为NP-hard问题,NP是指非确定性多项式(non-deterministic polynomial,缩写NP)。所谓的非确定性是指,可用一定数量的运算去解决多项式时间内可解决的问题。即有限的时间内无法精确解决的问题。

旅行商问题(TSP)就是一个NP-hard问题

如果采用普通搜索算法,即穷举法,在城市数量比较少(10个及以下)的时候还可以解决,一旦城市超过15个,我们就不可能在短时间内求解,数量更多时,求解时间可能要上亿年,所以穷举法求解旅行商问题是不可行的。

我们今天采用启发式算法之一——模拟退火算法

模拟退火算法求解的结果通常不是全局最优解,但是这个算法可以在有限时间内求解NP-hard问题的近似解,近似解和全局最优解通常差距极小

相关概念

温度:每次冷却后会降温,温度越高,当前的解越不稳定,温度较低时,当前的解很稳定.

候选解:符合题目条件的解,又称可行解

新解:已知当前的解,我们人为规定一个法则,生成一个新的候选解

Metropolis准则:先假设我们的目标是最小化问题,求解最小值问题。如果生成的新解的目标值小于当前解的目标值,则直接接受新解;如果生成的新解的目标值大于当前解的目标函数值,则概率接受新解,接受新解的概率取决于两解的目标值之差以及当前温度,当前的温度越高,接受新解的概率越大,两解的目标值之差越大,接受新解的概率越小

用公式表达就是

                               

 

链长:在每个温度下要进行L次迭代,这个L就是链长

冷却:主要是指数冷却,线性冷却

指数冷却:T_{k+1}=\alpha T_k,\alpha\in(0,1)

线性冷却:T_{k+1}=T_k-\eta k

基本思想

算法流程:

初始化各个参数以及初始解

当前温度不符合终止准则时:

        迭代次数k<L:

                生成新解

                根据Metropolis准则判断是否接受新解

                k=k+1

        end

        迭代次数到达时,冷却(线性冷却,指数冷却)

end

输出最终解

算法流程图

实例:模拟退火算法求解TSP(旅行商)问题 

数据集下载(tsp文件可以把后缀名改成txt):

链接:https://pan.baidu.com/s/1_8RMaoOwoYhFdxeyzl8-0Q?pwd=1234 
提取码:1234 
--来自百度网盘超级会员V4的分享

注意:下面的函数同时在当前文件夹下,运行程序TSP.m,才可以运行

主程序TSP.m 

%初始参数:T0(初始温度) T_end(结束温度) L(链长) alpha(降温速率) S1(初始解) 
% 1.计算任意两点间的距离矩阵
% 2.生成新解
% 3.根据Metropolis准则判断是否接受新解
% 4.继续迭代,直到达到了迭代次数
% 5.降温
% 6.重复上面的2~5,直到温度降到最低
% 定义的函数:
% 1.根据每个城市的坐标计算任意距离矩阵函数Distence.m
% 2.绘制路线图Drawpath.m
% 3.计算一个解的距离的函数CalDist.m
% 4.生成新解的函数NewSolution.m
% 5.Metropolis准则函数,传入参数为(df,T_now),返回0或1。1代表接受新解,Metropolis.m
% 6.输出解的函数Disp.m

% 总体思路:给定初始温度,温度大于最低温度的时候,代表计算还在继续。每迭代一次,温度以指数规律减少。每次迭代时,指定链长L是操作的最大次数,我们每次迭代一共生成L次新解

%bayg29是一个包括29个点的城市坐标数据集,每行第一个元素是横坐标,第二个元素是纵坐标
bayg29=[1150	1760
630	1660
40	2090
750	1100
750	2030
1030	2070
1650	650
1490	1630
790	2260
710	1310
840	550
1170	2300
970	1340
510	700
750	900
1280	1200
230	590
460	860
1040	950
590	1390
830	1770
490	500
1840	1240
1260	1500
1280	790
490	2130
1460	142
1260	1910
360	1980];
%citydataset代表当前的(N*2)数据集
citydataset=bayg29;
%模型的初始参数可以随时修改,L是链长,代表同一个温度下迭代的次数
T0=50000;T_end=1e-10;L=400;alpha=0.99;
[Num,~]=size(citydataset);%Num是城市的个数
S1=randperm(Num);%S1代表目前的解
DistMatrix=Distance(citydataset);%距离矩阵,第i行第j列是城市i到城市j的距离
disp(['初始路线的长度是:',num2str(CalDist(S1,DistMatrix))])
T_now=T0;
Drawpath(S1,citydataset)
%Tset=T_now;
Tset=1;p=1;
Calset=CalDist(S1,DistMatrix);
while T_now>T_end
    k=1;
    while k<=L
        S_new=NewSolution(S1);
        df=CalDist(S_new,DistMatrix)-CalDist(S1,DistMatrix);
        if Metropolis(df,T_now)==1 %接受新解
            S1=S_new;
        end
        k=k+1;
    end
    T_now=T_now*alpha;
    %Tset=[Tset,T_now];
    Tset=[Tset,p];p=p+1;
    cal=CalDist(S1,DistMatrix);
    Calset=[Calset,cal];
end
figure
plot(Tset,Calset)
xlabel('迭代次数')
ylabel('当前的总路线长度')
Drawpath(S1,citydataset)
disp('最终的路线是:')
Disp([S1])
disp(['最终路线的长度是:',num2str(CalDist(S1,DistMatrix))])

Diatance.m (生成距离矩阵,距离矩阵的第i行第j列代表第i个城市与第j个城市之间的距离)

function y=Distance(Label)
% Label是城市1~N的坐标
[Num,~]=size(Label);
y=zeros(Num,Num);%坐标矩阵初始化
for i=1:Num
    for j=1:Num
        y(i,j)=sqrt((Label(i,1)-Label(j,1))^2+(Label(i,2)-Label(j,2))^2);
    end
end

Metropolis.m (Metropolis准则)

function L=Metropolis(df,T)
if df<0 %新解比当前解小的时候,一定接受新解
    L=1;
else
    r=rand(1);
    if r<exp(-df/T) %新解大于当前解的时候,概率接受新解,接受概率取决于当前温度和新解与旧解之差
        L=1;
    else
        L=0;
    end
end

CalDist.m (根据当前解和城市的距离矩阵,生成这条路线的距离总和)

function sum=CalDist(s,Matrix)% s是当前解,Matrix是距离矩阵
[~,Num]=size(s);
sum=0;
for i=1:Num-1
    sum=sum+Matrix(s(i),s(i+1));
end
sum=sum+Matrix(Num,1);

NewSolution.m (用随机交换两个城市的方法生成新解)

function s1=NewSolution(s)
[~,Num]=size(s);
R=round(rand(1,2)*(Num-1)+1);
s1=s;
s1(R(1))=s(R(2));
s1(R(2))=s(R(1));

Drawpath.m(已知序列和各个城市的坐标矩阵,绘制路线图) 

function Drawpath(S,coordinate)
[~,Num]=size(S);
ChormMatrix=zeros(2,Num+1);
for i=1:Num
    ChormMatrix(1,i)=coordinate(S(i),1);
    ChormMatrix(2,i)=coordinate(S(i),2);
end
ChormMatrix(1,Num+1)=ChormMatrix(1,1);
ChormMatrix(2,Num+1)=ChormMatrix(2,1);
figure
hold on
plot(ChormMatrix(1,:),ChormMatrix(2,:))

Disp.m (已知一个序列,输出路线)

function Disp(S)
[~,Num]=size(S);
p=num2str(S(1));
for i=2:Num-1
    p=[p,'->',num2str(S(i))];
end
disp(p)

求解结果:

初始解:

 

最终解 

 

>> TSP

初始路线的长度是:27863.5694

最终的路线是:

27->7->25->23->8->24->13->16->19->11->22->17->14->18->15->4->10->20->2->21->1->28->6->12->9->5->26->29

最终路线的长度是:9665.4694

注意:模拟退火算法每次运行的结果都不一定相同,所以可以多试几次,得到一个比较小的解

  • 14
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
模拟退火算法是一种常用的求解TSP旅行问题)的优化算法之一,它可以在一定程度上避免陷入局部最优解。在Matlab中,我们可以通过以下步骤实现模拟退火算法求解TSP问题: 1. 定义目标函数,即计算路径长度; 2. 初始化初始解,并计算其目标函数值; 3. 定义降温方案,即确定温度下降的速度和降温的策略; 4. 在每个温度下执行以下循环: a. 随机生成新解,并计算其目标函数值; b. 如果新解的目标函数值更优,则接受新解; c. 否则按一定概率接受新解; 5. 当温度降低到一定程度或达到迭代次数时停止搜索,并返回最优解。 以下是模拟退火算法解决TSP问题Matlab代码示例: ```matlab % 定义目标函数 function dist = distance(path, dist_matrix) % 计算路径长度 dist = 0; for i = 1:length(path)-1 dist = dist + dist_matrix(path(i), path(i+1)); end dist = dist + dist_matrix(path(end), path(1)); end % 初始化初始解 path = [1:n]; % n为城市数 path = path(randperm(n)); % 计算初始解的目标函数值 dist_matrix = % 城市间距离矩阵 dist = distance(path, dist_matrix); % 定义降温方案 temp = 100; % 初始温度 cool_rate = 0.95; % 温度下降速度 % 迭代搜索 while temp > 1e-8 % 温度降低到一定程度停止搜索 for i = 1:100 % 每个温度下执行100次循环 % 随机生成新解 new_path = path; swap_index = randperm(n, 2); new_path(swap_index(1)) = path(swap_index(2)); new_path(swap_index(2)) = path(swap_index(1)); % 计算新解的目标函数值 new_dist = distance(new_path, dist_matrix); % 判断是否接受新解 delta = new_dist - dist; if delta < 0 || exp(-delta/temp) > rand() path = new_path; dist = new_dist; end end % 降温 temp = temp * cool_rate; end % 返回最优解 best_path = path; best_dist = dist; ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Logistic..

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

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

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

打赏作者

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

抵扣说明:

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

余额充值