跳到主要内容

模拟退火

一、直观理解:高温时敢乱走,降温后细打磨​

模拟退火(Simulated Annealing, SA)模仿金属退火:温度高时原子可大幅跃迁,温度降低后逐渐稳定在低能态。对应优化:

  • 当前解 xx,随机产生邻域解 x′x';
  • 若 f(x′)≤f(x)f(x')\le f(x)(最小化),则接受;
  • 若变差,仍以概率 exp⁡(−(f(x′)−f(x))/T)\exp\bigl(-(f(x')-f(x))/T\bigr) 接受,从而有机会跳出局部最优;
  • 按冷却计划降低温度 TT,接受变差的概率越来越小,搜索趋于收敛。

SA 实现简单,对离散组合问题很常用,但同样无最优保证,结果依赖随机性与降温表。

定位(必读):仅作兜底。TSP、排程等若有专用精确/近似算法或可建 MILP,应优先尝试。使用 SA 必须固定种子、多次运行,并与 2-opt 局部搜索等基线比较。

二、适用场景与优缺点​

类型说明
适用场景大规模组合邻域结构清晰(路径、分配、开关向量);目标可快速评价;精确法不可行;需要单线程易实现的元启发式。
核心优点代码短;能接受上坡移动;理论在无限缓慢降温下有收敛结果(实践达不到);参数相对直观。
局限与缺点降温过快易冻在劣解;过慢浪费评价;连续高维不如有梯度方法;约束需罚函数或邻域内保持可行。

强制检查:是否已尝试问题结构算法?是否有局部搜索基线?能否报告 NN 次实验?

三、核心原理​

1. Metropolis 接受准则​

P(accept)={1,Δ≤0e−Δ/T,Δ>0Δ=f(x′)−f(x)P(\text{accept})=\begin{cases} 1, & \Delta\le 0\\ e^{-\Delta/T}, & \Delta>0 \end{cases} \quad \Delta=f(x')-f(x)

2. 冷却计划​

常见:

  • 几何降温 T←αTT\leftarrow \alpha T,α∈[0.8,0.99]\alpha\in[0.8,0.99];
  • 每个温度层迭代 LL 次再降温;
  • 初温使初始接受率约 0.5∼0.80.5\sim 0.8;终温使上坡几乎不接受。

3. 邻域设计(决定成败)​

问题邻域例子
0-1 串翻转 1~2 位
TSP2-opt、交换两城
连续向量高斯扰动,步长随 TT 缩小

邻域应「小步可到达、大步偶尔可跳」。

4. 与爬山法​

T=0T=0 且不接受上坡即为爬山/局部搜索。SA 的价值在于可控的上坡。

四、关键决策​

1. 基线​

至少跑纯局部搜索(只接受改进)与随机重启。若 SA 不能稳定优于它们,说明邻域或降温有问题。

2. 可行性​

优先设计保持可行的邻域(如 TSP 交换仍是回路);否则重罚。

3. 预算​

以目标评价次数为公平预算,与基线对齐。

4. 复现​

rng(seed);记录每次最终 ff 与最好 ff。

5. 停用条件​

问题可转化为凸或中小 MILP 时,改回精确方法。

五、MATLAB 示例​

例:TSP 的模拟退火 + 2-opt 邻域,与贪心基线对比​

% 随机城市坐标
rng(1);
n = 20;
XY = rand(n, 2);
dist = squareform(pdist(XY));

% 路径长度
tourLen = @(tour) sum(dist(sub2ind([n n], tour, tour([2:end 1]))));

% ---- 基线1:最近邻贪心 ----
function tour = nnTour(D)
n = size(D,1); un = true(1,n); tour = zeros(1,n);
tour(1) = 1; un(1) = false;
for k = 2:n
last = tour(k-1);
cand = find(un);
[~, j] = min(D(last, cand));
tour(k) = cand(j); un(cand(j)) = false;
end
end
tour0 = nnTour(dist);
len0 = tourLen(tour0);
fprintf("最近邻基线长度 = %.4f\n", len0);

% ---- 基线2:纯 2-opt 爬山 ----
function [tour, L] = twoOptHill(tour, D, maxIt)
n = numel(tour); L = sum(D(sub2ind([n n], tour, tour([2:end 1]))));
for it = 1:maxIt
improved = false;
for i = 1:n-2
for k = i+1:n-1
% 2-opt 逆转 i+1..k
a = tour(i); b = tour(i+1); c = tour(k); d = tour(mod(k,n)+1);
delta = D(a,c)+D(b,d) - D(a,b)-D(c,d);
if delta < -1e-12
tour(i+1:k) = tour(k:-1:i+1);
L = L + delta; improved = true;
end
end
end
if ~improved, break; end
end
end
[tourH, lenH] = twoOptHill(tour0, dist, 100);
fprintf("2-opt 爬山基线 = %.4f\n", lenH);

% ---- SA 多次运行 ----
nRuns = 12;
bestLens = zeros(nRuns,1);
seeds = 5000 + (1:nRuns);
for r = 1:nRuns
rng(seeds(r));
tour = tour0(randperm(n)); % 随机起点排列
L = tourLen(tour);
bestTour = tour; bestL = L;
T = mean(dist(:)); % 粗初温
alpha = 0.995;
maxEval = 20000;
for ev = 1:maxEval
i = randi(n-1); k = randi([i+1, n]);
% 提议 2-opt
a = tour(i); b = tour(i+1); c = tour(k); d = tour(mod(k,n)+1);
if k == n, d = tour(1); end
% 简化:随机交换两位置
p = randperm(n, 2);
tour2 = tour; tour2(p(1)) = tour(p(2)); tour2(p(2)) = tour(p(1));
L2 = tourLen(tour2);
dE = L2 - L;
if dE <= 0 || rand < exp(-dE / max(T, 1e-12))
tour = tour2; L = L2;
if L < bestL, bestL = L; bestTour = tour; end
end
T = alpha * T;
end
% 末端再抛光
[bestTour, bestL] = twoOptHill(bestTour, dist, 50);
bestLens(r) = bestL;
end
fprintf("SA+抛光 %d 次: best=%.4f mean=%.4f std=%.4f\n", ...
nRuns, min(bestLens), mean(bestLens), std(bestLens));
fprintf("种子: "); disp(seeds);
fprintf("相对最近邻改进 %.2f%%, 相对2-opt改进 %.2f%%\n", ...
100*(len0-min(bestLens))/len0, 100*(lenH-min(bestLens))/max(lenH,eps));

连续问题可用 simulannealbnd(Global Optimization Toolbox):

fun = @(x) (x(1)^2+x(2)-11)^2 + (x(1)+x(2)^2-7)^2; % Himmelblau
lb = [-5,-5]; ub = [5,5];
vals = zeros(10,1);
for r = 1:10
rng(70+r);
opts = optimoptions("simulannealbnd", "Display", "off");
[~, vals(r)] = simulannealbnd(fun, [0,0], lb, ub, opts);
end
fprintf("simulannealbnd best/mean/std = %.4f / %.4f / %.4f\n", ...
min(vals), mean(vals), std(vals));

六、如何解释结果​

必须写清:

  1. 选用 SA 的理由(精确法不可用之处);
  2. 邻域、初温、降温、每温度迭代/总评价次数;
  3. 种子与多次运行分布;
  4. 与贪心、纯局部搜索的对比表;
  5. 最终解的可行性与业务含义;
  6. 「随机近优,非全局证明」。

七、常见误区​

1. 降温过快​

曲线上很快不接受上坡,等价于烂爬山。

2. 邻域不会产生多样性​

交换算子设计失败时,SA 再好也无效。

3. 只展示一次最佳运气​

必须统计。

4. 连续可微问题放弃 fmincon​

有梯度时 SA 通常不是首选。

5. 无基线宣称「效果很好」​

没有参照的「好」不可信。

6. 约束靠巨大罚却从不检查可行性​

最终方案可能仍不可行。

八、小结​

模拟退火的核心思想可以概括为:

在邻域中随机走动,用温度控制的 Metropolis 准则接受上坡移动,并通过降温从探索过渡到利用,以寻求近优解。

它是组合优化中常用的兜底元启发式。正确姿态是:结构算法优先、基线必比、种子必报、多次必跑,把 SA 当作「在预算内找更好可行解的工具」,而不是最优性证书。