模拟退火算法详解,以TSP问题为例

1.基本理论

1.1基本思想

模拟退火的思想起源于固体的退火过程,即将固体加热至足够高的温度,再缓慢的降温。在这一过程中,任意恒定温度都能达到热平衡是个重要的步骤。 M e t r o p o l i s 提出了这样一个重要性采样的方法,即设从当前状态 i 生成新状态 j ,若新状态的内能小于状态 i 的内能(即 E j < E i ),则接受新状态 j 作为新的当前状态;否则,以概率 e x p ( ( E j E i ) / ( k T ) ) 接受 j ,其中 k B o l t z m a n n 常数.。把模拟退火算法应用于最优化问题时,一般可以将温度 T 当做控制参数,目标函数值 f 视为内能 E ,而固体在某温度 T 时的一个状态对应一个解 x i ,然后算法师徒随着控制参数 T 的降低,使目标函数值 f (内能 E )也逐渐降低,直至区域全局最小值,就像固体退火一样。

1.2 参数说明

  1. 控制参数的初值 T 0 :冷却开始的温度
  2. 控制参数 T 的衰减参数:计算这一系列温度的表达式。
  3. 控制参数 T 的终值 T f
  4. m a r k o v 链的长度 L k :任意温度 T 的迭代次数

1.3 算法的基本步骤

  1. T = T 0 。即开始退火的初始温度,随机生成一个初始解 x 0 ,并计算相应的目标 E x 0
  2. T 等于冷却进度表中的下一个 T i
  3. 根据当前解 x i 进行扰动(扰动方式可以参考后面的例题),产生一个新解 x j ,计算相应的目标函数值 E x j ,计算 Δ E = E ( x j ) E ( x j )
  4. Δ E < 0 则接受新解;反之,按照上文中提到的概率进行接受。
  5. 在温度 T i 下,重复 L k 次的扰动和接受过程,即执行3和4
  6. 判断 T 是否已经达到 T f ,是,终止算法,否则进行降温。

1.4几点说明

1状态表达

状态表达即指实际问题的解如何以一种合适的数学形式被表达出来,它应当适用于 S A 的求解,又能充分表达实际问题。这需要仔细地设计。可以参考遗传算法和紧急搜索中编码的相关内容。常见的表达方式有:背包问题和指派问题的0-1编码,TSP问题和调度问题的自然数编码,还有用于连续函数优化的示数编码等。

2新解的产生

新解产生的基本要求是能够尽量遍及解空间的各个区域,这样,在某一恒定温度不断产生新解,就可能跳出当前区域的极小搜索其他区域,这是模拟退火算法能够进行广域搜索的一个重要条件。

3收敛的一般性条件

收敛到全局最有的一般性条件是:

  1. 初始温度足够高
  2. 热平衡时间足够长
  3. 终止温度足够低
  4. 降温过程足够缓慢
4参数的选择
  1. 控制参数 T 和初值 T 0
  2. 衰减函数。
    一个常用的衰减函数 T k + 1 = a T k a 一般取 0.5 0.99
  3. M a r k o v 链长度
    M a r k o v 链长度的选择原则是:在控制参数 T 的衰减函数已经选定的前提下, L k 应能使控制参数 T 的每一取值上达到准平衡。从经验上来说,对简单的情况可以令 L k = 100 n n 为问题的规模

2MATLAB实现

这里利用经典 T S P 问题来进行说明

2.1算法设计步骤

1. T S P 问题的解空间和初始解
2. 目标函数
3. 新解产生

常采用的方法为二变换法三变换法
下面的例题中有具体变换的代码。

4. 目标函数差
5. M e t r o p o l i s 接受准则

2.2具体程序

clear
clc
a = 0.99;   % 温度衰减函数的参数
t0 = 97; tf = 3; t = t0;
Markov_length = 10000;  % Markov链长度
coordinates = [
  0.6606,0.9695,0.5906,0.2124,0.0398,0.1367,0.9536,0.6091,0.8767,...
    0.8148,0.3876,0.7041,0.0213,0.3429,0.7471,0.4606,0.7695,0.5006,0.3124,0.0098,0.3637,0.5336,0.2091,0.4767,...
    0.4148,0.5876,0.6041,0.3213,0.6429,0.7471;0.9500,0.6740,0.5029,...
    0.8274,0.9697,0.5979,0.2184,0.7148,0.2395,...
    0.2867,0.8200,0.3296,0.1649,0.3025,0.8192,0.6500,0.7420,0.0229,...
    0.7274,0.4697,0.0979,0.2684,0.7948,0.4395,...
    0.8867,0.3200,0.5296,0.3649,0.7025,0.9192
    ];
