美赛BOOM数学建模5-1模拟退火

注明:本文根据数学建模BOOM网课简单整理,自用

❑模型简介

❑ 模拟退火的“实例”

• 齐白石原是木匠,快30岁才正式学画。直到57岁以后画风开始转变,才真正有所成就

• 鲁迅原学医,25岁弃医从文,但37岁时才写出第一篇白话文小说《狂人日记》

• 项羽24岁巨鹿之战成名,26岁称王却走错了路子,三十出头就……

❑ 模拟退火的基本思想,就是走出舒适圈,多去“试一试”,万一成了呢?

舒适区:当前处于局部最优解(鲁迅那个年代能留学的都是佼佼者)

试一试随机试探新解,有更好的解就直接选新解,没更好的则以一定概率选择新解

万一成了:找到了更优解甚至最优解,青史留名(载入语文/历史课本)

也可能没成:求的新解反而更差了(项羽没有去统一而是封王结果……)

一次没成,多试几次继续随机试探(齐白石也不是转行后立马成名的)

❑贪心算法失效——陷入局部最优

❑ 从爬山说起

• 假如北海想要在日落前爬上一座山的最高峰(求最优解)

• 但山中云雾缭绕、视野受限,只能看到当前位置附近一定范围内的情况

• 贪心算法:在视野内选取一个点,如果更高,就过去;否则就不去

直到视野内没有更高的点,则输出当前解作为最终解(视频中有板书过程)

• 显然,当北海走到某个小山峰时,四周看不到更高的点,就不会走下山去、寻找更高的峰

• 从而陷入了局部最优解

❑ 模拟退火思想

• 那么在可见范围内,随机选择一点

• 1.如果该点比当前位置更高,就直接去该点(优化)

• 2.如果该点更低,那么就多掷几次硬币,结合该点与当前点的高度差决定去不去一定概率

• 在刚才的局部最优解的峰,会有一定概率走下了当前山峰,从而发现另一个山峰的上坡

• 从而就有可能走上新的更高峰

❑ 算法关键点

