【智能优化算法】一种关于解决TSP问题的改进模拟退火算法

提示:内附MATLAB代码及实验数据在文章结尾,希望各位看官在看完之后能给出您宝贵的建议,在此先谢谢各位看官!


前言

提示:经典模拟退火算法是一种鲁棒性强、设置参数少、具有较高容错率的智能优化算法。在解决TSP问题时,因为无效代过多,多次求解解的稳定性差而被诟病,以下是我想出的一种解决模拟退火算法解决TSP问题的改进。


提示:以下是本篇文章正文内容

一、经典模拟退火算法解决TSP问题的缺点

1、优化速度慢
	通常算法以初始温度T(通常为 100*n,n为城市个数)开始,
	通过不断迭代使其小于一个很小的数作为算法结束条件。但其也因此导致算法耗时高。
2、无效代过多
	 所谓无效代即结果几乎不变的代(自己定义)。
	(以T>0.001为例)通常经典模拟退火算法的无效代可达到近千代。十分浪费时间。

二、解决方法

	通过对加快算法结束,与提高马尔科夫链长度,改变温度递减速度,
	阶梯式降温,加快算法结束,大幅提高算法速度的同时,提高解的精度,
	使十次百代期望、方差、最值都更加稳定。

1.实验代码与数据

初代版改进代码

%%%此码原例为最初步改进的模拟退火算法解决tsp问题%%
%以下为原例改动后%
close all;
clear;
clc;
tic
C = read_location('dsj32.text');  %%改动
%%%%%%%%%%%%%%%%%%%%%%%%%%
n = size(C,1);
L = 40*ceil(n*0.1);        	%%改动,使马尔科夫链长度随数据传入大小所变化,做到自适应
D = mat_distance(C,n);	%%改动,简化运算
% for gen = 1:10
%     result = zeros(1,100);	%%测试循环
%     for y = 1:100
        K = 0.99;
        %%%%%%%%%%%%%%%%%%%%%%%%%%
        T = 100*n;
%         clear len;
        for i = 1:n
            city(i) =i;         %%改动
        end
        l = 1;
        len(l) = func(city, D, n);  %%改动
%         figure(1);
        %%%%%%%%%%%%%%%%%%%%%%%%%%
        while T > 0.001  
            for i = 1:L
                len1 = func(city, D, n);    %%改动
                p1 = floor(1+n*rand());
                p2 = floor(1+n*rand());
                while p1==p2
                    p1 = floor(1+n*rand());
                    p2 = floor(1+n*rand());
                end
                tmp_city = city;
                tmp = tmp_city(p1);
                tmp_city(p1) = tmp_city(p2);
                tmp_city(p2) = tmp;
                len2 = func(tmp_city, D, n);    %%改动

                delta_e = len2 - len1;
                if delta_e <0
                    city = tmp_city;
                else
                    if exp(-delta_e/T) > rand()
                        city = tmp_city;
                    end
                end
            end
            l = l+1;
            len(l) = func(city,D,n);        %%改动
            T = T*K;
%             for i = 1:n-1
%                 plot([C(city(i),1),C(city(i+1),1)], [C(city(i),2), C(city(i+1),2)], 'bo-');     %%改动
%                 hold on;
%             end
%             plot([C(city(n),1),C(city(1),1)], [C(city(n),2), C(city(1),2)], 'ro-');     %%改动
%             hold off;
%             pause(0.01);
        end
% figure(2);
% plot(len)
% xlabel('迭代次数')
% ylabel('目标函数值')
% title('适应度进化曲线')
min(len)
toc
%     result(y) = min(len);      %纪录实验结果
%     end       %实验结束
%     End_result = [mean(result),median(result),min(result),max(result),std(result)];
%     pFile = fopen('SA_tsp.txt','a+');
%     if ~pFile
%         sprintf('Open_files_error!');
%         return
%     end
%     fprintf(pFile,'%.0f      %.0f      %.0f      %.0f      %.4f \n',End_result(1), End_result(2), End_result(3), End_result(4),  End_result(5));
%     fclose(pFile);
% end
初代改进实验数据

单点扰动 😐 无变速退火 😐 无提前结束判定


