原理移步 -> 模拟退火算法_百度百科
模拟退火算法主要步骤:
1、设置初始温度。
2、在迭代过程中,温度根据降温系数下降,判断得到的新状态是否更优:
是 -> 接受新状态
否 -> 以一定概率接受,这个概率随着温度的下降而减小
3、如果温度降到设定的温度下界,程序停止
伪代码
eps = 1e-8; //终止温度,略大于0,用于控制精度
T = 100; //初始温度,应该是高温的状态
delta = 0.98; //降温系数,控制退火快慢
g(x); //状态x时的评价函数,模拟物理中的内能
now,next; //当前状态和新状态
while(T > eps){
g(next),g(now); //计算能量
dE = g(next) - g(now); //能量差
if(dE >= 0) //新状态更优,接受
now = next;
else if(exp(dE/T)) //新状态更差,以概率P(dE) = e^(dE/T)接受,dE < 0,P(dE) 随着T的减小而减小,P(dE) ∈ (0,1)
now = next;
T *= delta; //降温
}
来道例题,用模拟退火算法求函数最值
hdu2899
F(x)=6x^7+8x^6+7x^3+5x^2-yx(0<=x<=100),输入y值,输出F(x)的最小值
输入样例
100
输出样例
-74.4291
C++代码实现
#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
double y;
double func(double x) { //计算题目所给函数结果
return 6 * pow(x, 7.0) + 8 * pow(x, 6.0) + 7 * pow(x, 3.0) + 5 * pow(x, 2.0) - y * x;
}
double SA() {
double T = 100; //初始温度
double delta = 0.98; //降温系数
double x = 50.0; //x的初始值
double now = func(x);
while (T > eps) {
int f[2] = {1, -1};
double newx = x + f[rand() % 2] * T; //x变动的大小要随温度的降低而降低
if (newx >= 0 && newx <= 100) {
double next = func(newx);
double dE = next - now;
if (dE <= 0) { //这里小于等于0为状态更优,因为是要求函数最小值
x = newx;
now = next;
} else if (exp(-dE / T) * RAND_MAX > rand()) { //将P(dE)以代码方式展现
x = newx;
now = next;
}
}
T *= delta; //降温
}
return now;
}
int main() {
while (scanf("%lf", &y))
printf("%.4f\n", SA());
return 0;
}
最后,模拟退火算法虽然能摆脱局部最优解达到全局最优,但它得到的是一个可行解,而不是精确解,也就是说不是一个完全正确的最优解,这都跟算法的参数有关(初始温度T、降温系数delta、终止温度eps)。
参考罗勇军《算法竞赛入门到进阶》