1.起源

模拟退火算法来源于热力学中固体物质的退火冷却过程 (退火是一种金属热处理工艺,指的是将金属缓慢加热到一定温度,保持足够时间,然后以适宜速度冷却)

2.物理退火流程

模拟退火的算法思想是参考物理退火的过程而来,物理退火的过程为:加温过程 -> 等温过程 -> 冷却过程

2.1 加温过程

通过加温,增强粒子的热运动,让各部分变得均匀。当温度足够高时,固体将熔解为液体,从而消除原先系统中可能存在的非均匀状态,保证后续进行的过程是从平衡态开始,由于是加温过程温度上升,所以该过程系统能量增加。

2.2 等温过程

对于与周围环境交换热量而温度保持不变的封闭系统,系统状态的自发变化总是朝着自由能减少的方向进行,当自由能达到最小时,系统达到平衡态

2.3 冷却过程

通过一定速率对液体进行冷却,减弱粒子的热运动并趋于有序,在每个温度都达到平衡态,最后在常温时达到基态,能量减为最小,从而得到低能态的晶体结构

2.4 组合优化与物理退化

3.原理

模拟退火算法的基本原理:对于目标函数 f ( X ) f(X) f(X)、自变量为 X X X n n n 维极小化问题(极大化问题乘以 − 1 -1 1转化为极小化问题),初值 X 0 X_0 X0 可以随机化或者自己设置。

3.1 算法核心迭代

f k , f k + 1 f_k,f_{k+1} fk,fk+1 分别为目标函数在第 k k k 次和第 k + 1 k+1 k+1 次迭代值,即 f k = f ( X k ) , f k + 1 = f ( X k + 1 ) f_k=f(X_k),f_{k+1}=f(X_{k+1}) fk=f(Xk),fk+1=f(Xk+1)
f k > f k + 1 f_k>f_{k+1} fk>fk+1,则接受 X k + 1 X_{k+1} Xk+1 作为下一次迭代的初值继续进行运算,直至满足终止条件(收敛或者迭代次数耗尽);
f k < f k + 1 f_k<f_{k+1} fk<fk+1,则接受 X k + 1 X_{k+1} Xk+1 的概率为 p p p,拒绝的概率为 1 − p 1-p 1p,其中接受概率公式如下: p = e x p ( − f k + 1 − f k T ) p=exp(-\frac{f_{k+1}-f_k}{T}) p=exp(Tfk+1fk) 其中 T T T 为控制参数,在模拟退火算法中, T T T 必须缓慢减少,避免变化过快,导致优化陷入极值点。

3.2 具体流程

以求解极小值问题为例:
( 1 ) (1) 1设定初始温度 T T T,迭代次数 L L L,误差 ϵ \epsilon ϵ,初始解 X 0 X_0 X0,得到目标函数 f ( X 0 ) f(X_0) f(X0)
( 2 ) (2) 2循环进行迭代, k = 1 , ⋯   , L k=1,\cdots,L k=1,,L
( 3 ) (3) 3根据当前温度得到新解 X ′ X' X(第一个可以随机生成), 代入 f ( X ) f(X) f(X) 得到 f ( X ′ ) f(X') f(X)
( 4 ) (4) 4 f ( X ) > f ( X ′ ) f(X)>f(X') f(X)>f(X),则接受 X ′ X' X 作为下一次迭代的初值,若 f ( X ) < f ( X ′ ) f(X)<f(X') f(X)<f(X),则以概率 e x p ( − f ( X ′ ) − f ( X ) T ) exp(-\frac{f(X')-f(X)}{T}) exp(Tf(X)f(X)) 接受 X ′ X' X 作为下一次迭代的初值;
( 5 ) (5) 5若满足终止条件,则输出当前最优解 X ′ X' X,终止条件;
( 6 ) (6) 6 T T T 减小,然后回到流程 ( 2 ) (2) 2,在当前温度下继续循环迭代,执行步骤 ( 3 , 4 , 5 ) (3,4,5) 345
( 7 ) (7) 7注意,这里的终止条件可以有多个,比如:迭代次数耗尽、满足最优解、温度降低到一定值、新目标函数与原先目标函数的误差小于 ϵ \epsilon ϵ

4.案例

4.1 求解n元函数的极小值