实验次数:100 次 / 组 | 位置个数:32


迭代次数: 1400<gen< 1550 | 千代平均用时:0.272s


期望 | 中位数 | 最小值 | 最大值 | 标准差


566173 561349 498613 664315 32937.0719
567024 559306 489836 673330 37308.1659
568564 564743 494002 663386 38425.2259
572630 566098 509389 691034 35376.3587
574995 570499 506533 680560 34439.1190
562617 560192 497545 659842 31493.1453
564005 557556 498730 662859 37184.1595
571313 567119 510284 669393 33314.2090
566368 562717 500297 684307 36246.0635
568557 564762 498730 692183 38245.2470


单点扰动 | 无变速退火 | 无提前结束判定


实验次数:100 次 / 组 | 位置个数:64


迭代次数: 1500<gen< 1600 | 千代平均用时:0.723s


期望 | 中位数 | 最小值 | 最大值 | 标准差


846473 846076 744589 980017 44072.5765
841996 842793 737311 952923 43199.4095
847630 841254 754021 981148 46654.6824
841312 838790 751072 946979 42931.0817
838554 834583 754667 990047 45172.0612
854117 850099 763757 951398 47274.6587
831714 828882 744542 941534 41155.0120
835390 835150 747665 985258 49525.0937
838086 834468 749835 944272 44002.4997
850357 840045 762102 982172 47294.8956


单点扰动 | 无变速退火 | 无提前结束判定


实验次数:100 次 / 组 | 位置个数:128


迭代次数: 1550<gen< 1700 | 千代平均用时:2.27s


期望 | 中位数 | 最小值 | 最大值 | 标准差


1225100 1225461 1100145 1356212 55245.5015
1225893 1218932 1103113 1445951 54925.9379
1214384 1204214 1075619 1403661 57908.2771
1232958 1234479 1117244 1353722 47298.9318
1237550 1238951 1064543 1366085 63151.2416
1219350 1216716 1077357 1375301 61219.1011
1226711 1225557 1081612 1431949 64763.5568
1234622 1224319 1076702 1414355 66330.6193
1229287 1226389 1135880 1374757 48683.7266
1218712 1209982 1124012 1407612 53705.8428


最优版改进代码

close all;
clear;
clc;
tic
C = read_location('dsj32.text');
n = size(C,1);        
L = 40*ceil(n*0.1);
D = mat_distance(C, n);
delay_idx = ceil(n*0.03);
Chaos_idx = ceil(n*0.4); 
%%%%%%%%%%%%%%%%%%%%%%%%%%
% for gen = 1:10
%     result = zeros(1,100);
%     for y = 1:100
        T = 100*n;
        count = 0;
        pan = 1;
        K = 0.99;
        l = 1;
        Iter = 0;
%         clear len;
        record = ones(1,50);
        for i = 1:n
            city(i) = i;
        end
        len(l) = func(city, D, n);
        %%%%%%%%%%%%%%%%%%%%%%%%
        while pan == 1
            for i = 1:L
                len1 = func(city, D, n);
                p1 = floor(1+n*rand());
                p2 = floor(1+n*rand());
                while p1==p2
                    p1 = floor(1+n*rand());
                    p2 = floor(1+n*rand());
                end
                tmp_city = city;
                tmp = tmp_city(p1);
                tmp_city(p1) = tmp_city(p2);
                tmp_city(p2) = tmp; 
                len2 = func(tmp_city, D, n);
                delta_e = len2 - len1;

                if delta_e <0
                    city = tmp_city;
                else
                    if exp(-delta_e/T) > rand() 
                        city = tmp_city;
                    end
                end
            end
            l = l+1;
            len(l) = func(city, D, n);
        %%%%%%变速降温%%%%%%%%% 
            if l >= Chaos_idx
                if count == delay_idx
                    if K> 0.9
                         K = 1 - abs(log(K));  %当以0.99为初值,前179均大于0.9,196197为正负分界位
                    else
                        K=0.9;                %保险选项避免无限制下降
                    end
                    count = 0;
                end
                T = T*K;
                count = count + 1;  
            end
        %%%%%%提前结束判定%%%%%%%
            Iter = Iter + 1;
            record(Iter)=len(l);
            if mod(l,50) == 0 
                Iter = 0;
            end
            if l >100
                if ( record(randi([31,40])) - record(randi([41,50])) == 0 || ...
                        record(randi([1,10])) - record(randi([11,20])) == 0 ) && ...
                        record(randi([1,10])) - record(randi([41,50])) == 0
                        pan = 0;
                end
            end
        end       %一次实验结束
