一、通俗理解
依旧利用爬山的场景,作为爬山者你总是在刚开始爬山的时候热情似火,十分激进
当位于分岔路口的时候,介于视野受限你无法知道哪条路才是通往最高峰,不同于爬山法此时你不再选择最陡峭的路,因为此时每条路对热情四溢的你来说都是一样的。
所以你先随机选择一条路,结果却发现这条路可能困难重重,无所谓,不冷静的你依然会有很大概率去走这条路
但是,随着时间的推移,你的热情逐渐退却,体力逐渐流逝,你意识到不能再这么胡乱地选择路径了,你变得越来越冷静,思绪越来越清晰,在分岔路口你逐渐选择那些看起来更陡峭的路径,所以当你发现了随机选择的路困难重重,你只有极低概率去走
最终,经过心路历程的变化,你终于爬到了山顶
此时此刻,你终于恍然大悟,退火退的不是燃烧的火焰,退的是你热情的心
二、算法名称的含义
- 温度:热情
- 劣解:困难重重的路
- 全局最优解:通往山顶的路
- 局部最优解:更陡峭的路径
- 关系:
- 温度越高,接受劣解的概率越大,搜索的随机性越强,越趋向于全局最优解
- 温度越低,接受劣解的概率越小,搜索的随机性越弱,越趋向于局部最优解
三、基本要素
- 状态产生函数(Generate):如何从当前状态生成新的候选状态
- 状态评估函数(Evaluate):得到每个状态的目标函数值
- 状态接受函数(Accept):根据温度等因素决定是否接受新生成的状态(核心)
- 在固定温度下,接受使目标函数值下降的候选解的概率要大于接受使目标函数值上升的候选解的概率
- 随着温度减小,接受使目标函数值上升的解的概率要逐渐减小
- 当温度趋于0时,只接受使目标函数值下降的解
- 降温函数(Cooling):每次迭代如何逐渐降低温度
- 内循环终止准则:在当前温度下的搜索是否平衡
- 外循环终止准则:整个算法何时终止
四、算法流程
- 初始化:
- 初始解:指定或随机生成
- 终止条件:终止温度、最大迭代次数、已经找到了最优解
- 迭代:
- 外循环终止:判断当前解是否满足终止条件,若满足则跳到4,否则继续执行
- 内循环终止:判断在当前温度下的搜索是否平衡,若不平衡则回到2.1,否则继续执行
- 产生候选解:根据当前解调用状态产生函数生成候选解
- 评估候选解:比较候选解和当前解的目标函数值当前解,若候选解的大则跳到2.6,否则继续执行
- 接受候选解:调用状态接受函数判断是否接受候选解,若不接受则回到2.2,否则继续执行
- 更新候选解:更新当前解为候选解
- 降温:调用温度更新函数降低温度,回到2.1进行新一轮迭代
- 输出:算法终止,输出得到的最优解
五、评测
- 良好的收敛性:能够在有限的迭代次数内收敛到一个满意的解
- 良好的鲁棒性:面对不同问题实例或参数设置变化时,依然可以有效地找到接近最优解的解决方案
- 不具有完备性和最优性:模拟退火算法依旧有概率会得到局部最优解而不是全局最优解
六、八皇后问题
描述:在一个 8x8 的国际象棋棋盘上,摆放八个皇后,使得任意两个皇后都不能处于同一行、同一列或同一斜线上
import random
import math
#初始状态生成函数
def initial(size):
state = random.sample(range(size),size)
return state
#状态产生函数:邻域替换,即随机选取两个位置替换值
def generate(state):
new_state = list(state)
i, j = random.sample(range(len(state)), 2)
new_state[i], new_state[j] = new_state[j], new_state[i]
return new_state
#状态评估函数:冲突数越少,目标函数值越大
def evaluate(state):
conflicts = 0
size = len(state)
for i in range(0,size-1):
for j in range(i+1,size):
diag1 = (state[i] - i) == (state[j] - j)
diag2 = (state[i] + i) == (state[j] + j)
if state[i] == state[j] or diag1 or diag2:
conflicts += 1
return conflicts
#状态接受函数
def accept(conflicts_diff,temperature):
return random.random() < math.exp(-conflicts_diff / temperature)
#降温函数
def cooling(temperature):
cooling_rate = 0.95
return temperature * cooling_rate
#模拟退火算法
def simulated_annealing(state):
temperature = 100.0
min_temperature = 1
interations = 0
max_iterations = 1000
cur_state = state
cur_conflicts = evaluate(cur_state)
#外循环终止准则:最低温or最大迭代次数
while interations != max_iterations and temperature != min_temperature:
balanced_flag = 0
#内循环终止准则:当前温度下最大迭代次数
while balanced_flag != 50:
#生成候选解
new_state = generate(cur_state)
#评估候选解
new_conflicts = evaluate(new_state)
#接受候选解
conflicts_diff = new_conflicts - cur_conflicts
accept_flag = accept(conflicts_diff,temperature)
if conflicts_diff < 0 or accept_flag:
#更新候选解
cur_state = new_state
cur_conflicts = new_conflicts
balanced_flag += 1
if cur_conflicts == 0:
return cur_state
temperature = cooling(temperature) #降温
interations += 1 #迭代次数+1
return cur_state
state = initial(8)
print('起始棋盘:', state)
result = simulated_annealing(state)
if evaluate(result) == 0:
print('成功:', result)
else:
print('失败:', result)