旅行商tsp问题(Traveling Salesman Problem)matlab源码

运用退火算法解决旅行商问题。

源码参考清风老师思路以及广大网友。侵权立删 

主函数 

%% 模拟退火解决TSP问题
tic
clear;clc
coord = [26.99611373,17.4952427;30.86325116,42.42106760;43.61357686,38.9299278;
    35.00118717,36.98696184;20.20818722,46.55925669;46.18764943,42.83843589;
    40.6920241,31.94898546;32.50662006,10.62166377;45.88614135,13.7874543;
    24.72317638,30.59033166;23.50924028,48.09930553;34.75421424,43.72244785;
    13.4758176,47.40048984;25.01990127,48.9365234];%坐标信息自己改

n = size(coord,1);  % 城市的数目
 
figure  % 新建一个图形窗口
plot(coord(:,1),coord(:,2),'o');   % 画出城市的分布散点图
hold on % 等一下要接着在这个图形上画图的
 
d = zeros(n);   % 初始化两个城市的距离矩阵全为0
for i = 2:n  
    for j = 1:i  
        coord_i = coord(i,:);   x_i = coord_i(1);     y_i = coord_i(2);  % 城市i的横坐标为x_i,纵坐标为y_i
        coord_j = coord(j,:);   x_j = coord_j(1);     y_j = coord_j(2);  % 城市j的横坐标为x_j,纵坐标为y_j
        d(i,j) = sqrt((x_i-x_j)^2 + (y_i-y_j)^2);   % 计算城市i和j的距离
    end
end
d = d+d';   % 生成距离矩阵的对称的一面
 
%% 参数初始化
T0 = 1000;   % 初始温度
T = T0; % 迭代中温度会发生改变,第一次迭代时温度就是T0
maxgen = 1000;  % 最大迭代次数
Lk = 500;  % 每个温度下的迭代次数
alpfa = 0.95;  % 温度衰减系数
 
%%  随机生成一个初始解
path0 = randperm(n);  % 生成一个1-n的随机打乱的序列作为初始的路径
result0 = calculate_tsp_d(path0,d); % 调用我们自己写的calculate_tsp_d函数计算当前路径的距离
 
%% 定义一些保存中间过程的量,方便输出结果和画图
min_result = result0;     % 初始化找到的最佳的解对应的距离为result0
RESULT = zeros(maxgen,1); % 记录每一次外层循环结束后找到的min_result (方便画图)
 
%% 模拟退火过程
for iter = 1 : maxgen  % 外循环, 我这里采用的是指定最大迭代次数
    for i = 1 : Lk  %  内循环,在每个温度下开始迭代
        path1 = gen_new_path(path0);  % 调用我们自己写的gen_new_path函数生成新的路径
        result1 = calculate_tsp_d(path1,d); % 计算新路径的距离
        %如果新解距离短,则直接把新解的值赋值给原来的解
        if result1 < result0    
            path0 = path1; % 更新当前路径为新路径
            result0 = result1; 
        else
            p = exp(-(result1 - result0)/T); % 根据Metropolis准则计算一个概率
            if rand(1) < p   % 生成一个随机数和这个概率比较,如果该随机数小于这个概率
                path0 = path1;  % 更新当前路径为新路径
                result0 = result1; 
            end
        end
        % 判断是否要更新找到的最佳的解
        if result0 < min_result  % 如果当前解更好,则对其进行更新
            min_result = result0;  % 更新最小的距离
            best_path = path0;  % 更新找到的最短路径
        end
    end
    RESULT(iter) = min_result; % 保存本轮外循环结束后找到的最小距离
    T = alpfa*T;   % 温度下降       
end
 
disp('最佳的方案是:'); disp(mat2str(best_path))
disp('此时最优值是:'); disp(min_result)
 
best_path = [best_path,best_path(1)];   % 在最短路径的最后面加上一个元素,即第一个点(我们要生成一个封闭的图形)
n = n+1;  % 城市的个数加一个(紧随着上一步)
for i = 1:n-1 
    j = i+1;
    coord_i = coord(best_path(i),:);   x_i = coord_i(1);     y_i = coord_i(2); 
    coord_j = coord(best_path(j),:);   x_j = coord_j(1);     y_j = coord_j(2);
    plot([x_i,x_j],[y_i,y_j],'-b')    % 每两个点就作出一条线段,直到所有的城市都走完
%     pause(0.02)  % 暂停0.02s再画下一条线段
    hold on
end
 
%% 画出每次迭代后找到的最短路径的图形
figure
plot(1:maxgen,RESULT,'b-');
xlabel('迭代次数');
ylabel('最短路径');
toc

 gen_new_path.m

function path1 = gen_new_path(path0)
    % path0: 原来的路径
    n = length(path0);
    % 随机选择两种产生新路径的方法
    p1 = 0.33;  % 使用交换法产生新路径的概率
    p2 = 0.33;  % 使用移位法产生新路径的概率
    r = rand(1); % 随机生成一个[0 1]间均匀分布的随机数
    if  r< p1    % 使用交换法产生新路径 
        c1 = randi(n);   % 生成1-n中的一个随机整数
        c2 = randi(n);   % 生成1-n中的一个随机整数
        path1 = path0;  % 将path0的值赋给path1
        path1(c1) = path0(c2);  %改变path1第c1个位置的元素为path0第c2个位置的元素
        path1(c2) = path0(c1);  %改变path1第c2个位置的元素为path0第c1个位置的元素
    elseif r < p1+p2 % 使用移位法产生新路径
        c1 = randi(n);   % 生成1-n中的一个随机整数
        c2 = randi(n);   % 生成1-n中的一个随机整数
        c3 = randi(n);   % 生成1-n中的一个随机整数
        sort_c = sort([c1 c2 c3]);  % 对c1 c2 c3从小到大排序
        c1 = sort_c(1);  c2 = sort_c(2);  c3 = sort_c(3);  % c1 < = c2 <=  c3
        tem1 = path0(1:c1-1);
        tem2 = path0(c1:c2);
        tem3 = path0(c2+1:c3);
        tem4 = path0(c3+1:end);
        path1 = [tem1 tem3 tem2 tem4];
    else  % 使用倒置法产生新路径
        c1 = randi(n);   % 生成1-n中的一个随机整数
        c2 = randi(n);   % 生成1-n中的一个随机整数
        if c1>c2  % 如果c1比c2大,就交换c1和c2的值
            tem = c2;
            c2 = c1;
            c1 = tem;
        end
        tem1 = path0(1:c1-1);
        tem2 = path0(c1:c2);
        tem3 = path0(c2+1:end);
        path1 = [tem1 fliplr(tem2) tem3];   %矩阵的左右对称翻转 fliplr,上下对称翻转 flipud
    end
end

calculate_tsp_d.m 

function  result =  calculate_tsp_d(path,d)
% 输入:path:路径(1至n的一个序列),d:距离矩阵
    n = length(path);
    result = 0; % 初始化该路径走的距离为0
    for i = 1:n-1  
        result = d(path(i),path(i+1)) + result;  % 按照这个序列不断的更新走过的路程这个值
    end   
    result = d(path(1),path(n)) + result;  % 别忘了加上从最后一个城市返回到最开始那个城市的距离
end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值