Posted on 2008-09-28 13:59
魔のkyo 阅读(735)
评论(0) 编辑 收藏 引用 所属分类:
Algorithm
模拟退火的基本思想:
(1) 初始化:初始温度T(充分大),初始解状态S(是算法迭代的起点), 每个T值的迭代次数L
(2) 对k=1,……,L做第(3)至第6步:
(3) 产生新解S′
(4) 计算增量Δt′=C(S′)-C(S),其中C(S)为评价函数
(5) 若Δt′<0则接受S′作为新的当前解,否则以概率exp(-Δt′/T)接受S′作为新的当前解.
(6) 如果满足终止条件则输出当前解作为最优解,结束程序。
终止条件通常取为连续若干个新解都没有被接受时终止算法。
(7) T逐渐减少,且T->0,然后转第2步。
注:新解不是更优的时候以概率exp(-Δt′/T)接受S′作为新解的目的是“跳出极值点”,极值点未必是最值点,但极值点周围的解都没有当前解优,这就是温度高时不稳定的好处。
伪码:
double T=1e6;//视具体情况而定
const int L=100;
double bestC;//全局最优评价值,这里是越低越优
double newC,dt;
while(T>eps){
for(int i=0;i<L;i++){
newx=produce(x);//从旧的解产生新的解,生成算法可以和T相关,使得随着T在不断的减少,newx不断精确
newC=C(newx);
dt=newC-bestC;
if(dt<0 || exp(-dt/T)>frand() ){ //frand返回[0,1)上的随机数
bestC=min(bestC,newC);
x=newx;
}
}
T*=0.618;
}
再给一个zju2976的实例
//以各个点正下方做初始状态进行模拟退火
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
typedef long long ll;
typedef ll i64;
typedef vector<int> vi;
const int INF=0x3F3F3F3F;
#define mset(a,x) memset(a,x,sizeof(a))
#define ABS(a) ((a) >= 0 ? (a) : -(a))
#define Assert(x) if(!(x))do{cout<<1;}while(1)
#define dbg(x) cerr<<#x<<" : "<<x<<endl
ll gcd(ll a,ll b){ll r;while(b){r=a%b;a=b;b=r;}return a;}
//return a double value [0,1)
double frand()
{
return 1.0*rand()/RAND_MAX;
}
inline double sq(double x){return x*x;}
int n;
int X[105],Y[105],Z[105],I[105];
double res;
double maxe,e;
double calcE(int x,int y)
{
double res=0;
for(int i=0;i<n;i++){
res+=I[i]*Z[i]/pow((sq(x-X[i])+sq(y-Y[i])+sq(0-Z[i])),1.5);
}
return res;
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d%d%d",&X[i],&Y[i],&Z[i],&I[i]);
}
res=0;
for(int i=0;i<n;i++){
int x=X[i],y=Y[i];
maxe=calcE(x,y);
int flag;
double T=1e6;
do{
double dt;
flag=0;
e=calcE(x+1,y);
dt=maxe-e;
if(e>maxe || exp(-dt/T)>frand() ){ flag=1; maxe=max(maxe,e); x++; }
e=calcE(x,y+1);
dt=maxe-e;
if(e>maxe || exp(-dt/T)>frand() ){ flag=1; maxe=max(maxe,e); y++; }
e=calcE(x-1,y);
dt=maxe-e;
if(e>maxe || exp(-dt/T)>frand()){ flag=1; maxe=max(maxe,e); x--; }
e=calcE(x,y-1);
dt=maxe-e;
if(e>maxe || exp(-dt/T)>frand()){ flag=1; maxe=max(maxe,e); y--; }
T*=0.618;
}while(flag);
res=max(res,maxe);
}
printf("%.2lf\n",res);
}
}