模拟退火
退火这个概念是在热力学当中的,实际上就是把物体加热到一个高温,然后慢慢冷却到一个特定的温度。要求均衡降温。
而运用到统计学当中,因为是模拟这个过程,所以叫模拟退火。
这个算法有几个重点部分:
重点部分1 算法流程
假设我们找的是区间最大值
const int T=100
const int T_min=1e-18
const int dr=0.97//温度衰减率
const int limit=1001; //循环次数限定
while (t>t_min)
{
int old, best, now;
int xh=0;
for (int i=1; ... ; i++)
{
now=f(i);
if (old-now<0) {old=now; xh=0;}
else if ((1.0*(now-old)/t)>rand()/(RAND_MAX+1.0) && (1.0*(now-old)/t)<1)
{old=now; xh++;}
if (xh>limit) {fu++; break;}
}
if (old>best) best=old;
t*=dr;
}
我们解释一下最核心的两个地方,如果新更新的值比原来优,那么直接更新。如果没有,那么一定概率选择这个不优的解。而这个概率由,两个函数的差值除以目前的温度与一个随机的数的大小决定。(这样做的原因是提高不陷入某个凸函数的区间的概率).
其他的地方,我用一个循环来限制了内部最大循环次数,这样可以有效提高程序效率。
重点部分2 关于参数的设定
根据退火的定义,我们要设定一个高温 T , T, T, 目标温度 T m i n T_{min} Tmin ,每次降温的热量 Δ r \Delta r Δr .
当然,要多次试验,尽管是相同参数都会产生不一样的结果,而且可能时间也不一样。使用c++的clock函数来测定时间。这个东西完全就是看 R P RP RP 的。平时脸黑没有关系。
当然说正经的,如果你的程序跑的有点慢,可以适当减小
Δ
r
\Delta r
Δr 来尝试, 或者增大
T
m
i
n
T_{min}
Tmin, 可是这些操作都会降低程序的准确性。所以在调试模拟退火的时候,要自己手动二分这些参数。 当然有个暴力跑对拍是最好的。可是你都写了模拟退火还写什么暴力啊?
重点部分3 套入其他的算法
从最开始的一个乱七八糟的函数上找极值,是比较序列的问题。如果只能处理这样的问题,那不是很垃圾吗?所以当然要套一些奇奇怪怪的♂算法。套什么最优值的就可以了。
先更新到这里