搜索 —— 启发式搜索 —— 模拟退火

【概述】

模拟退火(Simulated Annealing,SA),其类似于物理学上金属退火的过程,故称为模拟退火,其是一个随机化与贪心结合的算法,在你 RP 较好或数据范围比较小的时候,可以轻松解决许多难题。

模拟退火的原理与金属退火的原理近似:

  • 将热力学的理论套用到统计学上
  • 将搜寻空间内每一点想像成空气内的分子
  • 搜寻空间内的每一点,也像空气分子一样带有动能,其用于表示该点对命题的合适程度
  • 演算法先以搜寻空间内一个任意点作起始:每一步先选择一个相邻的点,然后再计算从现有位置到达相邻点的概率

【主要思路】

我们模拟物理退火的三个过程:加温、等温、冷却,来归纳一下模拟退火算法的主要思路:

首先,确定一个初始温度 T,这个参数是随机选择的,初始温度选择的越好,算法表现就越好,但具体该选何值,没有一个明确的界定方法,只能依靠 RP 来选,不过据说有些大佬可以根据题目推出最优初始温度

然后,当温度大于一个边界值时,我们将当前状态的答案与下一状态的答案进行比较:

  • 如果 res<newRes,转移答案
  • 如果 res>newRes,有一定概率转移答案

在扩展状态时有一个小方法:nextSta=nowSta+(rand()∗2−RAND_MAX)∗T,这样的原理是:(rand()∗2−RANDMAX) 的范围是从负数到正数的,这样在扩展坐标的时候就可以多方向扩展,不会只在一个方向上更新。

其次,确定转移答案的概率,由于转移答案的概率需要随着时间的推移res 和 newRes 差值的增大而增大,因此常表示为:e^x,其中 x={\frac{res-newRes}{T}}

最后,我们模拟降温过程,对 T 乘以一个小于但十分接近于 1 的数 delta,以体现时间对答案的影响。

这样,随着温度不断降低,变化幅度也越来越小,接受一个更劣的解的概率也越来越小。

void SA(double nowSta){
    int T = ****; //初始温度
    double delta=0.99;
    int res=getRes(nowSta);//初始状态能得到的答案
    while (T > EPS) { // EPS是一个大于0的极小值,用于精度的比较,一般取1E-9~1E-15
        int nextSta = nowSta + (rand() * 2 - RAND_MAX)*T; //扩展状态
        int newRes = getRes(nextSta); //记录下一个状态能得到的答案
        double pr = exp((res - newRes) / T) * RAND_MAX;//一定的概率

        if (res < newRes || pr > rand()){//新的代价小于当前代价,或在一定概率下
            nowSta = nextSta;//更新当前状态
            res = newRes;//更新新状态的答案
        }
        T *= delta; //降温的过程,将温度减小
    }
}

 

©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页