模拟退火算法

原理移步 -> 模拟退火算法_百度百科


模拟退火算法主要步骤:
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

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)。


参考罗勇军《算法竞赛入门到进阶》

你可能感兴趣的:(模拟退火算法,算法)