1. 程式人生 > >模擬退火演算法(Simulated Annealing)python的簡單實現

模擬退火演算法(Simulated Annealing)python的簡單實現

1 模擬退火演算法簡介

           模擬退火演算法是一種啟發式演算法。 通過不斷的迭代當前解在周圍找到問題的最優解。( 個人理解是在簡單的爬坡法加上了概率的因素,防止陷入區域性最優解。)     完整的模擬退火過程是模擬熱力學的退火過程,隨著溫度的不斷下降(本質上是隨著迭代次數的增多,發生跳轉的概率越來越小的過程),演算法將在多項式的時間內找到問題的近似全域性最優解(有可能還是區域性最優解)。

2  演算法流程

  1. 初始化溫度 T 和每個 T = t_{i} 時,進行迭代次數的L, 時間衰減率\eta, 初始化一個解 x_{0} ;
  2.  while $ $ $ $t>MinT
  3.     for$ $ $ $ $ $ l=1:L
  4.            計算函式值 value\_old = f(x\_old)
  5.            在 x\_old
    周圍隨機試探產生新的x\_newx\_new = x\_old + (random()-0.5)
  6.            value\_new = f(x\_new)value\_old作比較
  7.           if   value\_newvalue\_old更接近目標函式值
  8.                  x\_old = x\_new
  9.          else
  10.                以一定的概率接受x\_new, 條件式$\exp(-(value\_new-value\_old)/k*t)$ > random()
  11.   t = t * \eta

這裡面與爬坡法最大的區別是在演算法步驟10中, 當不滿足爬坡條件的時候,仍然以一定的概率接受接受到新值;當溫度較高的時候概率越大,也就更容易跳出區域性極值點,而隨著溫度慢慢下降,慢慢的也收斂到全域性極值點。

3 python程式碼實現

import numpy as np
import matplotlib.pyplot as plt
import math
def function(x):
    return -(10*math.sin(5*x)+7*math.cos(4*x))

initT = 1000
minT = 1
iterL = 1000
eta = 0.95
k = 1

x0 = 1.5#10*(2*np.random.rand()-1)

t = initT
print("init solution :",x0)
yy=[]
xx = np.linspace(0,10,300)
for i in range(len(xx)):
    yy.append(function(xx[i]))
plt.figure()
plt.plot(xx,yy)
plt.plot(x0,function(x0),'o')

x_old = x0
while t > minT:
    for i in range(iterL):#MonteCarlo method reject propblity
        value_old = function(x_old)
        x_new = x_old+np.random.rand()-0.5
        if x_new>=0 and x_new<=10:
            value_new = function(x_new)
            res = value_new-value_old
            if res<0 or np.exp(-res/(k*t))>np.random.rand():
                x_old = x_new
    t = t*eta

print("最優解: ",x_old)
print("最優值:",function(x_old))
plt.plot(x_old,function(x_old),'or')
plt.show()