建模算法入门笔记-模拟退火(SA)(附程序)
RickyWasYoung
2020年02月05日 16:44
收录于文集
共9篇

这两天宅在家里闲着是在是没什么意思,就总结一下以前数模时自己学到的一些算法吧,都是一些非常非常基础的算法,就作为学习笔记总结一下学到的最最干货的东西吧,以后学习科研都能用得上,也希望对各位学弟学妹们有所帮助吧,刚好2020MCM/ICM马上快开始了(今年没有参赛),希望对各位参加建模的同学有所帮助。关于数模的一些其他的干货(建模流程、写作、时间安排等等)我都放到这两个视频里面了,感兴趣的同学可以看一下:av73775318(美赛)、av66218067(国赛/省赛/校赛)。

模拟退火算法(SA)

说算法之前先介绍主要用模拟退火解决的问题吧

TSP问题(旅行商问题):如下图所示,每个圈代表一个城市,各城市之间的坐标固定,居民可以通过两城市之间的连线由一个城市去另一个城市。有一个商人从城市1出发,他要走遍其他城市且只经过这些城市一次,最后回到城市1,问他怎么规划路线,可以使他走过的路线最短。

小偷背包问题(0-1背包问题):有一个小偷行窃时发现共10件物品,质量分别为:10,8,5,9,7,4,3,2,5,6(kg),对应价值分别为15,6,10,14,8,9,6,8,3,8(价值单位),但是该小偷只能通过背包带走物品,该背包能承受的最大质量为40kg,问他需要带走那些物品,可以使他的利益最大化。

下面简单总结一下模拟退火的干货(详细介绍请参考教科书与相关论坛):

模拟退火算法模拟的是退火过程(将金属试件加热到一定温度后在另一较低温度下冷却,如果冷却速度足够低,则冷却过程中任一温度下该试件都处于热平衡状态,试件最终会达到热稳定状态,此时试件的内能最低)(应用时将控制参数视为温度,将目标函数值视为内能,控制参数足够大且在循环过程中不断变小,目标函数值不断朝向“最小”的方向变化,直至最终达到稳定为止)。模拟退火算法是一种概率算法(表现在“内能”未达到“最低”而“稳定”时对“新内能”的选取),用以在大空间内寻找最优解,能够求出全局最优解(而不是陷入局部最优,这是梯度下降法求大空间最优解的缺点)。

模拟退火算法的基本步骤简述如下:

1.规定退火开始时的初始温度,随机生成一个初始解(解1)(该初始解是全局的初始解),计算对应的目标函数值(值1)

2.令温度降低,对上一步的全局初始解施加扰动(注意:如何施加扰动是模拟退火算法的关键),得到新解(解2)及新目标函数值(值2)

3.若值2较值1小,则接受解2,作为新的解1,否则以一定概率接受解1,作为新的解1

4.不断迭代上述过程,直至温度不断降到最低

下面给出TSP问题的模拟退火MATLAB程序(题目是2019MCM/ICM的D题,将卢浮宫的逃生点或出入口化成34个点,用优化算法得到各点之间的相对二维坐标,再将负责人遍历各点的问题转化为tsp问题):

已知各点及其二维坐标:(点序号 x坐标 y坐标;)

1     -12.0     -180.0;    2      8.0     -180.0;    3     18.0     -180.0;     4     28.0     -180.0;    5     8.0     -180.0;    6     -12.0     -80.0;     7      8.0     -80.0;    8     18.0    -80.0;    9     28.0    -80.0;     10     8.0    -90.0;    11    -32.0     28.0;    12    -12.0     20.0;     13    -2.0     28.0;    14    8.0       20.0;    15     18.0     20.0;     16     28.0     20.0;    17     28.0     10.0;    18     8.0     0.0;     19     18.0     0.0;    20     28.0     0.0;    21     48.0     20.0;     22     48.0     30.0;    23     -32.0     128.0;    24     -12.0     120.0;     25     8.0     120.0;    26    18.0     120.0;    27    8.0     100.0;     28    28.0     100.0;    29     48.0     130.0;    30     38.0     120.0;     31     8.0     220.0;    32     18.0     220.0;    33    8.0     200.0;     34     38.0     228.0;  

代码如下(参考卓金武编 MATLAB在数学建模中的应用 北航出版社):

