一 | 模拟退火图片演示首先为了让各位能够对模拟退火算法有一个直观的视觉冲击,现在我们想要找到下面这幅图的极大值点,很明显这幅图中有许多局部极值点,如果仅仅采用简单的爬山算法很容易陷入局部最优。模拟退火(SA)算法求解旅行商(TSP)问题_java(图片来源:维基百科)这时候我们就想如果在搜索过程中陷入了局部最优,那么我们有没有什么办法从这个局部最优点“逃走”呢?办法总比困难多,既然在搜索过程中已经陷入了局部最优,反正按照常规的思路,陷入局部最优后如果继续进行搜索,基本上找不到比这个局部最优解更好的解如果一直找不到比局部最优解更好的解,(PS:常规的思维是不如这个局部最优解,我们就当前解进行更新),那么很明显最终的搜索结果只能是这个局部最优解
但是,我想各位小伙伴已经注意到了,常规思维是不如这个局部最优解,我们就当前解进行更新。那么我们就不采用常规思维,我们就来点不一样的。我们就尝试着接受一下比局部最优解更差的解作为当前解(PS:当然不是说接受比局部最优解差的太多的解),然后我们就对当前解的邻域进行搜索,一旦在当前解的这个邻域中搜索到一个比局部最优解更好的解,那我们是不是赚了,此时是不是就逃离了局部最优了,这其实就是模拟退火的基本思路。首先来展示一下使用SA求解TSP问题的动图。

二 | 旅行商(TSP)问题

假设有一个旅行商人要拜访n个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。

三 | 算法设计


01 | 模拟退火算法思想模拟退火算法的核心思想就是以一定概率接受比当前解更差的解,然后用这个更差的解继续搜索,其实这个思想很容易理解。


02 | 编码编码采用常规的整数编码,如果城市数目为N,那么解就可以表达为1~N的随机排列,用MATLAB中的randperm(N)进行表示。


03 | 邻域结构


(1)交换结构比如说有6个城市,当前解为123456,我们随机选择两个位置,然后将这两个位置上的元素进行交换
比如说,交换2和5两个位置上的元素,则交换后的解为153426。


(2)逆转结构
有6个城市,当前解为123456,我们随机选择两个位置,然后将这两个位置之间的元素进行逆序排列比如说,逆转2和5之间的所有元素,则逆转后的解为154326。


(3)插入结构
有6个城市,当前解为123456,我们随机选择两个位置,然后将这第一个位置上的元素插入到第二个元素后面。比如说,第一个选择2这个位置,第二个选择5这个位置,则插入后的解为134526。在搜索过程中,我们将以上三种邻域结构赋予不同的权重,然后采用轮盘赌的方式选择究竟使用哪个邻域结构。


04 | 接受准则前面我们说到模拟退火算法的核心思想就是以一定概率接受比当前解更差的解,那么这个概率究竟如何计算呢
比如说当前解Scurr表示,当前解Scurr的某个邻域产生的一个新解Snew表示。用f(Scurr)表示当前解的总距离f(Snew)表示新解的总距离。我用下面这个伪代码表示接受准则。这里需要注意的是T表示当前温度,因为在外层循环中每迭代一次后,温度T都会降低,即温度T需要乘一个小于1冷却因子降低温度,这就体现了“退火”的思想。

if f(Snew)<=f(Scurr)
    Scurr=Snew;
else
    delta=(f(Snew)-f(Scurr))/f(Scurr);
    p=exp(-T/delta);
    if rand<=p

        Scurr=Snew;
    end
end



05 | 模拟退火求解TSP问题流程图

模拟退火(SA)算法求解旅行商(TSP)问题_java_02