模拟退火算法(Simulate Anneal,SA)
定义一个可接受的概率p,p\(\in[0,1]\)
\(f(x_j)和f(x_i)\)越接近,p越大 新解和旧解函数越接近,越愿意接受新解
\(y=e^{-x}(0\le x\le1)关于x单调递减\) \ge是大等于qwq \le是小等于
所以我们可以假设\(p \propto e^{-\left| f(x_j)-f(x_i)\right|}\)
因为有了负号所以不需要取导数
保证搜索前期范围尽量大,搜索后期范围尽量小
对式子\(p_t \propto e^{-\left| f(x_j)-f(x_i)\right|}\)进行变形\(p \propto e^{-\left| f(x_j)-f(x_i)\right|*C_i}\)
搜索前期t较小,我们希望搜索范围更大,更倾向于接受新解,对应的p就应该大,而\(C_i\)与p负相关,因此后期我们希望p较小,\(C_i\)就应该大一点,可以得到\(C_i\)关于t递增 所以时间越长t越大
假设求最大值:简单流程 || TSP
-
随机生成一个解A,计算A对应的f(A)
-
在A附近随机生成一个解B,计算B对应的f(B)
-
if (f(B)>f(A)) 把B赋值给A //反复迭代
-
if(f(B)\(\le\)f(A)) 计算接受P的概率\(p = e^{-\left| f(x_j)-f(x_i)\right|*C_i}\),然后生成一个[0,1]之间的随机数r,如果r
问题:如果优化问题有约束条件怎么办 怎样随机生成B?
\(C_i\)如何设置 搜索过程什么时候结束
定义初始温度,\(T_0=100\),温度下降公式\(T_{t+1}=aT_t\),a常取0.95,那么时刻t的温度
\(T_t=a^t * t_0=100*0.95^t\)
\(p_t=e^{\frac{f(B)-f(A)}{T_t}}=e^{\frac{\left|f(B)-f(A) \right|}{100*0.95^t}}\)
取倒数是为了保证\(C_i\)关于t递增
温度一定,\(\Delta f\)越小,概率阅读,目标函数接受相差越小的可能性越大
\(\Delta f\)一定,温度越高,概率越大(但需要的计算越多),搜索前期温度越高越可能接受新解
t的实现通过迭代(循环)为保证搜索彻底,我们进行多次搜索,然后降温,再多次搜索
搜索停止时间:1.达到指定迭代次数 2.达到指定温度 3找到连续最优解M次都没变化(自己定M)
dalao的一张图
一遍SA往往无法跑出最优解,所以可以多跑几遍。
可以用一个全局变量记录所有跑过的SA的最优解,每次从那个最优解开始继续SA,可以减小误差。
如何生成新解
坐标系内:随机生成一个点,或者生成一个向量。
序列问题: $random_shuffle$或者随机交换两个数。
网格问题:可以看做二维序列,每次交换两个格子即可。
时间复杂度 \(O(\text{玄学})\)。
一般降温系数 \(\Delta\) 与 1 的差减少一个数量级, 耗时大约多 10 倍; \(T_0\) 和\(T_k\) 变化一个数量级, 耗时不会变化很大。
大神勃客https://www.luogu.com.cn/blog/m-sea/qian-tan-SA