智能优化算法-入门教程

【介绍】一篇入门之-TSP旅行商问题是什么

作者 : 老饼 发表日期 : 2022-10-30 23:15:09 更新日期 : 2025-05-21 21:53:04
本站原创文章,转载请说明来自《老饼讲解-深度学习》www.bbbdata.com



‌TSP问题(Traveling Salesman Problem)‌是一个经典的组合优化问题,它旅行商如何走完所有城市才能最短

本文讲解TSP问题的描述,并展示TSP问题的特点、数学表示方式,并展示一个求解TSP问题的代码示例

通过本文,可以快速了解TSP问题是什么,有什么特点,以及求解TSP问题的常用方法,以及如何求解TSP问题






   01. TSP旅行商问题是什么    




本节介绍TSP旅行商问题是什么,以及它的特点




     TSP旅行商问题      


TSP(Traveling Salesman Problem,旅行销售商)问题如下:
现有N个城市 ,旅行商需求穿过每个城市,最终回到出发城市
 TSP问题是什么
则旅行商问题为:如何寻找一条路径,使旅行总距离最小





    TSP问题的数学表述    


假设有5个城市,用矩阵D表示城市之间的距离
  代表第i个城市到第j个城市的距离      
路径X可以表示为序列形式: 
它代表先到城市1,再到城市5,再到3.....最后由4回到1
而总距离就是按这顺序行走的总距离
使用以上表示 ,则旅行商TSP问题可以理解为:求一 个1到N的组合X,令总距离F最小
✍️TSP问题的经典性
TSP问题有两个特有的经典特点
1. 不能穷举                
它的解空间是非常大的,这就不能用一般的穷举法来寻找最优解
如果有N个城市,那么就会有(N-1)!个解,N=15时,(15-1)!就约等于871亿

2. x与f(x)的非纯数学性
 它的目标函数   和解  而更倾向于一系列描述性计算
而不是一般问题那样具有严格的数值表达式,这导致它不能用梯度下降一类的算法来求解







   02. TSP问题的求解方法    





本节展示用智能算法求解TSP问题的一个例子





    TSP问题的求解方法     


TSP问题的求解方法往往使用智能优化算法求解,例如模拟退火、遗传算法、蚁群算法等
这类智能优化算法以启发式搜索为核心,可以求得TSP问题的优秀解
 用模拟退火算法求解TSP问题的代码实现如下:
%代码说明:模拟退火求解TSP旅行商问题
%来自《老饼讲解神经网络》www.bbbdata.com ,matlab版本:2018a
clc;clear all;close all 
cityLoc = [3.64,2.68  ;...  %beijing
           4.18,1.76  ;...  %shanghai
           3.71,2.60  ;...  %tianjin
           1.33,3.30  ;...  %wulumuqi
           4.20,2.96  ;...  %shenyang
           3.92,1.82  ;...  %nanjing
           2.55,1.64  ;...  %chengdu
           2.37,1.02  ;...  %kunming
           3.43,2.09  ;...  %zhengzhou
           3.54,0.70  ;...  %xianggang
           3.51,1.62  ;...  %wuhan
           3.44,0.80  ;...  %guangzhou
           3.24,2.77  ;...  %huhehaote
           2.38,2.32  ;...  %xiling
           2.56,2.24  ;...  %lanzhou
           3.01,2.03  ;...  %xian
           2.79,2.51  ;...  %yinchuan
           4.03,1.16  ;...  %fuzhou
           3.47,0.70  ;...  %aomen
           1.30,1.69] ;     %lasha
distMat = dist(cityLoc') ;                                                % 计算城市距离
N = size(cityLoc,1);                                                      % 城市个数
rng(888)                                                                  % 为方便复现结果,设定随机种子
															             
x = randperm(N);                                                          % 随机初始化解
E = distMat(x(end),x(1));                                                 % 初始化解的能量
for i=1:length(x)-1                                                       
    E = E+ distMat(x(i),x(i+1));                                          % 累加各个城市之间的距离
end


%---------温度初始化可用此方法(取N次邻域能量差均值的10倍)-------------
dE     = 0;                                                               % 计算平均能量差
try_cn = 20;                                                              % 尝试次数
for k = 1:try_cn                                                          
    pair =  randperm(N);                                                  % 随机生成要交换的两个位置
    new_x = x;  % 将旧解copy过来                                          
    new_x([pair(1),pair(2)])= new_x([pair(2),pair(1)]);                   % 将选择的两个位置进行交换
    new_E = distMat(new_x(end),new_x(1));                                 % 初始化新解的能量
    for i = 1:length(x)-1                                                   
        new_E = new_E+ distMat(new_x(i),new_x(i+1));                      % 累加各个城市之间的距离
    end                                                                   
    dE = dE+ abs(E-new_E)/try_cn;                                         % 更新平均能量差
end                                                                       
teamp = dE*10 ;                                                           % 温度初始化
														                  
														                  
%-------------外循环-------------------------                             
for t=1:100                                                               
    minE = E;                                                             % 记录本轮的最小能量
    maxE = E;                                                             % 记录本轮的最大能量
    %--------内循环-----------------------                                
    for k  =1:500                                                         
        pair  =  randperm(N);                                             % 随机生成要交换的两个位置
        new_x = x;  % 将旧解copy过来                                      
        new_x([pair(1),pair(2)])= new_x([pair(2),pair(1)]);               % 将选择的两个位置进行交换
        new_E = distMat(new_x(end),new_x(1));                             % 初始化新解的能量
        for i = 1:length(x)-1                                             
            new_E = new_E+ distMat(new_x(i),new_x(i+1));                  % 累加各个城市之间的距离
        end                                                               
        %--------按概率接受新解-------------------                        
        if(exp((E-new_E)/teamp)>rand())                                   % 如果接受新解
            x = new_x;                                                    % 更新解
            E = new_E;                                                    % 更新能量
            minE = min(E,minE);                                           % 更新本轮的最小能量
            maxE = max(E,maxE);                                           % 更新本轮的最大能量
        end
    end
    disp(['第',num2str(t),'轮:E=',num2str(E),',teamp:',num2str(teamp)])   % 打印当前温度与能量
    disp(['       minE=',num2str(minE),',maxE:',num2str(maxE)])           % 打印最小最大能量
    hold off
    plot(cityLoc(:,1),cityLoc(:,2),'o','MarkerEdgeColor','k','MarkerFaceColor','y','MarkerSize',10,'LineWidth',2)
    hold on
    plot(cityLoc([x,x(1)],1),cityLoc([x,x(1)],2))
    drawnow
    %--------降温,并检查是否退出循环--------
    teamp = teamp*0.9;                                                    % 降温
    if((maxE-minE)/maxE<0.001)                                            % 如果最优最差解并没太大差异
        break                                                             % 退出循环
    end
end
运行结果如下:
TSP问题求解结果
可以看到,本例中共有20个城市,路径的组合有(20-1)!种 ,是非常庞大的
但经模拟退火求解,可以看到,在有限的步数内,已经能自动找到一条不错的路径了








好了,以上就是TSP旅行商问题的介绍,以及它的求解示例了~









  End  





内容纠正