模擬退火算法介紹-代碼實現

1、爬山算法

爬山算法是一種非常簡單的貪心算法,它總是從當前解的鄰近解中選擇最優解作爲當前解,直到達到局部最優解。爬山算法的算法過程如下圖所示:

假設當前解從C點開始,經過若干次的鄰近最優解搜索,到達了局部最優解A,此時A的鄰近解中沒有比當前解更優的,因此爬山算法到此結束,返回的最優解A。很明顯,最優解應該是B點處的解,這便是爬山算法最大的弊端:極容易陷入局部最優。

2、模擬退火算法

由爬山算法可以得到一定的啓發:如果在達到局部最優解時,程序能跳出局部最優,那就有極大的可能尋找到全局最優解。

模擬退火算法就是基於上述的思想,如果新解比當前解要差,那麼就以一定的概率接受這個新解,這樣就有可能跳出局部最優從而達到全局最優。以圖1爲例,當到達局部最優A點時,程序會以一定的概率移動到E點,再以一定的概率移動到D點,從而極有可能到達全局最優點B點。

模擬退火算法的步驟如下:

  1. 定義四個參數值:初始溫度T,每個溫度t的迭代次數L,溫度衰退係數Dec(小於1),最低溫度T_END
  2. 初始解狀態S
  3. 在溫度t下迭代步驟(4)至(6)L次
  4. 產生新的解S’
  5. 計算新解的效果值dX = f(S’) - f(S),其中f爲結果值的計算函數。
  6. 如果dX<0,表示新解S’更優,則接受新解作爲當前解,否則以概率exp(-dX/t)接受新解S’作爲當前解
  7. 溫度衰退,t = t * Dec
  8. 如果t>T_END,返回步驟3,否則程序終止,得到最終解。

模擬退火算法的流程圖如下所示:

3、模擬退火算法解決旅行商問題的實現 

# -*- coding:utf-8 -*-
import math
import time
import random

# 初始溫度值
T = 5000
# 結束溫度值
T_end = 1e-8
# 在當前溫度下的循環次數
L = 100
# 溫度衰退係數
delta = 0.98

# 31個城市的座標
citys = [[1304,2312],[3639,1315],[4177,2244],[3712,1399],[3488,1535],[3326,1556],[3238,1229],[4196,1004],[4312,790],[4386,570],[3007,1970],[2562,1756],[2788,1491],[2381,1676],[1332,695],[3715,1678],[3918,2179],[4061,2370],[3780,2212],[3676,2578],[4029,2838],[4263,2931],[3429,1908],[3507,2367],[3394,2643],[3439,3201],[2935,3240],[3140,3550],[2545,2357],[2778,2826],[2370,2975]]

# 存儲城市間的距離
d = [[0 for i in range(31)] for j in range(31)]

# 最終的路徑
ansPath = []


def getTwoCityDistance(i , j):
   return math.sqrt((citys[i][0]-citys[j][0])**2 + (citys[i][1]-citys[j][1])**2)

def calcCityDistance():
    n = len(citys)
    for i in range(n):
        for j in range(i , n):
            d[i][j] = d[j][i] = getTwoCityDistance(i, j)

def getNewPath(oldPath):
    i = random.randint(0, len(oldPath)-1)
    j = random.randint(0, len(oldPath)-1)

    oldPath[i], oldPath[j] = oldPath[j], oldPath[i]
    return oldPath

def getPathDistance(path):
    dist = 0
    for i in range(len(path)-1):
        dist += d[path[i]][path[i+1]]
    return dist

# 是否採納當前解
#   1、新值比舊值小
#   2、概率採納
def metropolis(dOld, dNew, t):
    de = dNew - dOld
    if de<0:
        return True
    if (math.e**(-de/t)>random.random()):
        return True
    return False

def Saa():

    delCnt = 0
    calcCityDistance()

    ansPath = range(0, len(citys))

    t = T
    result = 0
    while t >= T_end:
        for i in range(0, L):
            newPath = getNewPath(ansPath)
            dNew = getPathDistance(newPath)
            dOld = getPathDistance(ansPath)
            result = dOld
            if (metropolis(dOld, dNew, t)==True):
                result = dNew
                ansPath = newPath
        t *= delta
        delCnt+=1

    print("Path:")
    print(ansPath)

    print("PathDistance:")
    print(result)

    print("CoolDown Time:")
    print(delCnt)

start = time.time()

Saa()

end = time.time()

print("Cost Time= %d s" % (end-start))

4、模擬退火算法的應用

模擬退火算法的應用很廣泛,可以高效求解NP問題,如旅行者問題(TSP)、0-1揹包問題、圖着色問題等等。在實際應用中,主要需要控制以下三個參數,兼顧搜索空間與搜索效率的平衡:

  1. 初始溫度值T。溫度T的設置是影響退火算法全局搜索性能的重要因素。初始溫度高,則搜索到全局最優解的可能性大,但要耗費較長的計算時間。
  2. 每個溫度t下的迭代次數L,影響退火速度。同一溫度下充分的搜索空間也是相當必要的,但是同時需要考慮到,L越大帶來的計算時間消耗也就越多。
  3. 溫度衰退問題。在實際應用中,一般採用公式t = t * dec進行溫度衰退,dec小於1,並且最好接近1,且一般爲0.98或0.95,爲了保證較大的解空間。

 

參考鏈接:

https://www.cnblogs.com/sench/p/9427193.html

https://www.jianshu.com/p/f04fe7b58080

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章