%%%%%%%%%%%%%%%%%%%%%%%%%%
% figure(1);
% plot(len)
% xlabel('迭代次数')
% ylabel('目标函数值')
% title('适应度进化曲线')
min(len)
%         result(y) = min(len);      %纪录实验结果
%     end       %实验结束
%     
%     End_result = [mean(result),median(result),min(result),max(result),std(result)];
%     pFile = fopen('result_tsp_plus_2_32.txt','a+');
%     if ~pFile
%         sprintf('Open_files_error!');
%         return
%     end
%     fprintf(pFile,'%.0f      %.0f      %.0f      %.0f      %.4f \n',End_result(1), End_result(2), End_result(3), End_result(4),  End_result(5));
%     fclose(pFile);
% end
toc
最优版实验数据

单点扰动 😃 有缓速退火:ceil(n*0.03) 😃 有提前结束判定


实验次数:100 次 / 组 | 位置个数:32


迭代次数:150<gen<220 | 千代平均用时: 0.027s


期望 | 中位数 | 最小值 | 最大值 | 标准差


566165 565087 500297 692471 35380.0116
565677 560941 485409 663355 36670.1092
562519 559887 485225 671126 33646.0139
564830 562887 487063 655802 34553.1247
566538 558890 506121 654428 34557.2271
565394 559291 500911 685008 34606.4036
563719 566444 491807 678816 33781.5247
570993 565151 505156 676283 35252.6242
569010 561412 493222 667139 37338.7443
563925 560576 486350 662886 36849.2120


单点扰动 | 有缓速退火:ceil(n*0.03) | 有提前结束判定


实验次数:100 次 / 组 | 位置个数:64


迭代次数:220 <gen< 310 | 千代平均用时:0.122 s


期望 | 中位数 | 最小值 | 最大值 | 标准差


835042 830176 738481 918978 41547.5318
828589 822509 743191 939677 40363.5212
833490 833704 732472 932675 42346.8312
829592 831291 735157 942589 40438.3012
832698 829725 730337 956147 42701.8277
828210 825905 746766 941774 41221.3060
834143 831956 733450 955474 43492.0436
824923 824682 740975 924024 38341.2791
828110 828581 718824 943491 38189.2520
831634 828052 729814 946426 40390.8248


单点扰动 | 有变速退火:ceil(n*0.03) | 有提前结束判定


实验次数:100 次 / 组 | 位置个数:128


迭代次数:330 <gen< 420 | 千代平均用时:0.602 s


期望 | 中位数 | 最小值 | 最大值 | 标准差


1216339 1218170 1116461 1357596 52514.7934
1221005 1221660 1066876 1347514 53025.7216
1215320 1215239 1099742 1376208 53300.8834
1219961 1216238 1083560 1358916 54055.5805
1227963 1228090 1098800 1367395 54136.2007
1223414 1219345 1101338 1383174 62595.5185
1223857 1220346 1089884 1387819 65265.6193
1212248 1210289 1073372 1336598 56157.3665
1218565 1219338 1063221 1317497 49642.5716
1218159 1209786 1100458 1440181 68872.1991

上述代码涉及函数

%%%%% __read_location.m__ %%%%%%
function locat = read_location(filename)
fid = fopen(filename,'rt');
location=[];
tline = fgetl(fid);
if(strcmp(tline,'MEUN'))
    while (~strcmp(tline,'EOF'))
        A=fscanf(fid,'%f',[1,2]);
        location = [location;A];
        tline = fgetl(fid);
    end
end
locat = location;
end

%%%%% __mat_distance.m__ %%%%%%
function  result = mat_distance( C , n )
    result = ones(n);
    for i = 1: n
        for j = 1:n
            if i ~= j
                result(i,j) = ((C(i,1) - C(j,1))^2 + (C(i,2) - C(j,2))^2)^0.5;
            else
                result(i,j) = 0;
            end
            result(j,i) = result(i,j);
        end
    end