例1:求解函数 f ( X ) = X 2 f(X)=X^2 f(X)=X2 的最小值,其中 X 2 = ∑ i = 1 10 x 2 X^2=\sum_{i=1}^{10}x^2 X2=i=110x2 − 10 ≤ x ≤ 10 -10\leq x\leq 10 10x10
下面通过matlab进行求解:
目标函数:

%--------目标函数f(x)---------
function result = func1(x)
    result = sum(x.^2);
end

模拟退火算法:

clear; clc;

%---------------------模拟退火核心-------------------------------
L = 200;                           % 每个温度的迭代次数
epsilon = 1e-10;                   % 新目标函数与原先目标函数的误差
T0 = 200;                          % 初始温度
T1 = 0.00001;                      % 终止温度
s = 0.01;                          % 自变量更新的步长,相当于学习率
K = 0.998;                         % 温度衰减参数
P = 0;                             % Metropolis 过程中总接受点

%---------------------根据题目所写--------------------------------
opt_minmax = 1;                    % 求解极小值问题为1,极大值问题为-1
n = 10;                            % 自变量维度
up = 10;                           % 自变量上限
sup = -10;                         % 自变量下限
x0 = rand(n, 1)*(up-sup)-up;       % 随机生成在范围内的初始自变量
x1 = rand(n, 1)*(up-sup)-up;       % 随机生成在范围内的 x1 自变量进行第一步
PreBest = x0;
NowBest = x1; 

%---------------------进行迭代----------------------------------
delta = abs(func1(NowBest) - func1(PreBest));
while (delta > epsilon) && (T0 > T1)
    T0 = K*T0;
    for i = 1:L
        x2 = x1 + s*(rand(n, 1)*(up-sup)-up);
        %-----下面这个循环是写题目的条件的,这里没啥好些,就重复了边界条件
        for j = 1:n
            while (x2(j) > up) || (x2(j) < sup)
                x2(j) = x1(j) + s*(rand*(up-sup)-up);
            end
        end
        %--------------查看解是否是全局最优解----------------
        if opt_minmax*func1(NowBest) > opt_minmax*func1(x2)
            PreBest = NowBest;             % 保留上一个最优解
            NowBest = x2;                  % 保留新的最优解
        end
        %---------------- Metropolis过程--------------------
        if opt_minmax*func1(x1) > opt_minmax*func1(x2)
            x1 = x2;
            P = P + 1;
        else
            p = exp(-(func1(x2)-func1(x1))/T0);
            if p > rand(1)
                x1 = x2;
                P = P + 1;
            end
        end
        Y(P) = func1(NowBest);
    end
    delta = abs(func1(NowBest) - func1(PreBest));
end

得到结果为:
X = [ − 0.0114 , − 0.0002 , 0.0020 , 0.0101 , 0.0074 , − 0.0003 , − 0.0084 , 0.0112 , − 0.0252 , 0.0052 ] X=[-0.0114,-0.0002,0.0020,0.0101,0.0074,-0.0003,-0.0084,0.0112,-0.0252,0.0052] X=[0.0114,0.0002,0.0020,0.0101,0.0074,0.0003,0.0084,0.0112,0.0252,0.0052]

f ( X ) = 0.0011 f(X)=0.0011 f(X)=0.0011
绘制适应度进化曲线:

%----------------------------画图--------------------------------
plot(Y, 'r');
hold on
scatter(length(Y), Y(end), 'bo', 'MarkerFaceColor', 'b')
text(length(Y), Y(end), ' 最优点')
xlabel('迭代次数'); ylabel('目标函数值'); title('适应度进化曲线');

智能算法之模拟退火算法-LMLPHP

4.2 求解二元函数的极小值

例2:求解函数 f ( x , y ) = 5 c o s ( x y ) + x y + y 3 f(x,y) = 5cos(xy)+xy+y^3 f(x,y)=5cos(xy)+xy+y3 的最小值,其中 − 5 ≤ x ≤ 5 , − 5 ≤ y ≤ 5 -5\leq x\leq 5,-5\leq y\leq 5 5x5,5y5
下面通过matlab进行求解:
目标函数:

%--------目标函数f(x)---------------
function result = func1(x)
    result = 5*cos(x(1).*x(2))+x(1).*x(2)+x(2).^3;
end

可以看看 f ( x , y ) f(x,y) f(x,y) 的图像:

clear;clc;
x = linspace(-5, 5);
y = linspace(-5, 5);
[x, y] = meshgrid(x, y);
f = 5*cos(x.*y)+x.*y+y.^3;
mesh(x, y, f);
xlabel('x'); ylabel('y'); zlabel('f');

