原理
模拟退火是寻找最优解的一种算法。
算法描述如下:
它包含两层循环,外层代表着温度的逐渐降低,内层代表在同一温度下的迭代次数。
每次迭代都会产生一个随机的解,如果这个解更优,则接受,否则按照一定 概率
接收。
这个 概率
由
e
−
∣
△
f
∣
t
e^{- \frac{|△f|} {t}}
e−t∣△f∣ 决定,随着温度降低,这个 概率
会越来越小。
例子
下面演示使用此方法求解函数 z = (x-34)^2 + (y-45)^2, 得到最小值时的解。
运行结果:
可以看到,最终通过模拟退火算法得到的解,与真实解[34, 45]已经十分接近。
代码如下:
import numpy as np
import matplotlib.pyplot as plt
#求此函数全局最小值时的解
def func(x, y):
return (x - 34) ** 2 + (y - 45) ** 2
solve = np.array([0, 0]) #初始解
t_max = 200 #最高温度
t_min = 0.01 #最低温度
t_factor = 0.8 #温度变化率
count = 20 #每个温度迭代次数
x, y = np.meshgrid(np.linspace(0, 100, 100), np.linspace(0, 100, 100))
z = func(x, y)
while t_max >= t_min:
for i in range(count):
#生成随机解
delta = np.random.rand() * np.pi * 2
new_arg = solve + (np.log((t_max - t_min) + 1)) * np.array([np.cos(delta), np.sin(delta)] )
delta_z = func(new_arg[0], new_arg[1]) - func(solve[0], solve[1])
#接受新解
if delta_z < 0 or np.random.rand() < np.exp(-(delta_z) / t_max ):
solve = new_arg
#画图
plt.clf()
plt.imshow(z)
plt.scatter(solve[0], solve[1])
plt.scatter(34, 45)
plt.title("t:" + str(t_max) + ", solve: " + str(solve))
plt.pause(0.003)
t_max = t_factor * t_max;