1、爬山算法
爬山算法是一種非常簡單的貪心算法,它總是從當前解的鄰近解中選擇最優解作爲當前解,直到達到局部最優解。爬山算法的算法過程如下圖所示:
假設當前解從C點開始,經過若干次的鄰近最優解搜索,到達了局部最優解A,此時A的鄰近解中沒有比當前解更優的,因此爬山算法到此結束,返回的最優解A。很明顯,最優解應該是B點處的解,這便是爬山算法最大的弊端:極容易陷入局部最優。
2、模擬退火算法
由爬山算法可以得到一定的啓發:如果在達到局部最優解時,程序能跳出局部最優,那就有極大的可能尋找到全局最優解。
模擬退火算法就是基於上述的思想,如果新解比當前解要差,那麼就以一定的概率接受這個新解,這樣就有可能跳出局部最優從而達到全局最優。以圖1爲例,當到達局部最優A點時,程序會以一定的概率移動到E點,再以一定的概率移動到D點,從而極有可能到達全局最優點B點。
模擬退火算法的步驟如下:
- 定義四個參數值:初始溫度T,每個溫度t的迭代次數L,溫度衰退係數Dec(小於1),最低溫度T_END
- 初始解狀態S
- 在溫度t下迭代步驟(4)至(6)L次
- 產生新的解S’
- 計算新解的效果值dX = f(S’) - f(S),其中f爲結果值的計算函數。
- 如果dX<0,表示新解S’更優,則接受新解作爲當前解,否則以概率exp(-dX/t)接受新解S’作爲當前解
- 溫度衰退,t = t * Dec
- 如果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揹包問題、圖着色問題等等。在實際應用中,主要需要控制以下三個參數,兼顧搜索空間與搜索效率的平衡:
- 初始溫度值T。溫度T的設置是影響退火算法全局搜索性能的重要因素。初始溫度高,則搜索到全局最優解的可能性大,但要耗費較長的計算時間。
- 每個溫度t下的迭代次數L,影響退火速度。同一溫度下充分的搜索空間也是相當必要的,但是同時需要考慮到,L越大帶來的計算時間消耗也就越多。
- 溫度衰退問題。在實際應用中,一般採用公式t = t * dec進行溫度衰退,dec小於1,並且最好接近1,且一般爲0.98或0.95,爲了保證較大的解空間。
參考鏈接:
https://www.cnblogs.com/sench/p/9427193.html
https://www.jianshu.com/p/f04fe7b58080