智能算法之模拟退火算法-LMLPHP

第二种方法适合小白,不过和meshgrid画出来的图相比较发现是翻转过的,所以可以自行选择。

x1 = linspace(-5, 5);
y1 = linspace(-5, 5);
N = size(x1, 2);
for i = 1:N
    for j = 1:N
        z(i, j)=5*cos(x1(i)*y1(j))+x1(i)*y1(j)+y1(j)^3;
    end
end
mesh(x1, y1, z);
xlabel('x1'); ylabel('y1'); zlabel('z');

智能算法之模拟退火算法-LMLPHP
模拟退火算法:

clear; clc;

%---------------------模拟退火核心------------------------------------------
L = 200;                             % 每个温度的迭代次数
epsilon = 1e-8;                      % 新目标函数与原先目标函数的误差
T0 = 200;                            % 初始温度
T1 = 0.00001;                        % 终止温度
s = 0.01;                            % 自变量更新的步长,相当于学习率
K = 0.998;                           % 温度衰减参数
P = 0;                               % Metropolis 过程中总接受点

%---------------------根据题目所写------------------------------------------
opt_minmax = 1;                      % 求解极小值问题为1,极大值问题为-1
n = 2;                               % 自变量维度
up = [5; 5];                         % 自变量x,y上限
sup = [-5; -5];                      % 自变量x,y下限
x0 = rand(2, 1).*(up-sup)-up;        % 随机生成在范围内的初始自变量x0,y0
x1 = rand(2, 1).*(up-sup)-up;        % 随机生成在范围内的 x1, y1 自变量进行第一步
PreBest = x0;
NowBest = x1; 

%---------------------进行迭代----------------------------------------------
delta = abs(func1(NowBest) - func1(PreBest));
while (delta > epsilon) && (T0 > T1)
    T0 = K*T0;
    for i = 1:L
        x2 = x1 + s*(rand(n, 1).*(up-sup)-up);
        %-----下面这个循环是写题目的条件的,这里没啥好些,就重复了边界条件
        for j = 1:n
            while (x2(j) > up(j)) || (x2(j) < sup(j))
                x2(j) = x1(j) + s*(rand*(up(j)-sup(j))-up(j));
            end
        end
        %--------------查看解是否是全局最优解----------------
        if opt_minmax*func1(NowBest) > opt_minmax*func1(x2)
            PreBest = NowBest;             % 保留上一个最优解
            NowBest = x2;                  % 保留新的最优解
        end
        %---------------- Metropolis过程--------------------
        if opt_minmax*func1(x1) > opt_minmax*func1(x2)
            x1 = x2;
            P = P + 1;
        else
            p = exp(-(func1(x2)-func1(x1))/T0);
            if p > rand(1)
                x1 = x2;
                P = P + 1;
            end
        end
        Y(P) = func1(NowBest);
    end
    delta = abs(func1(NowBest) - func1(PreBest));
end

得到结果为:
f ( x , y ) = f ( 4.4394 , − 5.0000 ) = − 152.0912 f(x,y)=f(4.4394,-5.0000)=-152.0912 f(x,y)=f(4.4394,5.0000)=152.0912
绘制适应度进化曲线:

%----------------------------画图--------------------------------
plot(Y, 'r');
hold on
scatter(length(Y), Y(end), 'bo', 'MarkerFaceColor', 'b')
text(length(Y), Y(end), ' 最优点')
xlabel('迭代次数'); ylabel('目标函数值'); title('适应度进化曲线');

智能算法之模拟退火算法-LMLPHP

4.3 货物配送规划

例3:根据下面的所给的条件,给此地的生鲜配送路线进行规划,让生鲜被高效率送到各销售市场中,使得资源达到最大的利用。

n n n :销售市场数量;
q i q_i qi:每个市场需求量 ( i = 1 , 2 , ⋯   , n ) (i=1,2,\cdots,n) (i=1,2,,n)
m m m:配送车数量(每辆车都型号都一致);
Q Q Q:配送车最大装载量;
d i j d_{ij} dij:市场 i i i 到市场 j j j 的距离;
t i j t_{ij} tij:从市场 i i i 到市场 j j j 所需时间;
d o i d_{oi} doi:配送中心 o o o 到市场 i i i 的距离;
c 0 c_0 c0 :每次配送固定成本;
c v c_v cv:单位里程行驶费用;
v v v:配送车匀速行驶速度;
T T T:生鲜装卸时间;
β 1 \beta_1 β1:单位时间配送运输损耗比例;
β 2 \beta_2 β2:单位时间配送装卸损耗比例;
u i j k u_{ijk} uijk:配送车辆 k k k i i i j j j 路径上行驶时的载重量;
p p p:单位重量货物的货损价格;
f 0 f_0 f0:单次配送任务中,配送中心派出的送货车辆总数;
f v f_v fv:单次配送任务中,所有配送车辆行驶里程数之和;
f b f_b fb:单次配送任务中,所有配送线路上产生的货损量之和。

