模拟退火算法

时间:2015-11-10 13:42:35

标签: c++ simulated-annealing

我在C ++中实现了模拟退火,以在某个范围内最小化(x-2)^2+(y-1)^2

我得到了不同的输出,这对于这种启发式方法是不可接受的。似乎解决方案正在趋同但从未完全接近解决方案。

我的代码:

#include <bits/stdc++.h>
using namespace std;

double func(double x, double y)
{
    return (pow(x-2, 2)+pow(y-1, 2));
}
double accept(double z, double minim, double T,double d)
{
    double p = -(z - minim) / (d * T);
    return pow(exp(1), p);
}
double fRand(double fMin, double fMax)
{
    double f = (double)rand() / RAND_MAX;
    return fMin + f * (fMax - fMin);
}

int main()
{
    srand (time(NULL));
    double x = fRand(-30,30);
    double y = fRand(-30,30);
    double xm = x, ym=y;
    double tI = 100000;
    double tF = 0.000001;
    double a = 0.99;
    double d=(1.6*(pow(10,-23)));
    double T = tI;
    double minim = func(x, y);
    double z;
    double counter=0;

    while (T>tF) {
        int i=1;
        while(i<=30) {
            x=x+fRand(-0.5,0.5);
            y=y+fRand(-0.5,0.5);
            z=func(x,y);
            if (z<minim || (accept(z,minim,T,d)>(fRand(0,1)))) {
                minim=z;
                xm=x;
                ym=y;
            }
            i=i+1;
        }
        counter=counter+1;
        T=T*a;
    }

    cout<<"min: "<<minim<<" x: "<<xm<<" y: "<<ym<<endl;
    return 0;
}

如何才能让它达到解决方案?

1 个答案:

答案 0 :(得分:1)

我认为在实施模拟退火算法时有一些问题是错误的。

在每次迭代中,您应该查看当前最小值的一些邻居z,并且如果f(z)至少你也可以接受新点,但有接受概率函数。

问题在于,在accept函数中,参数d太低了 - 它将始终返回0.0并且永远不会触发接受条件。尝试类似1e-5的内容;它不必在物理上是正确的,它只需要在降低温度的同时降低。

在更新外循环中的温度后,你应该放x=xmy=ym,然后再做内循环或者不是搜索当前解决方案的邻居,你基本上会随意乱走(你也没有检查任何边界。)

这样做,我通常得到一些像这样的输出:

min: 8.25518e-05 x: 2.0082 y: 0.996092

希望它有所帮助。