模拟退火算法应用——求解TSP问题

仅作自己学习使用


一、问题

        旅行商问题(TSP) 是要求从一个城市出发,依次访问研究区所有的城市,并且只访问一次不能走回头路,最后回到起点,求一个使得总的周游路径最短的城市访问顺序。
       采用模拟退火算法求解TSP问题,很自然的想到退火的目标函数(优化函数)应该就是总的周游距离。那么在算法中如何体现呢?那就是把城市的坐标放在一个n×2的矩阵中,矩阵中存放城市的顺序就是依次周游城市的路径,所以在求解过程中会不断的产生新的更优解(周游顺序,在算法中体现就是城市坐标的存放顺序),有了这个关键的思路就很好解决了。

二、Matlab代码

clear
clc
T1 = cputime;
C = [
    % 各个城市坐标
    39.91, 116.39;   % 北京
    31.22, 121.48;   % 上海
    23.13, 113.27;   % 广州
    22.54, 114.06;   % 深圳
    30.67, 104.06;   % 成都
    34.27, 108.93;   % 西安
    31.98, 118.75;   % 南京
    39.92, 116.36;   % 天津
    28.71, 115.83;   % 南昌
    45.75, 126.63;   % 哈尔滨
    36.07, 120.38;   % 青岛
    38.04, 114.48;   % 石家庄
    29.59, 106.54;   % 重庆
    26.08, 119.30;   % 福州
    30.25, 120.16;   % 杭州
    28.19, 112.97;   % 长沙
    25.03, 102.73;   % 昆明
    35.68, 139.76;   % 东京
    37.56, 126.97;   % 首尔
    1.35, 103.82;    % 新加坡
    13.41, 103.86;   % 金边
    21.03, 105.85;   % 河内
    3.14, 101.69;    % 吉隆坡
    39.90, 32.85;    % 安卡拉
    37.97, 23.73;    % 雅典
    38.71, -9.14;    % 里斯本
    41.89, 12.50;    % 罗马
    52.52, 13.41;    % 柏林
    55.75, 37.62;    % 莫斯科
    48.86, 2.35;     % 巴黎
];

n = length(C);  % 获取城市的个数
T = 100 * n;    % 初始温度
L = 10;         % 马尔可夫链长度
K = 0.986;      % 降温系数

%%  构建城市坐标结构体
city = struct([]);
for i = 1:n
    city(i).x = C(i,1);     % 经度
    city(i).y = C(i,2);     % 纬度
end

%% 开始退火
% 统计迭代次数
count = 1;   
% 计算每次迭代后的总距离(第一次就是初始时,按照坐标的顺序计算的距离)
Dist(count) = GetDist(city,n); 
figure(1)
% 当温度无限趋于0度时停止迭代
while T > 0.01 
    % 每次降温 均进行多次迭代
    for i = 1:L
        % 计算原路线周游距离
        len1 = GetDist(city,n);
        % 产生随机扰动(随机交换两个城市的坐标)
        p1 = floor(1 + n * rand()); % rand函数产生一个0,1之间均匀分布的实数,包含0但不包含1
        p2 = floor(1 + n * rand()); % 因此这个表达式可以产生一个从1到n的随机数
        while (p1 == p2)
            p1 = floor(1 + n * rand()); 
            p2 = floor(1 + n * rand());
        end
        temp_city = city;
        % 交换第P1个城市和第P2个城市的坐标
        temp = temp_city(p1);
        temp_city(p1) = temp_city(p2);
        temp_city(p2) = temp;
        % 计算新路线的周游距离
        len2 = GetDist(temp_city,n);
        % 新、老路线的差值(相当于能量)
        delta = len2 - len1;
        if(delta<0)
            % 新路线的评估函数更小(记住,模拟退火算法相当于是一个求函数极小值的算法)
            city = temp_city;  % 更新原路线(变量里存放城市的顺序也就是访问城市的顺序)
        else
            % Metropolis接受准则(概率选择更差的解)
            if exp((len1-len2)/T) > rand()
                % 记住这个概率的公式,指数部分一定是要个负数,概率的值不可能超过1
                city = temp_city;
            end
        end
    end
    % 本次迭代结束,统计迭代次数加1
    count = count + 1; 
    % 将本次迭代的最优解放在len中
    Dist(count) = GetDist(city,n); 
    %% 本次退火结束,降温
    T = T * K;
    % 按照新的城市的顺序,把这些城市画出来
    for i = 1: n-1
        plot([city(i).x,city(i+1).x],[city(i).y,city(i+1).y],'bo-');
        hold on;
    end
    plot([city(n).x,city(1).x],[city(n).y,city(1).y],'ro-');
    title(['优化最短距离:', num2str(Dist(count))]);
    hold off
    pause(0.005); % 动态显示出每次的搜索结果
end
T2 = cputime;
figure(2)
plot(Dist,LineWidth=2)
xlabel("迭代次数")
ylabel("目标函数值")
title("适应度进化曲线","搜索时间:"+(T2-T1)+" s")
%% 评估函数
function result = GetDist(city,n)
% 计算总的周游路径长度(评估函数)
% city是各个城市的坐标
    result = 0;
    for i = 1:n-1
        result = result + sqrt((city(i).x - city(i+1).x)^2 + (city(i).y - city(i+1).y)^2);
    end
    result = result + sqrt((city(n).x - city(1).x)^2 + (city(n).y - city(1).y)^2);
end

三、效果

周游图

适应度进化曲线

四、问题

        大家可以试一试更多的城市,当有很多城市的坐标相差不大时,在最后的搜索结果中,会出现一个非常奇怪的问题,就是在周游图中,有些城市消失了,检查存放城市的city结构体,是存放着这些坐标的,这里如果有知道的朋友还请多多批评指教,我将及时改正。

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
模拟退火算法是一种常用的求解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; ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

亲爱的老吉先森

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

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

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

打赏作者

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

抵扣说明:

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

余额充值