4.3.1 分析

决策变量:
X i j k = { 1 , 配 送 车 k 从 市 场 ( 或 配 送 中 心 ) i 到 市 场 j 0 , 其 他 X_{ijk}=\left\{ \begin{aligned} 1, \quad 配送车 k 从市场(或配送中心) i 到市场 j \\ 0, \quad \quad \quad \quad \quad \quad \quad \quad其他 \quad \quad \quad\quad \quad \quad \quad \end{aligned} \right. Xijk={1,k()ij0, Y i k = { 1 , 市 场 i 的 货 物 由 配 送 车 k 配 送 0 , 其 他 Y_{ik}=\left\{ \begin{aligned} 1, \quad 市场 i 的货物由配送车k配送 \\ 0, \quad \quad \quad \quad \quad其他\quad \quad \quad \quad\quad \quad \end{aligned} \right. Yik={1,ik0, 目标函数 m i n Z = m i n ( f 0 c 0 + f v c v + f b p ) min Z = min(f_0c_0+f_vc_v+f_bp) minZ=min(f0c0+fvcv+fbp) m i n Z = m i n [ k c 0 + ∑ i = 0 n ∑ j = 0 n ∑ k = 1 m d i j X i j k c v + ( ∑ i = 0 n ∑ j = 0 n ∑ k = 1 m β 1 t i j u i j k X i j k + ∑ i = 0 n ∑ k = 1 m β 2 T q i Y i k ) p ] minZ=min[kc_0+\sum_{i=0}^n\sum_{j=0}^n\sum_{k=1}^md_{ij}X_{ijk}c_v \\ + (\sum_{i=0}^n\sum_{j=0}^n\sum_{k=1}^m\beta_1t_{ij}u_{ijk}X_{ijk}+\sum_{i=0}^n\sum_{k=1}^m\beta_2Tq_{i}Y_{ik})p] minZ=min[kc0+i=0nj=0nk=1mdijXijkcv+(i=0nj=0nk=1mβ1tijuijkXijk+i=0nk=1mβ2TqiYik)p] 约束条件
每条路线的生鲜需求量之和不超过配送车最大装载量 Q Q Q ∑ i = 1 n q i Y i k ≤ Q ( k = 1 , 2 , ⋯   , m ) \sum_{i=1}^nq_{i}Y_{ik} \leq Q \quad(k=1,2,\cdots,m) i=1nqiYikQ(k=1,2,,m) 每辆车不可能同时去两个市场: ∑ i = 1 n X o i k = ∑ i = 1 n X i o k ≤ 1 ( k = 1 , 2 , ⋯   , m ) \sum_{i=1}^nX_{oik}=\sum_{i=1}^nX_{iok}\leq1 \quad(k=1,2,\cdots,m) i=1nXoik=i=1nXiok1(k=1,2,,m) 每个市场只有一辆配送车送货: ∑ k = 1 m Y i k = 1 ( i = 1 , 2 , ⋯   , n ) \sum_{k=1}^mY_{ik}=1\quad (i=1,2,\cdots,n) k=1mYik=1(i=1,2,,n) 这里假设市场需求量之和为配送车最大装载量之和: ∑ i = 1 n q i = ∑ k = 1 m Q \sum_{i=1}^{n}q_i=\sum_{k=1}^mQ i=1nqi=k=1mQ

编写程序,进行计算

5.优缺点及可改进方向

6.参考文献

[1] 周佳莉. 模拟退火算法的应用[J]. 西部皮革,2019,41(20):82.
[2] 包子阳,余继周,杨杉. 智能优化算法及其MATLAB实例(第3版)
[3] 康雯轩. 基于模拟退火算法的共享单车城市配送路径规划[J]. 科技与创新,2022(13):104-106,109. DOI:10.15913/j.cnki.kjycx.2022.13.032.

12-04 17:35