今天数学建模课讲了模拟退火~
目录
前言
模拟退火、 遗传算法这些大一时候听到的高大上的词语,终于在限选课(必须选的选修课,大一我选了,没做作业想水过去结果给挂了,大二不能申请免修淦)上学到了这两种“智能算法”。上一节课讲的遗传算法,当天就打了400+行,但是一直debug,问题不断。。。
这节课讲的模拟退火要简单许多,特此打了代码。关于模拟退火的教程,网上已经很多了,都是框架的东西,这里把实例分享给大家,结合实例学起来会好很多。
待求函数
老师的结果
效果很好,but没有给出源码,自己尝试打了一下。
我的代码
#include<iostream>
#include<cmath>
#include<random>
#include<time.h>
using namespace std;
//---------------------------FUNCTION-------------------------//
double func(double); //待测函数
void LinearAnneal(double&,double); //线性退火
void ExponentialAnneal(double&,double); //指数退火
void ClassicalAnneal(double&,double,double); //经典退火
void RapidAnneal(double&,double,double,double); //快速退火
void Initialize(); //参数初始化
double EvaluationFunc(double); //评价函数
double Jump(double,double,double,double);
//-------------------------GlobalVariate----------------------//
double T,T0,TE; //当前温度,初始温度,最终接受温度
double Value; //最优状态
double ans;
double upper,lower;
int times;
int main()
{
Initialize();
double newans;
while(T>TE)
{
newans=ans+Jump(upper,lower,T0,T);
while(newans>upper || newans<lower)
{
newans=ans+Jump(upper,lower,T0,T);
}
if(EvaluationFunc(newans)<EvaluationFunc(ans))
{
ans=newans;
if(EvaluationFunc(newans)<EvaluationFunc(Value))Value=newans;
}
else
{
double p=1-(EvaluationFunc(ans)-EvaluationFunc(newans))/T;
if((rand()%1000)/1000.0<=p)ans=newans;
}
ExponentialAnneal(T,0.999);
// LinearAnneal(T,0.1);
// ClassicalAnneal(T,T0,times++);
// RapidAnneal(T,T0,times++,0.98);
cout<<"Temprature:"<<T<<","<<"\tx="<<ans<<"\ty="<<func(ans)<<"\n";
}
cout<<"\n=====================================\nans:"<<ans<<"\tvalue:"<<func(ans)<<"\nbest ans:"<<Value<<"\tbest value:"<<func(Value)<<"\nstandard ans:"<<1.850736<<"\tstandard value:"<<func(1.850736);
system("pause");
return 0;
}
double Jump(double upper,double lower,double t0,double t)
{
double a=(rand()%(int)((upper-lower)));
a*=pow(-1,rand()%2);
return abs(a)>0.01?a:0.01*pow(-1,rand()%2);
}
double EvaluationFunc(double x)
{
return -func(x);
}
void Initialize()
{
srand(time(0));
T=T0=1000;TE=0.1;
Value=ans=((rand())%300)/100.0-1;
upper=2;
lower=-1;
times=1;
}
double func(double x)
{
return x*sin(10*3.1415*x)+2;
}
void LinearAnneal(double& t,double delta) //线性退火
{
t-=delta;
}
void ExponentialAnneal(double& t,double alpha) //指数退火,alpha∈(0.8,0.99)
{
t*=alpha;
}
void ClassicalAnneal(double& t,double t0,double time) //经典退火
{
t=t0/(log(time+1));
}
void RapidAnneal(double& t,double t0,double time,double alpha) //快速退火
{
t=t0/(1+alpha*time);
}
说明
说实话,这个代码的效果在我看来并不好,一些疑问请教了老师。
总结
这类智能算法,参数的设置都很关键,自己也是萌新,如果有大佬指教,非常高兴!!