用经典的模拟退火算法求解30城市小规模的TSP问题

模拟退火算法编码比较简单,而且容易调试,所以应用比较广泛。算法的思想可以参考这篇:模拟退火算法的基本思想和算法流程
直接给出源代码:

主程序:
clear all;
close all;
clc;
%% 参数设置
t_0 = 1e100;       %初始温度
t_f = 1e-90;      %终止温度
num_gen = 100;
num_swap=2;
num_city = 48;
[len_side,city] = City(num_city);    %城市坐标
cool_rate = 0.85;
solu = randperm(num_city);
t_k = t_0;
min_fit = zeros(2,2693);
j=1;
fit0=Fitness(solu,len_side);
min_fit(1,j)=j;
min_fit(2,j)=fit0;
%% 开始循环
while t_k > t_f         %循环条件,把降温底线作为条件         
    for i = 1 : num_gen                  %循环次数
       pre_fit = Fitness(solu,len_side); %旧适应度值
       temp_solu = Move(solu,num_swap);  
%随机n次交换
       temp_fit = Fitness(temp_solu,len_side);   %新距离和
       diff = temp_fit - pre_fit;  %产生误差
       if diff < 0     
%距离变小,直接接受,不用考虑 
           solu = temp_solu;             %接受    
       else
           if rand() < exp(-diff/(t_k))   %否则,以一定的概率接受
               solu = temp_solu;        %概率符合了,进来接受       
           end
       end
    end
   last_fit=Fitness(solu,len_side);
   t_k = t_k*cool_rate;      %降温过程
   j=j+1;
   min_fit(1,j)=j;
   min_fit(2,j)=last_fit;
end
%% 输出结果
temp_fit = last_fit/sqrt(10);
fprintf('\t\t\t最小值 = % 3.4f\n',temp_fit); 
figure
plot(min_fit(1,:),min_fit(2,:),'k');

move函数:
function s = Move(solu,n) 
s = solu;
len=length(solu);
 for i = 1 : n
    spot1 = round((len-1)*rand())+1;%生成随机交换点(1~30之间                      
    spot2 = round((len-1)*rand())+1;
    temp = s(1,spot1);        %交换操作
    s(:,spot1) = s(:,spot2);
    s(:,spot2) = temp;
 end
end

city函数
function [Len,city_loc]=City(n)
Len=zeros(n,n);%Len是一个30*30的矩阵,city_location是一个30行两列的矩阵
if n==30
    city=[41 94;37 84;54 67;25 62;7 64;2 99;68 58;71 44;54 62;83 69;64 60;18 54;22 60;%每一行是一个城市坐标
        83 46;91 38;25 38;24 42;58 69;71 71;74 78;87 76;18 40;13 40;82 7;62 32;58 35;45 21;41 26;44 35;4 50];%30 cities d'=423.741 by D B Fogel
end
if n ==48
    city=[6734 1453;2233 10;5530 1424;401 841;3082 1644;7608 4458;7573 3716;
7265 1268;6898 1885;1112 2049;5468 2606;5989 2873;4706 2674;4612 2035;6347 2683;
6107 669;7611 5184;7462 3590;7732 4723;5900 3561;4483 3369;6101 1110;5199 2182;
1633 2809;4307 2322;675 1006;7555 4819;7541 3981;3177 756;7352 4506;7545 2801;3245 3305;
6426 3173;4608 1198;23 2216;7248 3779;7762 4595;7392 2244;3484 2829;6271 2135;
4985 140;1916 1569;7280 4899;7509 3239;10 2676;6807 2993;5185 3258;3023 1942]
end
    for i=1:n-1
        for j=i+1:n
            Len(i,j)=((city(i,1)-city(j,1))^2+(city(i,2)-city(j,2))^2)^0.5;
            Len(j,i)=Len(i,j);
        end
    end
    city_loc=city;
end
Fitness函数
%-------------函数说明----------------
%    距离计算函数
%       输入变量:
%               inputcities:原来的地点顺序和位置
%       输出变量:
%               d:顺序相加的距离和
%---------------------------------------
function fit = Fitness(s,len_side)   %城市距离求和
fit=0;
len=size(len_side,1);
for i = 1:(len-1)
     fit = fit+len_side(s(i),s(i+1));
end
fit = fit + len_side(s(len),s(1)); %相邻两个点的距离
end


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值