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