模拟退火算法与其python实现(一)

模拟退火算法(SimulatedAnnealing)是基于Monte-Carlo迭代求解策略的一种随机寻优算法,主要用于组合优化问题的求解。

假设现在有这么一个函数:

现要求其在[0,100]范围内的最小值,如果不求导计算,可能第一反应都是穷举法,把范围内每个值都算一遍再比较大小。如果求的是整数范围,那么要算100遍,但是如果要精确到小数后8位,则要算10000000000次,即便使用计算机依然是一个庞大的运算过程。而优化问题中很多都类似于问题,无法用穷举法解出答案,我们叫这类问题为NP难问题(可查看维基百科:NP-hard),于是,有人提出了爬山法

模拟退火算法与其python实现(一)_第1张图片

但是这个方法的缺点在于最优解的产生依赖于最初值的选取,无法解决非凸函数,即容易收敛于局部最优解:

模拟退火算法与其python实现(一)_第2张图片

同时,也无法解决有平台的函数:

模拟退火算法与其python实现(一)_第3张图片

于是,Kirkpatrick等提出了模拟退火算法,它是一种启发式搜索算法,即按照预定的控制策略进行搜索,在搜索过程中获取的中间信息将用来改进控制策略


1.模拟退火算法的原理

1.1概念

模拟退火算法的思想借鉴于固体的退火原理,当固体的温度很高的时候,内能比较大,固体的内部粒子处于快速无序运动,当温度慢慢降低的过程中,固体的内能减小,粒子的慢慢趋于有序,最终,当固体处于常温时,内能达到最小,此时,粒子最为稳定。模拟退火算法便是基于这样的原理设计而成。

模拟退火算法从某一高温出发,在高温状态下计算初始解,然后以预设的邻域函数产生一个扰动量,从而得到新的状态,即模拟粒子的无序运动,比较新旧状态下的能量,即目标函数的解。如果新状态的能量小于旧状态,则状态发生转化;如果新状态的能量大于旧状态,则以一定的概率准则发生转化。当状态稳定后,便可以看作达到了当前状态的最优解,便可以开始降温,在下一个温度继续迭代,最终达到低温的稳定状态,便得到了模拟退火算法产生的结果。

 

1.2状态空间与邻域函数

状态空间也称为搜索空间,它由经过编码的可行解的集合所组成。而邻域函数应尽可能满足产生的候选解遍布全部状态空间。其通常由产生候选解的方式和候选解产生的概率分布组成。候选解一般按照某一概率密度函数对解空间进行随机采样获得,而概率分布可以为均匀分布、正态分布、指数分布等。

 

1.3状态转移概率(Metropolis准则)

状态转移概率是指从一个状态转换成另一个状态的概率,模拟退火算法中一般采用Metropolis准则,具体如下:

模拟退火算法与其python实现(一)_第4张图片

其与当前温度参数T有关,随温度的下降而减小。

 

1.4冷却进度表

冷却进度表是指从某一高温状态T向低温状态冷却时的降温函数,设时刻的温度为T(t),则经典模拟退火算法的降温方式为:

而快速模拟退火算法的降温方式为:

另外还有几种常用的降温函数个人感觉大同小异,就不过多介绍了。

 

1.5初始温度

一般来说,初始温度越大,获得高质量解的几率越大,但是花费的时间也会随之增加,因此,初温的确定应该同时考虑计算效率与优化质量,常用的方法包括:

(1)均匀抽样一组状态,以各状态目标值的方差为初温。

(2)随机产生一组状态,确定亮亮状态间的最大目标值差,然后根据差值,利用一定的函数确定初温,如:

其中Pr为初始接受概率。

(3)根据经验公式给出

 

1.6循环终止准则

内循环终止准则:

(1)检验目标函数的均值是否稳定

(2)连续若干步的目标值变化较小

(3)按一定的步数进行抽样

外循环终止准则

(1)设置终止温度

(2)设置外循环迭代次数

(3)算法搜索到的最优值连续若干步保持不变

(4)检验系统熵是否稳定

 

Python实现过程:

下面便通过python求解开头提到的问题,首先定义函数,然后通过pyplot看看函数在[0,100]上的大致图像:

from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
import math

#define aim function
def aimFunction(x):
    y=x**3-60*x**2-4*x+6
    return y
x=[i/10 for i in range(1000)]
y=[0 for i in range(1000)]
for i in range(1000):
    y[i]=aimFunction(x[i])

plt.plot(x,y)

模拟退火算法与其python实现(一)_第5张图片

可以看到最小值大概在40左右,通过求导计算得到最小值为40.033。

接下来便构造SA模型:

定义初温、低温阈值并通过随机得到初始x,同时定义时刻t。通过均匀分布构造邻域函数,同时设定内循环次数为50次,降温函数使用

代码实现如下:

T=1000 #initiate temperature
Tmin=10 #minimum value of terperature
x=np.random.uniform(low=0,high=100)#initiate x
k=50 #times of internal circulation 
y=0#initiate result
t=0#time
while T>=Tmin:
    for i in range(k):
        #calculate y
        y=aimFunction(x)
        #generate a new x in the neighboorhood of x by transform function
        xNew=x+np.random.uniform(low=-0.055,high=0.055)*T
        if (0<=xNew and xNew<=100):
            yNew=aimFunction(xNew)
            if yNew-y<0:
                x=xNew
            else:
                #metropolis principle
                p=math.exp(-(yNew-y)/T)
                r=np.random.uniform(low=0,high=1)
                if r

经过循环输出x与y,结果如下:

多次运行:




可以看到SA算法很好的逼近了最优解。


Reference:

优化算法——模拟退火算法

你可能感兴趣的:(智能算法)