模拟退火算法

在实际日常中,人们会经常遇到如下问题:在某个给定的定义域 X X 内,求函数f(x)对应的最优值。此处以最小值问题举例(最大值问题可以等价转化成最小值问题),形式化为:

minxXf(x). min x ∈ X f ( x ) .

如果 X X 是离散有限取值,那么可以通过穷取法获得问题的最优解;如果X连续,但 f(x) f ( x ) 是凸的,那可以通过梯度下降等方法获得最优解;如果 X X 连续且f(x)非凸,虽说根据已有的近似求解法能够找到问题解,可解是否是最优的还有待考量,很多时候若初始值选择的不好,非常容易陷入局部最优值。

这里写图片描述

随着日常业务场景的复杂化,第三种问题经常遇见。如何有效地避免局部最优的困扰?模拟退火算法应运而生。其实模拟退火也算是启发式算法的一种,具体学习的是冶金学中金属加热-冷却的过程。由S.Kirkpatrick, C.D.Gelatt和M.P.Vecchi在1983年所发明的,V.Čern在1985年也独立发明此演算法。

不过模拟退火算法到底是如何模拟金属退火的原理?主要是将热力学的理论套用到统计学上,将搜寻空间内每一点想像成空气内的分子;分子的能量,就是它本身的动能;而搜寻空间内的每一点,也像空气分子一样带有“能量”,以表示该点对命题的合适程度。演算法先以搜寻空间内一个任意点作起始:每一步先选择一个“邻居”,然后再计算从现有位置到达“邻居”的概率。若概率大于给定的阈值,则跳转到“邻居”;若概率较小,则停留在原位置不动。

一、模拟退火算法基本思想

模拟退火其实也是一种贪心算法,但是它的搜索过程引入了随机因素。在迭代更新可行解时,以一定的概率来接受一个比当前解要差的解,因此有可能会跳出这个局部的最优解,达到全局的最优解。以下图为例,假定初始解为左边蓝色点A,模拟退火算法会快速搜索到局部最优解B,但在搜索到局部最优解后,不是就此结束,而是会以一定的概率接受到左边的移动。也许经过几次这样的不是局部最优的移动后会到达全局最优点D,于是就跳出了局部最小值。

这里写图片描述

根据热力学的原理,在温度为 T T 时,出现能量差为dE的降温的概率为 p(dE) p ( d E ) ,表示为:
p(dE)=exp(dEkT). p ( d E ) = exp ⁡ ( d E k T ) .

其中 k k 是波尔兹曼常数,值为k=1.3806488(13)×1023 exp exp 表示自然指数,且 dE<0 d E < 0 。因此 dE/kT<0 d E / k T < 0 ,所以 p(dE) p ( d E ) 函数的取值范围是(0,1)。满足概率密度函数的定义。其实这条公式更直观意思就是:温度越高,出现一次能量差为 p(dE) p ( d E ) 的降温的概率就越大;温度越低,则出现降温的概率就越小。

在实际问题中,这里的“一定的概率”的计算参考了金属冶炼的退火过程。假定当前可行解为 x x ,迭代更新后的解为x_new,那么对应的“能量差”定义为:

Δf=f(x_new)f(x). Δ f = f ( x _ n e w ) − f ( x ) .