clc clear a = 0.99; t0 = 97; tf = 3; t = t0; Markov_length = 10000; coordinates = [ 1     -12.0     -180.0;    2      8.0     -180.0;    3     18.0     -180.0;     4     28.0     -180.0;    5     8.0     -180.0;    6     -12.0     -80.0;     7      8.0     -80.0;    8     18.0    -80.0;    9     28.0    -80.0;     10     8.0    -90.0;    11    -32.0     28.0;    12    -12.0     20.0;     13    -2.0     28.0;    14    8.0       20.0;    15     18.0     20.0;     16     28.0     20.0;    17     28.0     10.0;    18     8.0     0.0;     19     18.0     0.0;    20     28.0     0.0;    21     48.0     20.0;     22     48.0     30.0;    23     -32.0     128.0;    24     -12.0     120.0;     25     8.0     120.0;    26    18.0     120.0;    27    8.0     100.0;     28    28.0     100.0;    29     48.0     130.0;    30     38.0     120.0;     31     8.0     220.0;    32     18.0     220.0;    33    8.0     200.0;     34     38.0     228.0;         ]; coordinates(:,1) = []; amount = size(coordinates,1); dist_matrix = zeros(amount, amount); coor_x_tmp1 = coordinates(:,1) * ones(1,amount); coor_x_tmp2 = coor_x_tmp1'; coor_y_tmp1 = coordinates(:,2) * ones(1,amount); coor_y_tmp2 = coor_y_tmp1'; dist_matrix = sqrt((coor_x_tmp1-coor_x_tmp2).^2 + (coor_y_tmp1-coor_y_tmp2).^2); sol_new = 1:amount; % sol_new是每次产生的新解;sol_current是当前解;sol_best是冷却中的最好解; E_current = inf;E_best = inf;          % E_current是当前解对应的回路距离; % E_new是新解的回路距离; % E_best是最优解的 sol_current = sol_new; sol_best = sol_new;           p = 1; while t>=tf     for r=1:Markov_length% 产生随机扰动         if (rand < 0.5)    % 随机决定是进行两交换还是三交换             % 两交换             ind1 = 0; ind2 = 0;             while (ind1 == ind2)                 ind1 = ceil(rand.*amount);                 ind2 = ceil(rand.*amount);             end                 tmp1 = sol_new(ind1);                 sol_new(ind1) = sol_new(ind2);                 sol_new(ind2) = tmp1;             else             % 三交换             ind1 = 0; ind2 = 0; ind3 = 0;             while (ind1 == ind2) || (ind1 == ind3) || (ind2 == ind3) || (abs(ind1-ind2) == 1)                 ind1 = ceil(rand.*amount);                 ind2 = ceil(rand.*amount);                 ind3 = ceil(rand.*amount);             end             tmp1 = ind1;tmp2 = ind2;tmp3 = ind3;             % 确保ind1 < ind2 < ind3             if (ind1 < ind2) && (ind2 < ind3);             elseif (ind1 < ind3) && (ind3 < ind2)                 ind2 = tmp3;ind3 = tmp2;             elseif (ind2 < ind1) && (ind1 < ind3)                 ind1 = tmp2;ind2 = tmp1;             elseif (ind2 < ind3) && (ind3 < ind1)                 ind1 = tmp2;ind2 = tmp3; ind3 = tmp1;             elseif (ind3 < ind1) && (ind1 < ind2)                 ind1 = tmp3;ind2 = tmp1; ind3 = tmp2;             elseif (ind3 < ind2) && (ind2 < ind1)                 ind1 = tmp3;ind2 = tmp2; ind3 = tmp1;             end                 tmplist1 = sol_new((ind1+1):(ind2-1));             sol_new((ind1+1):(ind1+ind3-ind2+1)) = sol_new((ind2):(ind3));             sol_new((ind1+ind3-ind2+2):ind3) = tmplist1;             end             %检查是否满足约束             % 计算目标函数值(即内能)         E_new = 0;         for i = 1 : (amount-1)             E_new = E_new + ...                 dist_matrix(sol_new(i),sol_new(i+1));         end             % 再算上从最后一个城市到第一个城市的距离         E_new = E_new + dist_matrix(sol_new(amount),sol_new(1));         if E_new < E_current             E_current = E_new;             sol_current = sol_new;             if E_new < E_best                 E_best = E_new;                 sol_best = sol_new;             end         else             if rand < exp(-(E_new-E_current)./t)                 E_current = E_new;                 sol_current = sol_new;             else                     sol_new = sol_current;             end         end     end     t=t.*a;        end     disp('最优解为:')     disp(sol_best)     disp('最短距离:')     disp(E_best)

路线结果:

16 15 14 13 12 11 27 26 25 24 23 33 31 32 34 29 30 28 22 21 9 8 7 10 4 3 2 5 1 6 18 19 20 17

这篇先写到这里,有什么意见或建议可以留言,谢谢大家

参考:卓金武等.MATLAB在数学建模中的应用.北京航空航天大学出版社