算法:模拟退火

之前觉得模拟退火算法是很高大上的存在,一直没有去了解。然后上次数模校赛我们就用到了模拟退火算法,发现思路其实并不复杂。

模拟退火算法

模拟退火(Simulated Annealing),来源于热力学上的退火现象。退火现象就是,将固体加温再徐徐冷却,最后在常温时就会呈现晶体状态。从微观角度来看,固体加温时,内部粒子趋于无序,内能增大;徐徐冷却时,粒子趋于有序,内能减小,在每个温度都达到平衡态;最后在常温时达到基态,此时内能减到最小。

其实退火现象只是算法思路的来源,用物理学的原理是无法解释算法的。从算法的角度来看,模拟退火算法是用于解决优化问题的算法。优化问题即满足题目约束的条件下求最优解的问题,常用的思路有广度优先搜索、贪心、动态规划等。不过当一个优化问题规模很大时,要找到最优解几乎是不可能的,所以我们只能去找尽可能接近最优的解。如果用一般的思路求解,往往会陷入局部最优,而模拟退火算法可以避免这个问题。局部最优解相当于函数的极小值,全局最优解相当于函数的最小值,显然,全局最优解才是我们的目标。

模拟退火算法的思路模仿了退火原理。首先选取一个初始解,然后迭代更新,最后得到最优解。每次迭代都要先用旧解得到新解,再作比较,若新解更优,则用新解代替旧解;否则,以一定概率替换旧解。也就是说,每次迭代都趋于得到一个更优的解,最后自然会得到一个接近最优的解。不过,当旧解更优时,新解仍然有一定概率替换旧解,这样算法就有了一定的随机性,即使旧解是局部最优,新解也有机会跳出去。考虑到随着迭代次数的增加,旧解已经越来越接近最优了,这时就应该减小新解跳出旧解的概率。

代码

const Solution DOMAIN;
const double INIT_T = 100;
const double MIN_T = 1;
const double RATE = 0.98;
const int LOOP = 1000;

/**
  * @return: the initialized solution
  */
Solution init();

/**
  * @param s: the old solution
  * @param domain: the domain of solution
  * @return: the new solution
  */
Solution getNext(Solution s, Solution domain);

void sa() {
  Solution s = init();
  double t = INIT_T;
  while (t > MIN_T) {
    for (int i = 0; i < LOOP; ++i) {
      Solution next = getNext(s, DOMAIN);
      if (next < s) s = next;
      else {
        double p = exp((s - next)/t);
        if (rand() / (RAND_MAX + 1) < p) s = next;
      }
    }
    t *= RATE;
  }
}

参考资料

  1. 百度百科
    https://baike.baidu.com/item/模拟退火算法/355508?fr=aladdin
  2. 博客
    https://www.cnblogs.com/ranjiewen/p/6084052.html
    https://blog.csdn.net/AI_BigData_wh/article/details/77943787?locationNum=2&fps=1
    https://blog.csdn.net/qq_30981697/article/details/70032094?locationNum=9&fps=1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章