现代启发式算法(二)——模拟退火算法

仅记录自己的学习历程


继续我们在遗传算法求解TSP问题中所说的,遗传算法具有很强的全局搜索能力,但由于“早熟”问题使得局部搜索能力不足,模拟退火算法虽然全局搜索能力不强,但具有很强的局部搜索能力,混合使用遗传算法和模拟退火算法可以解决很多NP-hard问题,即由遗传算法提供问题的较优解,然后由模拟退火求解全局最优解。

模拟退火的算法过程如下:
1.对原来的解进行变化,生成一个新的解;
2.如果新的解小于原来的解,则使用新解代替原解;
3.如果新的解大于原来的解,则以一定的概率使用新解代替原解
4.重复步骤1-3,直到达到结束条件。

我们需要知道模拟退火算法具有很强局部搜索能力的原因。下面这个公式虽然很简洁,但就是模拟退火算法的精髓之处。公式中ΔE代表着新解与原解之间的差值(注意:这里新解一定是大于原解,如果新解小于原解,则新解直接被接受了,就不需要以一定概率接受这个大于原解的新解),P代表着这个大于原解的新解被接受的概率,T作为参数控制概率的大小变化,k为布尔兹曼常数(为了简化,下文的例子中并不会用到k)。假设T=2000,k=1,如果新解与原解之间的差值等于2000,则该新解被接受的概率为exp(-1)=0.3679,差值越小,被接受的概率越大;反之,被接受的概率越小,所以T的取值对于模拟退火算法至关重要!你还要意识到这个接受概率P是一个指数函数,exp(-2)=0.1353,exp(-1)=0.3679,exp(-0.5)=0.6065,虽然新得到的解并不优于原来的解,但也许新得到的较差的解经过某种变换就可以得到比原来的解更好的解,这就为什么模拟退火算法要以一定的概率接受较差的解的原因,也是该算法具有很强局部搜索能力的原因。
现代启发式算法(二)——模拟退火算法_第1张图片

正如前文所说的,我们在遗传算法给出的较优解的基础上,继续使用模拟退火算法求解TSP问题。虽然下文的代码并不完整,但并不影响我们理解模拟退火算法。

说明:沿用遗传算法中的ga_adaptation函数计算该条path的长度,sa_exchange与遗传算法中的ga_exchange作用类似,flag_refuse作为一个标志位,如果新解被连续拒绝20次则跳出当前循环。

T=2000;                 %初始温度
T_end=1;                %外层循环截至条件
Loop=200;               %内层循环次数
Reduce=0;               %退火系数,应该是动态变化的
while(T>=T_end)
    flag_refuse=0;      %内层循环退出标志
    for i=1:Loop 
        path_old=path;
        E_old=ga_adaptation(path_old);
        path_new=sa_exchange(path);
        E_new=ga_adaptation(path_new);
        if(E_new%新解小于原解->接受
            path=path_new;
            flag_refuse=0;
        else                    %否则以一定概率->接受or拒绝
            if(rand < exp(-(E_new-E_old)/T))
                path=path_new;
            else
                flag_refuse=flag_refuse+1;
            end
        end
        if(flag_refuse==20)     %当新解被连续拒绝20次,则退出当前内层循环
            break;
        end
    end
    Reduce=10*T/2000;       %退火系数要使 T 尽可能慢地减小,以便模拟退火算法搜索更多地解空间
    T=T-Reduce;
end

你可能感兴趣的:(数学建模)