其对应的“一定概率”为:
p(Δf)=exp(ΔfkT)exp(ΔfkT) p ( Δ f ) = { exp ⁡ ( − Δ f k T ) 最 小 值 优 化 问 题 exp ⁡ ( Δ f k T ) 最 大 值 优 化 问 题

注:在实际问题中,可以设定 k=1 k = 1 。因为 kT k T 可以等价于一个参数 T T 。如设定k=2 T=1000 T = 1000 ,等于直接设定 T=2000 T = 2000 的效果。

二、模拟退火算法描述

  1. 初始化:初始温度 T T (充分大),温度下限Tmin(充分小),初始解状态 x x (是算法迭代的起点),每个T值的迭代次数 L L
  2. l=1,2,...,L做第3至第6步;
  3. 产生新解 x_new x _ n e w : ( x_new=x+Δx x _ n e w = x + Δ x );
  4. 利计算增量 Δf=f(x_new)f(x) Δ f = f ( x _ n e w ) − f ( x ) ,其中 f(x) f ( x ) 为优化目标;
  5. Δf<0 Δ f < 0 (若寻找最大值, Δf>0 Δ f > 0 )则接受 x_new x _ n e w 作为新的当前解,否则以概率 exp(Δf/(kT)) exp ⁡ ( − Δ f / ( k T ) ) 接受 x_new x _ n e w 作为新的当前解;
  6. 如果满足终止条件则输出当前解作为最优解,结束程序。(终止条件通常取为连续若干个新解都没有被接受时终止算法。);
  7. T T 逐渐减少,且T>Tmin,然后转第2步。

这里写图片描述

三、模拟退火算法的优缺点

模拟退火算法的应用很广泛,可以高效地求解NP完全问题,如货郎担问题(Travelling Salesman Problem,简记为TSP)、最大截问题(Max Cut Problem)、0-1背包问题(Zero One Knapsack Problem)、图着色问题(Graph Colouring Problem)等等,但其参数难以控制,不能保证一次就收敛到最优值,一般需要多次尝试才能获得(大部分情况下还是会陷入局部最优值)。观察模拟退火算法的过程,发现其主要存在如下三个参数问题:

  (1) 温度T的初始值设置问题
  温度 T T 的初始值设置是影响模拟退火算法全局搜索性能的重要因素之一、初始温度高,则搜索到全局最优解的可能性大,但因此要花费大量的计算时间;反之,则可节约计算时间,但全局搜索性能可能受到影响。

  (2) 退火速度问题,即每个T值的迭代次数
  模拟退火算法的全局搜索性能也与退火速度密切相关。一般来说,同一温度下的“充分”搜索是相当必要的,但这也需要计算时间。循环次数增加必定带来计算开销的增大。

  (3) 温度管理问题
  温度管理问题也是模拟退火算法难以处理的问题之一。实际应用中,由于必须考虑计算复杂度的切实可行性等问题,常采用如下所示的降温方式:

T=α×T.α(0,1). T = α × T . α ∈ ( 0 , 1 ) .

注:为了保证较大的搜索空间, α α 一般取接近于1的值,如0.95、0.9。

四、模拟退火算法Python实战

经过上面理论知识的熏陶,相信大家已经对模拟退火算法有了较深入的理解,接下来通过实战再强化一下大家的认识,此处利用模拟退火算法求解如下优化问题:

minf(x)=(x2)(x+3)(x+8)(x9) min f ( x ) = ( x − 2 ) ∗ ( x + 3 ) ∗ ( x + 8 ) ∗ ( x − 9 )

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

def inputfun(x):
    return (x-2)*(x+3)*(x+8)*(x-9)

initT = 1000 #初始温度
minT = 1 #温度下限
iterL = 1000 #每个T值的迭代次数
delta = 0.95 #温度衰减系数
k = 1

initx = 10*(2*np.random.rand()-1)
nowt = initT
print "初始解:",initx

xx = np.linspace(-10,10,300)
yy = inputfun(xx)
plt.figure()
plt.plot(xx,yy)
plt.plot(initx,inputfun(initx),'o')

#模拟退火算法寻找最小值过程
while nowt>minT:
    for i in np.arange(1,iterL,1):
        funVal = inputfun(initx)
        xnew = initx+(2*np.random.rand()-1)
        if xnew>=-10 and xnew<=10:
            funnew = inputfun(xnew)
            res = funnew-funVal
            if res<0:
                initx = xnew
            else:
                p = np.exp(-(res)/(k*nowt))
                if np.random.rand()<p:
                    initx = xnew
#            print initx-xnew
#    print initx
#    print nowt
    nowt = nowt*delta

print "最优解:",initx
print "最优值:",inputfun(initx)
plt.plot(initx,inputfun(initx),'*r')
plt.show()

这里写图片描述

这里写图片描述

可以看到,即使初始解选取的有风险,模拟退火算法经过迭代,也可以成功跳出局部最优值,最终收敛到问题的全局最优。

参考资料

  1. http://wiki.mbalib.com/wiki/模拟退火算法 模拟退火算法
  • 60
    点赞
  • 314
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
JSP(Job Shop Scheduling Problem)是一种经典的调度问题模拟退火算法是一种启发式优化算法。下面是对JSP和模拟退火算的简要介绍: JSP(Job Shop Scheduling Problem)是一种经典的调度问题,它涉及到多个作业(jobs)需要在多个机器上进行加工。每个作业由一系列操作(operations)组成,每个操作需要在特定的机器上完成,并且具有特定的加工时间。目标是找到一个最优的作业顺序和操作分配方案,以最小化总加工时间或最大化生产效率。 模拟退火算法(Simulated Annealing Algorithm)是一种启发式优化算法,灵感来源于固体退火过程。它通过模拟金属退火时的温度变化过程来搜索问题的解空间。算法从一个初始解开始,通过接受劣解的概率来避免陷入局部最优解,逐渐降低温度直到达到终止条件。 在JSP中应用模拟退火算法可以通过以下步骤实现: 1. 定义问题的状态表示:可以使用染色体编码表示作业顺序和操作分配方案。 2. 初始化初始解:随机生成一个初始解。 3. 定义目标函数:根据作业顺序和操作分配方案计算总加工时间。 4. 定义邻域操作:设计一些邻域操作,如交换两个操作的位置或改变作业顺序。 5. 迭代搜索:根据模拟退火算法的原理,通过接受劣解的概率来避免陷入局部最优解,逐渐降低温度并在每个温度下进行邻域搜索。 6. 终止条件:达到一定的迭代次数或满足特定的停止准则时停止搜索。 7. 输出最优解:返回找到的最优解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值