模拟退火(Simulated Annealing,SA)是一种全局优化算法,它用于寻找给定问题的近似全局最优解。算法受到物理中固体退火过程的启发,物质在高温下具有较高的能量状态,随着温度的缓慢降低,物质的内部结构会逐渐稳定在最低能量的晶格结构上。在优化问题中,这一过程被用来找到一个良好的近似全局最优解。
算法步骤
模拟退火算法的基本步骤如下:
- 初始化:
- 确定初始解 x x x;
- 设定初始温度 T T T(高于系统可能达到的最高能量状态);
- 确定冷却计划,即如何降低温度。
- 循环迭代: 在每个温度水平上,重复以下步骤多次:
- 扰动: 生成一个新的候选解 x n e w x_{new} xnew,通常通过在当前解 x x x 的基础上进行随机的小幅度修改。
- 计算能量变化(成本函数差): Δ E = E ( x n e w ) − E ( x ) \Delta E = E(x_{new}) - E(x) ΔE=E(xnew)−E(x),其中 E E E 代表能量(成本或目标函数)。
- 接受判断:
- 如果 Δ E < 0 \Delta E < 0 ΔE<0,即新的解比当前解更好,则接受新解 x = x n e w x = x_{new} x=xnew;
- 如果 Δ E ≥ 0 \Delta E \geq 0 ΔE≥0,则以一定的概率接受较差的解,概率为 e − Δ E / T e^{-\Delta E / T} e−ΔE/T。这允许算法有机会跳出局部最优解,探索更广的解空间。
- 降温: 按照冷却计划降低温度 T T T。
- 终止条件: 重复上述迭代过程,直到满足终止条件,如温度降至某个预设的阈值或者迭代次数达到一定数量。
核心概念
- 温度(Temperature): 控制扰动幅度的参数,温度高时系统更可能接受差的解,以促进搜索过程的多样性;温度低时系统趋向稳定,搜索过程更加保守。
- 冷却计划(Cooling Schedule): 温度降低的速率对算法的性能至关重要。太快的冷却可能导致早熟收敛(陷入局部最优),而太慢的冷却则会导致算法运行时间过长。
- 接受准则(Acceptance Criterion): 决定是否接受新解的规则,通常基于Metropolis准则。
应用
模拟退火算法被广泛应用于各种优化问题,包括旅行商问题(TSP)、作业调度问题、网络设计、电路布局设计等。该算法在处理具有众多局部最优解的复杂问题时特别有效,能够找到一个相当好的全局最优解。
优缺点
模拟退火算法的主要优点是其简单性和对各种问题的适用性。然而,算法的效率高度依赖于冷却计划和参数的选择。不合适的参数设置可能导致算法在寻找最优解的过程中效率低下。此外,由于算法本质上是随机的,因此可能需要多次运行以确保找到一个好的解。
让我们通过一个简单的例子来说明模拟退火算法的工作原理——假设我们要优化一个二维空间中的目标函数,这个函数在不同的位置具有不同的值,我们的目标是找到函数的最小值。
目标函数示例:
假设我们的目标函数是 f ( x , y ) = sin ( x ) ⋅ cos ( y ) f(x, y) = \sin(x) \cdot \cos(y) f(x,y)=sin(x)⋅cos(y) ,我们想要找到这个函数在区间 x ∈ [ − π , π ] ) 和 ( y ∈ [ − π , π ] x \in [-\pi, \pi] ) 和 ( y \in [-\pi, \pi] x∈[−π,π])和(y∈[−π,π] 中的最小值。
模拟退火算法过程:
- 初始化:
- 随机选择一个初始解,例如 x = 0 x = 0 x=0, y = 0 y = 0 y=0。
- 设定初始温度,比如说 T = 100 T = 100 T=100。
- 设定冷却率,例如每次迭代后温度降低 1%,即新温度 T ′ = 0.99 ⋅ T T' = 0.99 \cdot T T′=0.99⋅T。
- 循环迭代:
- 循环开始时温度 T = 100 T = 100 T=100。
- 在当前温度下执行若干次迭代:
- 扰动:
- 随机生成一个新的位置 ( x ′ , y ′ ) (x', y') (x′,y′),比如在当前位置 ( x , y ) (x, y) (x,y)的基础上加上一个小的随机偏移。
- 计算能量变化:
- 计算新解的函数值 f ( x ′ , y ′ ) f(x', y') f(x′,y′)和当前解的函数值 f ( x , y ) f(x, y) f(x,y)。
- 计算能量变化 Δ E = f ( x ′ , y ′ ) − f ( x , y ) \Delta E = f(x', y') - f(x, y) ΔE=f(x′,y′)−f(x,y)。
- 接受判断:
- 如果 Δ E < 0 \Delta E < 0 ΔE<0,即新解的函数值更低,那么接受新解,更新当前位置为 ( x ′ , y ′ ) (x', y') (x′,y′)。
- 如果 Δ E ≥ 0 \Delta E \geq 0 ΔE≥0,则计算概率 p = e − Δ E / T p = e^{-\Delta E / T} p=e−ΔE/T。随机生成一个 [0, 1] 区间的随机数 r r r,如果 r < p r < p r<p,也接受这个新解。
- 降温:
- 更新温度 T = 0.99 ⋅ T T = 0.99 \cdot T T=0.99⋅T。
- 终止条件:
- 当温度降低到某个阈值以下,比如说 T < 0.001 T < 0.001 T<0.001,或者经过一定数量的迭代后,算法终止。
- 输出结果:
- 输出当前解 ( x , y ) (x, y) (x,y)以及对应的函数值 f ( x , y ) f(x, y) f(x,y) 作为最小值的近似。
经过这个过程,我们可能得到函数
f
(
x
,
y
)
f(x, y)
f(x,y) 的一个很好的最小值近似。重要的是要注意,由于存在随机性,可能需要多次运行模拟退火过程以获得最佳结果。此外,在实际应用中,选择合适的初始温度、冷却率和扰动策略对算法的成功至关重要。
以下是一个模拟退火算法的Python示例代码,用于寻找函数
f
(
x
,
y
)
=
sin
(
x
)
⋅
cos
(
y
)
f(x, y) = \sin(x) \cdot \cos(y)
f(x,y)=sin(x)⋅cos(y)在给定区间内的最小值点。
import math
import random
# 目标函数
def f(x, y):
return math.sin(x) * math.cos(y)
# 生成新的解
def new_solution(x, y, T):
x_new = x + random.uniform(-1, 1) * T
y_new = y + random.uniform(-1, 1) * T
return x_new, y_new
# 模拟退火算法
def simulated_annealing():
# 初始化
x = random.uniform(-math.pi, math.pi)
y = random.uniform(-math.pi, math.pi)
T = 100.0 # 初始温度
T_min = 0.001 # 最小温度
alpha = 0.99 # 冷却率
# 当前最佳解
current_solution = x, y
current_energy = f(x, y)
while T > T_min:
# 产生新的候选解
x_new, y_new = new_solution(x, y, T)
# 确保新解在定义域内
x_new = max(min(x_new, math.pi), -math.pi)
y_new = max(min(y_new, math.pi), -math.pi)
candidate_energy = f(x_new, y_new)
# 计算能量差
delta_energy = candidate_energy - current_energy
# Metropolis准则
if delta_energy < 0 or math.exp(-delta_energy / T) > random.random():
# 接受新解
current_solution = x_new, y_new
current_energy = candidate_energy
# 降温
T *= alpha
return current_solution, current_energy
# 运行模拟退火算法
best_solution, best_energy = simulated_annealing()
print(f"Best solution (x, y): {best_solution}")
print(f"Best energy (minimum function value): {best_energy}")
'''
Best solution (x, y): (1.525660884034248, 1.5565233874376394)
Best energy (minimum function value): 0.014257919242966856
'''
在这个代码中,f
函数定义了我们要优化的函数,new_solution
函数生成了新的解,并考虑了温度 T
来控制解的扰动幅度。simulated_annealing
是实现模拟退火算法的核心函数。我们不断生成新的解,使用 Metropolis 准则来决定是否接受新解,最后通过降温过程来逐步寻找最优解。