amount = size(coordinates,2);
for i = 1:amount
    for j = i+1:amount
        dist_matrix(i,j) = norm(coordinates(1,i)-coordinates(1,j),coordinates(2,i)-coordinates(2,j));
    end
end
dist_matrix = [dist_matrix;zeros(1,amount)];
dist_matrix = dist_matrix+dist_matrix';

sol_new = 1:amount;         % 产生初始解
% sol_new是每次产生的新解;sol_current是当前解;sol_best是冷却中的最好解;
E_current = inf;E_best = inf;       % E_current是当前解对应的回路距离;
% E_new是新解的回路距离;
% E_best是最优解的
sol_current = sol_new; sol_best = sol_new;
p = 1;
count = 0;
while t>=tf
    for r=1:Markov_length       % Markov链长度
        % 产生随机扰动
        if (rand < 0.5) % 随机决定是进行两交换还是三交换
            % 两交换
            ind1 = 0; ind2 = 0;
            while (ind1 == ind2)
                ind1 = ceil(rand.*amount);
                ind2 = ceil(rand.*amount);
            end
            tmp1 = sol_new(ind1);
            sol_new(ind1) = sol_new(ind2);
            sol_new(ind2) = tmp1;
        else
            % 三交换
            ind1 = 0; ind2 = 0; ind3 = 0;
            while (ind1 == ind2) || (ind1 == ind3) ...
                    || (ind2 == ind3) || (abs(ind1-ind2) == 1)
                ind1 = ceil(rand.*amount);
                ind2 = ceil(rand.*amount);
                ind3 = ceil(rand.*amount);
            end
            tmp1 = ind1;tmp2 = ind2;tmp3 = ind3;
            % 确保ind1 < ind2 < ind3
            if (ind1 < ind2) && (ind2 < ind3);
            elseif (ind1 < ind3) && (ind3 < ind2)
                ind2 = tmp3;ind3 = tmp2;
            elseif (ind2 < ind1) && (ind1 < ind3)
                ind1 = tmp2;ind2 = tmp1;
            elseif (ind2 < ind3) && (ind3 < ind1)
                ind1 = tmp2;ind2 = tmp3; ind3 = tmp1;
            elseif (ind3 < ind1) && (ind1 < ind2)
                ind1 = tmp3;ind2 = tmp1; ind3 = tmp2;
            elseif (ind3 < ind2) && (ind2 < ind1)
                ind1 = tmp3;ind2 = tmp2; ind3 = tmp1;
            end

            tmplist1 = sol_new((ind1+1):(ind2-1));
            sol_new((ind1+1):(ind1+ind3-ind2+1)) = ...
                sol_new((ind2):(ind3));
            sol_new((ind1+ind3-ind2+2):ind3) = ...
                tmplist1;
        end

        %检查是否满足约束

        % 计算目标函数值(即内能)
        E_new = 0;
        for i = 1 : (amount-1)
            E_new = E_new + ...
                dist_matrix(sol_new(i),sol_new(i+1));
        end
        % 再算上从最后一个城市到第一个城市的距离
        E_new = E_new + ...
            dist_matrix(sol_new(amount),sol_new(1));

        if E_new < E_current
            E_current = E_new;
            sol_current = sol_new;
            if E_new < E_best
                % 把冷却过程中最好的解保存下来
                E_best = E_new;
                sol_best = sol_new;
            end
        else
            % 若新解的目标函数值小于当前解的,
            % 则仅以一定概率接受新解
            if rand < exp(-(E_new-E_current)./t)
                E_current = E_new;
                sol_current = sol_new;
            else
                sol_new = sol_current;
            end
        end
    end
    count = count+1;
    t=t*a;      % 控制参数t(温度)减少为原来的a倍
end
disp('迭代了:');
disp(count);
disp('最优解为:')
disp(sol_best)
disp('最短距离:')
disp(E_best)

程序结果:

迭代了:
   346

最优解为:
  Columns 1 through 11 

    22    26    15    17     9     7     8    19    14    23    20

  Columns 12 through 22 

    13     5    25    21     4     6    12    18    29     3    28

  Columns 23 through 30 

    11    27    24    16    30     2    10     1

最短距离:
    4.7138

猜你喜欢

转载自blog.csdn.net/qq_35109096/article/details/81127573
今日推荐