模拟退火算法(Simulate Anneal,SA)
求全局最小点。
每次随机出一个新解。如果这个解更优,则采纳它;否则以一定概率采纳它。
设这个新的解与上一个解的差为ΔE,温度为T,k 为一个随机数,离子趋于平衡的概率(即可采纳的概率)为:
\[P_k=e^{-\frac{\Delta E}{kT}}
\]
可见,ΔE/kT越小,温度T越高(此时的迭代次数越少),k越大(人工设置,影响较差解的采纳概率),ΔE越小(这个较差解与上一个解的差越小),被采纳的概率也就越大。
ΔE<0,新解更小,采纳它;否则,从(0,1)中随机一个数R,若R<P\(_k\),则采纳它。
(这个图是求最大)
求函数在[0,9]之间的最大值:
import math
import random
def y(x): # 函数y即能量E
return x + 10 * math.sin(5 * x) + 7 * math.cos(4 * x)
def is_acceptable(delta_E,tmp,k=1): # 是否可采纳
if delta_E<0: # ΔE<0,直接采纳
return True
p=math.exp(-delta_E/(k*tmp)) # 求概率
if random.random()<p:
return True
else:
return False
left = 0 # 左边界
right = 9 # 右边界
tmp = math.e**5 # 初始温度
tmp_min = math.e**-3 # 停止温度
alpha = 0.98 # 降温系数
x_old = left + random.random() * (right-left) # 生成初始随机解
E_old = y(x_old)
counter = 0 # 生成更差解的次数
while tmp > tmp_min:
t = (random.random() - 0.5) * 3 # 生成随机解
x_new= x_old + t
if x_new<left or x_new>right:
x_new = x_new - 2*t
E_new = y(x_new)
delta_E = -(E_new - E_old)
if is_acceptable(delta_E,tmp): # 可采纳
x_old = x_new
E_old = E_new
if delta_E<0: # ΔE<0,生成更优解,降温
tmp = tmp * alpha
else:
counter += 1
if counter > 10000:
break
print('y(' + str(x_old) + ') = ' + str(E_old))
TSP问题:
import math
import random
#############################################
def get_all_dist(): # 每两个城市间的距离
for i in range(len(cities)):
for j in range(i,len(cities)):
d[(i,j)] = d[(j,i)] = math.sqrt((cities[i][0]-cities[j][0])**2 + (cities[i][1]-cities[j][1])**2)
def create_new_route(a): # 产生新路径
i = random.randint(0,len(a)-1)
j = random.randint(0,len(a)-1)
a[i],a[j] = a[j],a[i]
def get_route_dist(a): # 路径长度即能量E
dist = 0
for i in range(len(a)-1):
dist += d[(a[i],a[i+1])]
return dist
def is_acceptable(delta_E,tmp,k=1): # 是否可采纳
if delta_E<0: # ΔE<0,直接采纳
return True
p=math.exp(-delta_E/(k*tmp)) # 求概率
if random.random()<p:
return True
else:
return False
#############################################
# 城市坐标
cities = [[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 = dict() # 每两个城市间的距离
get_all_dist()
route_old = list(range(len(cities))) # 初始路径
E_old = get_route_dist(route_old) # 初始路径长度
tmp = math.exp(3) # 初始温度
tmp_min = math.exp(-8) # 停止温度
alpha = 0.98 # 降温系数
counter = 0 # 生成更差解的次数
#############################################
while tmp > tmp_min:
route_new = route_old
create_new_route(route_new) # 生成随机解
E_new = get_route_dist(route_new)
delta_E = E_new - E_old
if is_acceptable(delta_E,tmp): # 可采纳
route_old = route_new
E_old = E_new
if delta_E<0: # ΔE<0,生成更优解,降温
tmp = tmp * alpha
else:
counter += 1
if counter > 10000:
break
print(route_old)
print(E_old)
参考:
posted on 2020-03-11 17:20 HolaWorld 阅读(1123) 评论(0) 编辑 收藏 举报