• 时间有限,需设置终止条件(“退火”过程中温度不断降低,剩余时间不多时就别乱跑

• 且算法需要做到:若当前所处的山峰越高,前往低点的概率越低(概率的表达式

• 这样才能使求得最优解的概率更大

• 关键在于,“概率”怎么求

❑适用赛题

❑ 可行解过多、 NP-hard问题

❑ NP-hard问题

• 旅行推销员问题(Travelling salesman problem, TSP):给定一系列城市和每对城市之间的距离,求解访问每一座城市一次回到起始城市的最短回路

• TSP问题是组合优化中的一个NP-hard问题,该问题的可行解是所有顶点的全排列,随着顶点数的增加,会产生组合爆炸,传统算法难以求解

• 此时就适合用模拟退火等启发式算法求近似解

❑ 适用赛题特点

• 有些规划类问题的可行解过多,传统算法运算时间过长

• 能够列出可行解的任一排列(例如题目要求最短回路,起码能先写出个回路作为初始化)

❑ 国赛题目:高等教育学费标准

• 假设高校所需1000万经费,涉及多种筹款路径,理论上的筹款组合方案过多,若暴力求解可能费时几十小时,此时就适合模拟退火求解

❑典型例题

❑ 遍历全国省会

• 已知全国34个省会城市(包括直辖市、自治区首府和港澳台)的经纬度坐标(第一个为北京)

• 现在需要从北京出发,到所有城市视察

• 要求每个城市只能到达一次,并最终回到北京

• 求视察路线方案,使得总路径最短

❑ 问题分析

• 若把所有可能的路线方案都列出来再求最小值,则有33!(33的阶乘)种方案

• 这是1036数量级,运算时间会很长

• 此时可考虑使用模拟退火

• 本期课程的原理讲解内容对于部分同学来说较难理解,应结合代码理解

❑原理与求解思路

❑ 所有可行解

• 本题的解空间就是固定起点和终点的所有可行路线的集合

• 题目要求以北京作为起点和终点,那么设起点北京为1号城市𝑥1

• 余下需要遍历的33个城市依次设为2,3,……,34号城市𝑥34

• 最后还需回到北京,设终点北京为35号城市𝑥35

• 因为起点与终点固定,则共有33!个可行解

❑ 目标函数:总路程最短

• 从1号𝑥1出发遍历34个城市最后回到1号𝑥35

• 第𝑖号城市𝑥𝑖与第𝑖 + 1号城市𝑥𝑖+1之间的路径长度设为𝑑𝑥𝑖𝑥𝑖+1

• 则目标函数:

❑ 1、初始化

• 设定一个初始温度𝑇0和问题的一个初始解𝑥(0)

• 有那么多种可行解,可以随便选一个作为初始解

• 例如本题,可以把原始数据的排列直接作为初始解,解为𝑥1𝑥2 𝑥3…… 𝑥35

• 或利用蒙特卡罗法求一个较好的初始解(课程第四部分代码求解会讲)

❑ 2、随机产生新解

• 在当前温度𝑇𝑖下随机求一个解𝑥′,制定产生新解的准则(准则不唯一,能确保随机即可)

• 假设上一步的解为:

随机选序号𝑢, 𝑣,将𝑢到𝑣的这部分转为逆序,得到解:

❑ 3、计算目标函数差值

• 随机得到的解𝑥′和当前解𝑥(𝑖),两种方案总路径的差值记为𝛥𝑓 :

❑ 4、是否接受新解

• 接受准则:

• 表达式中判断准则𝑒𝑥𝑝( − 𝛥𝑓/𝑇𝑖)是由热力学得到的灵感,后面补充讲解

• 题目求总路径最短,如果𝛥𝑓 < 0意味解𝑥′的总路径更短,则接受𝑥′作为新解, 𝑥(𝑖)= 𝑥′

• 𝛥𝑓 > 0意味解𝑥′总路径更长不如原解𝑥(𝑖),但为防止陷入局部最优解,仍以一定概率接受𝑥′

• 在代码实现上,if 𝑒𝑥𝑝( − 𝛥𝑓/𝑇𝑖) ≥ rand 则接受𝑥′作为新解,否则保留解𝑥(𝑖)

• 显然, 𝛥𝑓越小,意味着p越大,那么接受𝑥′的概率就更大

❑ 5、马尔科夫过程

• 在当前温度T𝑖下,重复2、3、4步

• 温度Ti不变时,判断准则中的e𝑥𝑝( −𝛥𝑓/𝑇i) 由𝛥𝑓 决定,而𝛥𝑓 由随机解x′和当前解x(𝑖)决定

所以新解x(i+1)只与𝑥(i)有关,而与更早的x(i-1),x(i-2)...x(0)无关

• 显然这是个马尔科夫过程,x′在原解x(𝑖)的邻域中符合均匀分布*

❑ 6、退火过程

• 选定降温系数𝛼,求得新温度T𝑖+1 = 𝛼𝑇𝑖,此处设为0.999

• 再重复2、3、4、5步;然后继续降低温度……

❑ 7、结束条件

• 直到温度足够小,设终止温度为e = 10^−30,当𝑇 < 𝑒时终止迭代,输出最终解

• 退火过程足够慢、每个温度下寻找新解的次数足够多,则最终解是全局最优解的概率越大*

❑ *理论上模拟退火可以找到全局最优(该部分不要求掌握)

马尔科夫过程随机解𝑥′只与x(i)有关,所以x'在原解x(𝑖)的邻域中符合均匀分布

• 而x′被接受的状态由上页的概率表达式p 所决定

• 那么经过有限次的重复2、3、4步,在温度Ti下解的平衡态x𝑖满足玻尔兹曼分布

• 平衡态Xi代表温度Ti下任意一种可能出现的解,S为所有可能出现的解的集合

• 式中f(i)代表该解下的总路径(目标函数值)

• 接着降低温度𝑇𝑖+1< T𝑖,在温度𝑇𝑖+1下有限次的重复2、3、4步

• 整个优化过程就是不断寻找新解和缓慢降温的交替过程,那么温度趋于0时得到最终解

重点在于,温度趋于0时得到的最终解,是不是接近于全局最优解?

• 上一页提到,温度𝑇𝑖 下解的平衡态𝑥𝑖 满足玻尔兹曼分布,根据玻尔兹曼分布和状态转移概率:(热力学统计物理,背景概念很多,此处只给结论)

• 从玻尔兹曼分布可知,温度T → 0时某个值大于0的状态(函数值)f(𝑥𝑖)的分布概率趋于0

• 也就意味着只有f(𝑥𝑖)尽可能趋于0的状态才会存在

对应现实问题,求得的最终解中只有fmin,也就是最优解(本题的最短路径)

• 从状态转移概率公式可知,当温度𝑇 → 0, 𝛥𝑓 ≥ 0时转移到更高函数值的概率趋近于0

也就意味着温度极低时,转移到更差解的概率越小、会以更大概率停留在当前解

• 结论:当寻找新解次数足够多、降低温度足够慢,最终会以接近于1的概率求得全局最优解

• 证明:根据玻尔兹曼分布和状态转移概率,求最终从一个极低的温度转移到𝑇 = 0后的概率

分布,结合两个公式可得:

❑代码求解

• 重点在于,如何在代码中实现课程第三部分原理讲解中的各种计算

• 求解结果每次都不一样

已知全国34个省会城市(包括直辖市、自治区首府和港澳台)的经纬度坐标(第一个为北京);现在需要从北京出发,到所有城市视察,要求每个城市只能到达一次,并最终回到北京。求视察路线方案,使得总路径最短。

1、导入数据

因为题目提供的数据是经纬度,注意第一列是经度、第二列是纬度,写函数时不要写错了

求两个城市间距离,是求在地球上的弧线长度,也就是求一个扇形的弧长

可使用distance函数求球体上两点间距离

d(i,j) = distance(lat1,lon1,lat2,lon2,radius);其中lat1、lon1是第一个点的纬度和经度,lat2,lon2是第二个点的纬度和经度,radius是球体的半径

clc, clear, close all
%数据在文件cities.xlsx中,注意要放在与本文件同一文件夹下
city = table2array(readtable('citys.xlsx','Range','B2:C35')); %table2array改变数据类型
n = size(city,1);      %城市距离初始化                                                                    
d = zeros(n,n+1);      %35号只会作为终点          
for i = 1:n
    for j = 1:n
            d(i,j)= distance(city(i,2),city(i,1),city(j,2),city(j,1),6371); % distance求圆心角的角度.第一个点的纬度、第一个点的经度
    end    
end
%各城市到35号即北京的距离作为第35列
for i=1:n
    d(i,35)= distance(city(i,2),city(i,1),city(1,2),city(1,1),6371);
end

2、蒙特卡罗法求初始解

之前讲过蒙特卡罗法。本题总共34个城市,从1号城市北京出发,遍历完所有34个城市后,返回北京,设返回的北京为第35号。

每次随机选一种路径方案,出北京外的其他33个城市,利用randperm(33)为33个从1到33的整数随机排列;那么1+randperm(33)就是2到34的整数随机排列。

path=[];
lenth=inf; %总路径及长度初始化,inf正无穷
for j=1:1000  %求较好的初始解,随机求1000种方案,挑出最好的作为初始方案
    temp_path=[1 1+randperm(33) 35];    % 当前解(方案)
    temp_lenth=0;   % 当前方案的总路径
    % 求该方案下总路径长度temp_lenth
    for i=1:34
        temp_lenth=temp_lenth+d(temp_path(i),temp_path(i+1));
    end
    % 如果该方案下总路径长度temp小于所记录的当前最短总路径长度long(初始为正无穷)
    if temp_lenth<lenth
        path=temp_path; lenth=temp_lenth;      % 将该路径方案temp_path记为最短路径方案path,将该方案的长度temp_lenth记为最短路径长度lenth
    end
    % 如此循环1000次,就从1000个随机方案里挑选出最优的方案作为初始方案,用于后面的模拟退火
end

3、模拟退火

while循环实现温度不断降低,温度初试为1,每次新的温度是之前的0.999倍;当温度低于10^(-30)时终止循环。

while循环内嵌套for循环,实现固定温度下的马尔科夫过程,即不断求新解、并判断是否接受。

判断是否接受新解,就是代码中的if和elseif两种情况

e=0.1^30;alpha=0.999;T=1000;markov=1000;   %这些参数都是可以改的
% for k=1:L  %退火过程
accept=0;rand_accept=0;refuse=0;
tic
while T>e
    for t=1:markov
        %新解随机选序号𝑢, 𝑣,将𝑢到𝑣的这部分转为逆序作为新解
        c=2+floor(33*rand(1,2));  %产生新解;floor向下取整,得到两个2到34的随机整数,(1,2)一行两列
        c=sort(c);  %随机选的两个点升序排序,用于接下来计算
        u=c(1);v=c(2);  %模型中的随机选的两个点u和v,u是序号小的那一个
        %计算目标函数值的增量
        df=d(path(u-1),path(v))+d(path(u),path(v+1))-...
            d(path(u-1),path(u))-d(path(v),path(v+1));
        if df<0 %接受准则
            path=[path(1:u-1),path(v:-1:u),path(v+1:35)]; %新路径u到v逆序
            lenth=lenth+df; 
            accept=accept+1;
        elseif exp(-df/T)>=rand   %rand产生0到1的随机数;不等号左边与温度T有关
            path=[path(1:u-1),path(v:-1:u),path(v+1:35)]; 
            lenth=lenth+df;
            rand_accept=rand_accept+1;
        else
            refuse=refuse+1;
        end
    end
toc
    T=T*alpha;
end
path(35)=1;     % 1号和35号都是北京,把35改成1,方便画图
plot(city(path ,1), city(path ,2),'o-');
    disp('最短路程:')
    disp(lenth)
    disp('直接接受新解次数:')
    disp(accept)
    disp('接受更差的随机解次数:')
    disp(rand_accept)
    disp('不接受随机解次数:')
    disp(refuse)    
for i = 1:n
    %对每个城市进行标号
    text(city(i,1),city(i,2),['   ' num2str(i)]); %number to string
end
xlabel('东经')
ylabel('北纬')
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值