end

%%%%% __func.m__ %%%%%%
function len = func( city, D, n )
    len = 0;
    for j = 1 :n-1
        len = len + D(city(j),city(j+1));
    end
    len = len + D(city(1),city(n));
end

上述测试数据

dsj32

MEUN
28058 70693
74614 68741
2826 66276
83233 83319
97828 84797
63439 76839
63813 4398
19627 70191
33379 15374
81791 67499
16282 13501
36401 70047
3670 2143
25166 23313
41081 31055
7377 55288
31030 21879
46027 26224
20125 90107
42338 18912
69218 1550
42144 51698
5040 45702
16277 57404
86309 32481
62854 39211
28531 55151
61319 41596
89588 23657
32067 85014
32141 21366
31385 65488
EOF
%%%%%%%%%%%%%%%%

dsj64

MEUN
28058 70693
74614 68741
2826 66276
83233 83319
97828 84797
63439 76839
63813 4398
19627 70191
33379 15374
81791 67499
16282 13501
36401 70047
3670 2143
25166 23313
41081 31055
7377 55288
31030 21879
46027 26224
20125 90107
42338 18912
69218 1550
42144 51698
5040 45702
16277 57404
86309 32481
62854 39211
28531 55151
61319 41596
89588 23657
32067 85014
32141 21366
31385 65488
56429 87942
39382 63234
78340 97120
97038 46787
45678 1016
97952 46076
7706 51700
98832 62000
72981 7170
49421 22731
60919 75279
95693 83239
25501 39037
66730 9761
12454 28583
41023 1102
43783 53149
47207 80731
39537 72731
23073 98579
5392 64380
73184 15112
16841 63760
92143 84839
1017 91759
45454 93371
92538 63308
73373 46842
12839 22703
53964 82998
57721 58460
10470 18010
EOF
%%%%%%%%%%%%%%%%

dsj128

MEUN
28058 70693
74614 68741
2826 66276
83233 83319
97828 84797
63439 76839
63813 4398
19627 70191
33379 15374
81791 67499
16282 13501
36401 70047
3670 2143
25166 23313
41081 31055
7377 55288
31030 21879
46027 26224
20125 90107
42338 18912
69218 1550
42144 51698
5040 45702
16277 57404
86309 32481
62854 39211
28531 55151
61319 41596
89588 23657
32067 85014
32141 21366
31385 65488
56429 87942
39382 63234
78340 97120
97038 46787
45678 1016
97952 46076
7706 51700
98832 62000
72981 7170
49421 22731
60919 75279
95693 83239
25501 39037
66730 9761
12454 28583
41023 1102
43783 53149
47207 80731
39537 72731
23073 98579
5392 64380
73184 15112
16841 63760
92143 84839
1017 91759
45454 93371
92538 63308
73373 46842
12839 22703
53964 82998
57721 58460
10470 18010
80165 44509
67713 50003
80013 44649
18033 90918
52372 21363
68342 4232
29834 25913
31801 1611
32980 89583
84395 85338
71275 15827
74162 1300
71474 87423
41076 33933
7470 30485
49546 1389
65427 32436
10106 34065
80670 86866
98504 66184
8160 18704
54220 45219
82856 34602
27616 72869
24893 57493
20515 58687
30308 51825
33080 17828
86143 37757
91603 13368
12479 85134
90134 73252
97430 37885
34748 33557
74202 58479
55212 14153
55236 73172
55715 28878
38584 93935
53999 96305
97520 11492
48924 74588
64940 3165
57734 2384
95469 16992
42369 55029
34601 68251
4062 6403
25306 50939
35438 46774
18349 71151
69420 9400
25753 89660
43188 66799
11515 43460
67721 59473
83774 17408
67387 78159
92069 47608
23921 57618
42204 5215
24993 98945
53728 61573
63380 15411
EOF
%%%%%%%%%%%%%%%%


总结

通过改进,在处理相同数量的位置点下,既提高了运算速度,也保证了 解的期望值稳定,也使得解的精度有所提高。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值