模拟退火算法

Posted sench

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟退火算法相关的知识,希望对你有一定的参考价值。

一、什么是模拟退火算法

1、爬山算法

在了解模拟退火算法之前,先来看一下爬山算法:爬山算法是一种贪心算法,该算法每次从当前的解空间中选取一个解作为最优解,直到达到一个局部最优解。假设函数f(x)的图像如下图:
技术分享图片
现在使用爬山算法来求f(x)的最大值,若C为当前最优解,则爬山算法搜索到A就会停止搜索,这会获得一个局部最优解,而不是全局最优解。

2、模拟退火算法

继续考虑寻找f(x)最大值的问题,爬山算法搜索到A点时就会停止搜索,原因是A点左右的值均小于A点的值。模拟退火算法采用的解决办法是以一定的概率选择A两边的点,尽管A两边的点并不是局部最优解,这样就有一定的概率搜索到D点,从而搜索到B点,最终获得了全局最优解。
上文中的一定概率来自于固体退火原理:当固体温度较高时,物质内能较大,固体内部分子运动剧烈;当温度逐渐降低时,物体内能也随之降低,分子运动趋于平稳;当固体温度降到常温时,固体内部分子运动最终平稳。根据Metropolis准则,粒子在温度T时趋于平衡的概率为e^(-ΔE/(kT)),其中E为温度T时的内能,ΔE为其改变量,k为Boltzmann常数。

二、模拟退火算法流程图

技术分享图片

三、模拟退火算法伪代码

/*
* J(y):在状态y时的评价函数值
* Y(i):表示当前状态
* Y(i+1):表示新的状态
* r: 用于控制降温的快慢
* T: 系统的温度,系统初始应该要处于一个高温的状态
* T_min :温度的下限,若温度T达到T_min,则停止搜索
*/
while( T > T_min )
{
  dE = J( Y(i+1) ) - J( Y(i) ) ; 

  if ( dE >=0 ) //表达移动后得到更优解,则总是接受移动
       Y(i+1) = Y(i) ; //接受从Y(i)到Y(i+1)的移动
  else
  {
       // 函数exp( dE/T )的取值范围是(0,1) ,dE/T越大,则exp( dE/T )也
      if ( exp( dE/T ) > random( 0 , 1 ) )
      Y(i+1) = Y(i) ; //接受从Y(i)到Y(i+1)的移动
  }
  T = r * T ; //降温退火 ,0<r<1 。r越大,降温越慢;r越小,降温越快
  /*
  * 若r过大,则搜索到全局最优解的可能会较高,但搜索的过程也就较长。若r过小,则搜索的过程会很快,但最终可能会达到一个局部最优值
  */
  i ++ ;
}

四、例子

当x∈[-5, 5]时,求函数f(x) = x^4+x^3-x^2-x的最小值。

代码如下(Python版本):

import math
import random

# 起始温度,x的上限
T = 5
# 常温,x的下限
T_MIN = -5
# 迭代次数
k = 100
# 温度的下降率
delta = 0.9

def f(x):
    return x**4 + x**3 - x**2 -x

def saa():
    t = T
    #先产生k个初始解
    px = [random.uniform(-5, 5) for i in range(0, k)]
    while(t>=T_MIN):
        for i in range(len(px)):
            fx = f(i)
            x_next = i + (random.random() * 2 - 1) * t    #计算i周围的函数值
            if x_next>=-5 and x_next<=5:
                fx_next = f(x_next)
                if fx > fx_next:     #找到更小的值则更新
                    px[i] = x_next
                else:
                    p = math.e ** ((fx_next-fx)/T)    #否则按概率更新
                    if p>random.random():
                        px[i] = x_next
        t-=t*delta
        ans = [f(x) for x in px]   #计算f(x)
        return min(ans)   #返回ans的最小值

saa()

输出:

-0.6063902871880511

技术分享图片
由该函数的图像可以看出,该函数在[-5, 5]上的最小值为-0.6左右。

五、参考

1、http://www.cnblogs.com/heaad/archive/2010/12/20/1911614.html
2、https://blog.csdn.net/google19890102/article/details/45395257

以上是关于模拟退火算法的主要内容,如果未能解决你的问题,请参考以下文章

Matlab 模拟退火算法模型代码

遗传算法混合模拟退火算法求解带约束的流水线调度问题matlab代码

C++2018华为软挑:模拟退火+贪心FF解决装箱问题

模拟退火算法

数学建模:模拟退火算法(SA)

Python数模笔记-模拟退火算法求解旅行商问题的联合算子模拟退火算法