📄 fsa.cpp
字号:
/* 功能:模拟退火反演算法 */
/* 文献:地球物理反演 */
/* 作者:王家映教授 */
/* 出版:高等教育出版社(第二版) */
/* 编程:蒋龙聪 */
/* 单位:中国地质大学(武汉)地球物理与空间信息 */
/* 专业:地球探测与信息技术 */
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
/* 功能:模拟退火反演算法 */
#define DS 0.99
#define ERRO 0.50
#define Lambda 6
#define LayerN 4
#define H 5
#define MarkT 10
#define MinT 0.001
#define POINTS 1001
#define SF 0.5
void SA(double,double);
double ranD(void);
double obfun(double[]);
double OBS[POINTS];
double Temperature;
FILE * SATXT;
double ranD(void)
{
double ranD=0.0;
ranD=(rand()%5000)/5000.0;
// ranD=0.1+(0.6-0.2)*ranD;
return(ranD);
}
double obfun(double x[])
{
double g[POINTS],b[201],r[POINTS];//定义数组
double dt=0.5,f0=60; //数组赋值
double t[3];//时间
double v[4];
double SUM=0.0;
int mx=1;
int i=0,j=0,nw=100;
double h[3]={50,20,50};
v[0]=x[0];
v[1]=x[1];
v[2]=x[2];
v[3]=x[3];
//初始化反射系数数组
for(i=0;i<POINTS;i++)
r[i]=0.0;
t[0]=2*h[0]/v[0];
j=(int)(1000*t[0]/dt);
r[j]=(v[1]-v[0])/(v[1]+v[0]);
for(i=1;i<MarkT;i++)
{
t[i]=t[i-1]+2*h[i]/v[i];
j=(int)(1000*t[i]/dt);
r[j]=(v[i+1]-v[i])/(v[i+1]+v[i]);
}
//求取子波
for(i=-nw;i<nw+1;i++)
{
double a=(0.001*3.1415926*f0*i*dt);
b[i+nw]=100.0*(1.0-2.0*a*a)*exp(-a*a);
}
//Convolution
for(i=0;i<POINTS;i++)//从第一道循环
{
double sum=0.0;
for(j=-nw;j<nw+1;j++)
{
if(i-j>=0&&i-j<POINTS)
sum=sum+b[j+nw]*r[i-j];
}
g[i]=sum;
}
for(i=0;i<POINTS;i++)
SUM+=sqrt((OBS[i]-g[i])*(OBS[i]-g[i]));
return(SUM);
}
/*采用保留局部最优解方式*/
void SA(double lbounds[],double ubounds[])
{
int MaxGen=0;
int Gen=0;
int Counter=0;
int i=0,j=0,k=0;
double R=0.0;
double E0=0.0;
double E1=0.0;
double DeltaE=0.0;
double P=0.0;
double T=0.0;
double Val=0.0;
double BestVal=0.0;
double Local[LayerN];
double Global[LayerN];
double CurSol[LayerN];
double NexSol[LayerN];
T=Temperature;
MaxGen=(int)(log(MinT/Temperature)/log(DS)+0.5);
MaxGen=MaxGen;
//第一步:随机选择初始值
for(i=0;i<(LayerN);i++)
{
CurSol[i]=(ubounds[i])*ranD();
// cout<<CurSol[i];
}
/*
for(i=0;i<LayerN;i++)
{
CurSol[i]=500+i*200;
}
*/
//初始化局部变量和全局变量值
for(i=0;i<(LayerN);i++)
{
Local[i]=CurSol[i];
Global[i]=CurSol[i];
}
//第二步:在某一温度下,对当前模型进行扰动,得到新的模型值NextSol
while(T>MinT)
{
Gen++;
for(i=0;i<MarkT;i++)
{
Counter++;
R=Gen/(2*MaxGen);
if( (int) ( ranD()+0.5 )==0 )
{
for(i=0;i<LayerN;i++)
NexSol[i]=CurSol[i]+(ubounds[i]-CurSol[i])*( pow( ranD()*(1.0-R),Lambda) );
}
else
{
for(i=0;i<LayerN;i++)
NexSol[i]=CurSol[i]-(CurSol[i]-lbounds[i])*( pow( ranD()*(1.0-R),Lambda) );
}
/*
if( (int) ( ranD()+0.5 )==0 )
{
for(i=0;i<LayerN;i++)
NexSol[i]=CurSol[i]+(ubounds[i]-lbounds[i])*( pow( ranD()*(1.0-R),Lambda) );
}
else
{
for(i=0;i<LayerN;i++)
NexSol[i]=CurSol[i]-(ubounds[i]-lbounds[i])*( pow( ranD()*(1.0-R),Lambda) );
}
*/
//判断是否为全局最优解
if(obfun(NexSol)<obfun(Global))
{
for(i=0;i<(LayerN);i++)
{
Local[i]=Global[i];
Global[i]=NexSol[i];
}
}
E1=obfun(NexSol);
E0=obfun(CurSol);
DeltaE=E1-E0;
P=exp(-DeltaE/T);
P=pow((1-H*P*E1/(E0*E0)),1/H);
// cout<<"DeltaE"<<DeltaE<<endl;
if(DeltaE<0)
{
for(i=0;i<(LayerN);i++)
CurSol[i]=NexSol[i];
}
//else if//( exp(-DeltaE/T)<ranD() )
else if(P<ranD())
{
for(i=0;i<(LayerN);i++)
CurSol[i]=NexSol[i];
}
Val=obfun(NexSol);
BestVal=obfun(Global);
fprintf(SATXT,"%10.6f %10.6f",Val,BestVal);
/* 把最优解输出到文件中去 */
if(Val<=ERRO||BestVal<=ERRO)
{
printf("寻找解得次数为:%5d\n",Counter);
/*
if ((salog = fopen("galog.txt","w"))==NULL)
{
exit(1);
}
*/
fprintf(SATXT,"\n\n");
for(i=0;i<(LayerN);i++)
fprintf(SATXT," %10.7f ",Global[i]);
// fclose(salog);
printf("Sucess\n");
exit(0);
}
//第三步:降低温度
T=T*DS;
// simulated(BestVal);
// cout<<" T= "<<T<<" Val= "<<Val<<" BestVal= "<<BestVal<<" Counter= "<<Counter <<endl;
}
// simulated(BestVal);
}
}
void main(void)
{
int i=0,j=0,k=0;
double tim=0.0,E1=0,E0=0,DeltaE=0;
double amptitude=0.0;
double Time[POINTS];
double CurSol[LayerN],NexSol[LayerN];
double lbound[LayerN]={1000,800,1000,1000};
double ubound[LayerN]={3000,1500,3000,3000};
srand((unsigned int)time(NULL));
/* 从文件中读取数据 */
FILE *INFILE;
if ((INFILE = fopen("result.txt","r"))==NULL)
{
printf("打开的文件不存在,请调试!\n");
exit(1);
}
for (i=0; i<POINTS; i++)
{
fscanf(INFILE, "%lf",&titude);
fscanf(INFILE, "%lf",&tim);
Time[i]=tim;
OBS[i]=amptitude;
}
for (i=0; i<POINTS; i++)
printf("F=%f Data=%f\n",Time[i],OBS[i]);
fclose(INFILE);
SATXT=fopen("simulate.txt","w");
/* 确定初始温度值 */
for(i=0;i<(LayerN);i++)
{
CurSol[i]=(ubound[i])*ranD();
fprintf(SATXT," %10.7f ",CurSol[i]);
}
// fprintf(salog," \n ");
for(i=0;i<LayerN;i++)
{
NexSol[i]=CurSol[i]+(2*ranD()-1)*SF;
}
E1=obfun(NexSol);
E0=obfun(CurSol);
DeltaE=E1-E0;
Temperature=-DeltaE/log(0.995);
printf("初始温度为:%f\n",Temperature);
SA(lbound,ubound);
fclose(SATXT);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -