基于模拟退火算法的TSP算法

304 篇文章 190 订阅
13 篇文章 8 订阅

一,理论基础

模拟退火(simulated annealing,SA)算法的思想最早是由Metropolis等提出的。其出发点是基于物理中固体物质的退火过程与一般的组合优化问题之间的相似性。模拟退火法是一种通用的优化算法,其物理退火过程由以下三部分组成:
(1)加温过程。其目的是增强粒子的热运动,使其偏离平衡位置。当温度足够高时,固体将熔化为液体,从而消除系统原先存在的非均匀状态。
(2)等温过程。对于与周围环境交换热量而温度不变的封闭系统,系统状态的自发变化总是朝自由能减少的方向进行的,当自由能达到最小时,系统达到平衡状态。
(3)冷却过程。使粒子热运动减弱,系统能量下降,得到晶体结构。
SA算法实现过程如下(以最小化问题为例):
(1)初始化:取初始温度 T 0 T_0 T0足够大,令 T = T 0 T=T_0 T=T0,任取初始解 S 1 S_1 S1,确定每个 T T T时的迭代次数,即Metropolis链长 L L L
(2)对当前温度 T T T k = 1 , 2 , ⋯   , L k=1,2,\dotsm,L k=1,2,,L,重复步骤(3)~(6)。
(3)对当前解 S 1 S_1 S1随机扰动(比如交换 S 1 S_1 S1分量的数据)产生一个新解 S 2 S_2 S2
(4)计算S2的增量 d f = f ( S 2 ) − f ( S 1 ) df=f(S_2)-f(S_1) df=f(S2)f(S1),其中 f ( S 1 ) f(S_1) f(S1)为S1的代价函数。
(5)若 d f < 0 df<0 df<0,则接受S2作为新的当前解,即 S 1 = S 2 S_1=S_2 S1=S2;否则计算S2的接受概率 e x p ( − d f / T ) exp(-df/T) exp(df/T),即随机产生 ( 0 , 1 ) (0,1) (0,1)区间上均匀分布的随机数 r a n d rand rand,若 e x p ( − d f / T ) > r a n d exp(-df/T)>rand exp(df/T)>rand,也接受S2作为新的当前解, S 1 = S 2 S_1=S_2 S1=S2;否则保留当前解 S 1 S_1 S1
(6)如果满足终止条件 S t o p Stop Stop,则输出当前解 S 1 S_1 S1为最优解,结束程序。终止条件 S t o p Stop Stop通常为:在连续若干个Metropolis链中新解 S 2 S_2 S2都没有被接受时终止算法,或是设定结束温度。否则,则按衰减函数衰减 T T T后返回步骤(2)。
以上步骤称为Metropolis过程。逐渐降低控制温度,重复Metropolis过程,直至满足结束准则Stop,求出最优解。

二,TSP问题介绍

TSP(traveling salesman problem,旅行商问题)是典型的NP完全问题,即其最坏情况下的时间复杂度随着问题规模的增大按指数方式增长,到目前为止还未找到一个多项式时间的有效算法。
TSP问题可描述为:已知 n n n个城市相互之间的距离,某一旅行商从某个城市出发访问每个城市有且仅有一次,最后回到出发城市,如何安排才使其所走路线距离最短。简言之,就是寻找一条最短的遍历 n n n个城市的路径,或者说搜索自然子集 X = { 1 , 2 , ⋯   , n } X=\{1,2,\dotsm,n\} X={1,2,,n}( X X X的元素表示对 n n n个城市的编号)的一个排列 π ( X ) = { V 1 , V 2 , ⋯   , V n } π(X)=\{V_1,V_2,\dotsm,V_n\} π(X)={V1,V2,,Vn},使得 T d = ∑ i = 1 n + 1 d ( V i , V i + 1 ) + d ( V n , V 1 ) T_d=\sum_{i=1}^{n+1} {d(V_i,V_{i+1})}+d(V_n,V_1) Td=i=1n+1d(Vi,Vi+1)+d(Vn,V1)取得最小值,其中 d ( V i , V i + 1 ) d(V_i,V_{i+1}) d(Vi,Vi+1)表示城市 V i V_i Vi到城市 V i + 1 V_{i+1} Vi+1的距离。

三,思路和步骤

1.算法流程
模拟退火算法求解TSP问题的流程图如图1所示。

图1 模拟退火算法求解流程图

在这里插入图片描述
2.模拟退火算法实现

控制参数的设置

需要设置的主要控制参数有降温速率 q q q、初始温度 T 0 T_0 T0、结束温度 T e n d T_{end} Tend以及链长 L L L

初始解

对于 n n n个城市的TSP问题,得到的解就是对1~ n n n的一个排序,其中每个数字对应城市的编号。

解变换生成新解

通过对当前解 S 1 S_1 S1进行变换,产生新的路径数组即新解,这里采用的变换是产生随机数的方法来产生将要交换的两个城市,用二邻域变换法产生新的路径,即可行的新解 S 2 S_2 S2

Metropolis准则

若路径长度函数为 f ( S ) f(S) f(S),则当前解的路径为 f ( S 1 ) f(S_1) f(S1),新解的路径为 f ( S 2 ) f(S_2) f(S2),路径差为 d f = f ( S 2 ) − f ( S 1 ) df=f(S_2)-f(S_1) df=f(S2)f(S1),则Metropolis准则为 P = { 1 , d f <0 e x p ( − d f T ) , d f ≥0 P= \begin{cases}1, & \text{$df$<0} \\ exp(-\frac {df} {T}), & \text{$df$≥0} \\\end{cases} P={1,exp(Tdf),df<0df≥0如果 d f < 0 df<0 df<0,则以概率1接受新的路径;否则以概率 e x p ( − d f T ) exp(-\frac {df} {T}) exp(Tdf)接受新的路径。

降温

利用降温速率 q q q进行降温,即 T = q T T=qT T=qT,若 T T T小于结束温度,则停止迭代输出当前状态,否则继续迭代。

四,MATLAB程序实现

  • 计算距离矩阵
function D = Distance(citys)
%% 计算两两城市之间的距离
% 输入 citys  各城市的位置坐标
% 输出 D  两两城市之间的距离

n = size(citys,1);
D = zeros(n,n);
for i = 1:n
   for j = i+1:n
       D(i,j) = sqrt(sum((citys(i,:) - citys(j,:)).^2));
       D(j,i) = D(i,j);
   end
end
  • 初始解
S1=randperm(N);			% 随机产生一个初始路线
  • 生成新解
function S2 = NewAnswer(S1)
%% 输入
% S1:当前解
%% 输出
% S2:新解

N = length(S1);
S2 = S1;                
a = round(rand(1,2)*(N-1)+1); %产生两个随机位置 用来交换
W = S2(a(1));
S2(a(1)) = S2(a(2));
S2(a(2)) = W;         %得到一个新路线
  • Metropolis准则
function [S,R] = Metropolis(S1,S2,D,T)
%% 输入
% S1:  当前解
% S2:   新解
% D:    距离矩阵(两两城市的之间的距离)
% T:    当前温度
%% 输出
% S:   下一个当前解
% R:   下一个当前解的路线距离

R1 = PathLength(D,S1);  %计算路线长度
N = length(S1);         %得到城市的个数

R2 = PathLength(D,S2);  %计算路线长度
dC = R2 - R1;   %计算能力之差
if dC < 0       %如果能力降低 接受新路线
    S = S2;
    R = R2;
elseif exp(-dC/T) >= rand   %exp(-dC/T)概率接受新路线
    S = S2;
    R = R2;
else        %不接受新路线
    S = S1;
    R = R1;
end
  • 画路线轨迹图
function DrawPath(Route,citys)
%% 画路径函数
%输入
% Route  待画路径   
% citys  各城市坐标位置

figure
plot([citys(Route,1);citys(Route(1),1)],...
     [citys(Route,2);citys(Route(1),2)],'o-');
grid on

for i = 1:size(citys,1)
    text(citys(i,1),citys(i,2),['   ' num2str(i)]);
end

text(citys(Route(1),1),citys(Route(1),2),'       起点');
text(citys(Route(end),1),citys(Route(end),2),'       终点');

  • 输出路径函数
function p = OutputPath(R)
%% 输出路径函数
% 输入:R 路径
R = [R,R(1)];
N = length(R);
p = num2str(R(1));
for i = 2:N
    p = [p,'—>',num2str(R(i))];
end
disp(p)
  • 可行解路线长度函数
function Length = PathLength(D,Route)
%% 计算各个体的路径长度
% 输入:
% D     两两城市之间的距离
% Route 个体的轨迹

Length = 0;
n = size(Route,2);
for i = 1:(n - 1)
    Length = Length + D(Route(i),Route(i + 1));
end
Length = Length + D(Route(n),Route(1));
  • 模拟退火算法主函数
    模拟退火算法参数设置如下所列。

在这里插入图片描述
主函数代码如下:

 %% I. 清空环境变量
clear all
clc

%% II. 导入城市位置数据
X = [16.4700   96.1000
     16.4700   94.4400
     20.0900   92.5400
     22.3900   93.3700
     25.2300   97.2400
     22.0000   96.0500
     20.4700   97.0200
     17.2000   96.2900
     16.3000   97.3800
     14.0500   98.1200
     16.5300   97.3800
     21.5200   95.5900
     19.4100   97.1300
     20.0900   92.5500];

%% III. 计算距离矩阵
D = Distance(X);  %计算距离矩阵
N = size(D,1);    %城市的个数

%% IV. 初始化参数
T0 = 1e10;   % 初始温度
Tend = 1e-30;  % 终止温度
L = 2;    % 各温度下的迭代次数
q = 0.9;    %降温速率
syms x;
Time = ceil(double(solve(T0*(0.9)^x == Tend)));    % 计算迭代的次数
% Time = 132;
count = 0;        %迭代计数
Obj = zeros(Time,1);         %目标值矩阵初始化
track = zeros(Time,N);       %每代的最优路线矩阵初始化

%% V. 随机产生一个初始路线
S1 = randperm(N);
DrawPath(S1,X)
disp('初始种群中的一个随机值:')
OutputPath(S1);
Rlength = PathLength(D,S1);
disp(['总距离:',num2str(Rlength)]);

%% VI. 迭代优化
while T0 > Tend
    count = count + 1;     %更新迭代次数
    temp = zeros(L,N+1);
    %%
    for k = 1:L
        % 1. 产生新解
        S2 = NewAnswer(S1);
        % 2. Metropolis法则判断是否接受新解
        [S1 R] = Metropolis(S1, S2, D, T0);   % Metropolis抽样算法
        temp(k, :) = [S1 R];            % 记录下一路线及其长度
    end
    %% 3. 记录每次迭代过程的最优路线
    [d0, index] = min(temp(:, end));    % 找出当前温度下最优路线
    if count == 1 || d0 <= Obj(count-1)
        Obj(count) = d0;                    % 如果当前温度下最优路程小于上一路程则记录当前路程
    else
        Obj(count) = Obj(count-1);    % 如果当前温度下最优路程大于上一路程则记录上一路程
    end
    track(count, :) = temp(index, 1:end-1);  % 记录当前温度的最优路线
    %降温
    T0 = q * T0;
end

%% VII. 优化过程迭代图
figure
plot(1:count,Obj)
xlabel('迭代次数')
ylabel('距离')
title('优化过程')

%% VIII. 绘制最优路径图
DrawPath(track(end,:),X)

%% IX. 输出最优解的路线和总距离
disp('最优解:')
S = track(end,:);
p = OutputPath(S);
disp(['总距离:',num2str(PathLength(D,S))]);

五,结果分析

优化前的一个随机路线轨迹图如图2所示。

初始种群中的一个随机值:
11>1>14>12>7>13>2>9>10>4>8>5>3>6>11
总距离:62.0785

优化后的路线如图3所示。

最优解:
6>12>7>13>8>11>9>10>1>2>14>3>4>5>6
总距离:29.3405
图2 随机路线图

在这里插入图片描述

图3 最优解路线图

在这里插入图片描述

优化迭代过程如图4所示。

图4 模拟退火算法优化过程图

在这里插入图片描述

由图4可以看出,优化前后路径长度得到很大改进,由优化前的64.7606变为29.8332,变为原来的46.1%,600多代以后路径长度已经保持不变了,可以认为已经是最优解了。

六,算法的改进

(1)使用逆转操作,即选择两个城市后,逆转这两个城市之间的所有城市。
(2)选择3个城市,将两个城市之间的城市插入到第3个城市的后面(这两个城市之间不包括第3个城市)。

七,算法的局限性

问题规模 n n n比较小时,得到的一般都是最优解,但当规模比较大时,一般只能得到近似解。这时可以通过增大种群大小和增加最大迭代次数使优化值更接近最优解。

八,参考文献

[1] 张建航, 李国. 模拟退火算法及其在求解TSP中的应用[J]. 现代电子技术, 2006, 29(22): 157-158.
[2] 盛国华, 陈玉金. 改进模拟退火算法求解TSP问题[J]. 电脑知识与技术, 2008(15): 129-130+156.
[3] 郁磊, 史峰, 王辉, 等. MATLAB智能算法30个案例分析(第2版)[M]. 北京: 北京航空航天大学出版社, 2015.

模拟退火算法是一种常用于解决旅行商问题(TSP)的优化算法。它的算法思想是通过模拟物质的冷却过程来搜索最优解。首先,随机生成一个初始解,然后以一定的概率接受更差的解,这样可以避免陷入局部最优解。随着时间的推移,温度逐渐降低,搜索的范围也逐渐缩小,最终得到一个较优的解。 在模拟退火算法中,邻域函数的选择对于收敛结果有很大的影响。通过改进邻域函数的方法,可以优化模拟退火的性能,使得搜索过程更加高效。此外,降温系数也对算法的性能有明显的影响,一个合适的降温系数可以优化算法的运行时间。常见的降温方式有指数降温方式等,可以根据实际情况选择不同的降温方式进行实验,并观察算法的结果。 实验结果表明,随着温度的降低,模拟退火算法的波动幅度减小,系统趋于稳定。优化邻域函数可以明显提升模拟退火算法的性能,使得得到的最优解更接近真实最优解。降低降温系数可以显著提升算法的性能,而算法计算的结果并不会有太大下降。因此,选择一个合适的降温系数对于算法的性能至关重要。 综上所述,模拟退火算法是一种有效解决旅行商问题的方法。通过合理选择邻域函数和降温系数,可以优化算法的性能,并得到较优的解。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [一文看懂模拟退火算法求解TSP问题(通俗易懂)](https://blog.csdn.net/qq_43937678/article/details/115679214)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

心️升明月

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

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

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

打赏作者

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

抵扣说明:

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

余额充值