00001
00002
00004
00005
00006
00007
00008
00009
00011
00012 #include "general.h"
00013
00014 #include "scparser.h"
00015
00016 #ifndef _GENERAL_H
00017
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <time.h>
00021 #include <math.h>
00022 #define ASSERT(a) ((void)0)
00023 #define ERROR(s) puts(s)
00024 #define Max(a,b) ((a) > (b)? (a):(b))
00025 #define Min(a,b) ((a) > (b)? (b):(a))
00026
00027 #endif
00028
00029 #define MAXLIN 5 //Maximum iterations within a line search
00030 #define MXFCON 2 //Maximum iterations before F can be decreased
00031
00032
00033 #define MAXREPEAT 10 //Maximum iterations when energy and gradient are identical
00034
00035
00036 class MDFrame *__conj_simframe;
00037
00038
00039
00040
00041
00042
00043 static double *s,
00044 *rss,*rsg,
00045 *ginit,
00046 *xopt,*gopt;
00047
00048 #ifdef __cplusplus
00049 extern "C" void CGRelax(void (*func)(int,double*,double *, double*),
00050 int n,double acc,int maxfn,double dfpred,
00051 double x[],double g[],double *f, double *buffer);
00052 #endif
00053
00054 #define MP_Sync() {}
00055 #define MP_BeginMasterOnly() {}
00056 #define MP_EndMasterOnly() {}
00057 #define MP_Free(s) free(s)
00058
00059 void NumGrad(double (*func)(int,double*),int n, double *x, double *g)
00060 {
00061 int i;
00062 const double dt=1e-8;
00063 for(i=0;i<n;i++)
00064 {
00065 double f1, f2;
00066 x[i]+=dt;
00067 f1=func(n,x);
00068 x[i]-=dt+dt;
00069 f2=func(n,x);
00070 x[i]-=dt;
00071 g[i]=(f1-f2)/2/dt;
00072 }
00073 }
00074
00075
00076
00077
00078
00079
00080
00081 void CGRelax(void (*func)(int,double*,double *, double*),
00082 int n,double acc,int maxfn,double dfpred,
00083 double x[],double g[],double *f, double *buffer)
00084 {
00085 register int i;
00086 int iretry,
00087 iterc,
00088 iterfm,
00089 iterrs,
00090 ncalls,
00091 nfbeg,
00092 nfopt;
00093 register double beta,ddspln,dfpr,finit,fmin,gamden,gama,gfirst,gmin,gnew,
00094 gspln,gsqrd,sbound,step,stepch,stmin,sum,temp;
00095
00096 int n0, n1;
00097
00098
00099 int nrepeat;
00100 double f_old, sum_old;
00101
00102 nrepeat = 0;
00103
00104 n0=0; n1=n;
00105
00106
00107 if(buffer==NULL)
00108 {
00109
00110 s=(double *)realloc(s,sizeof(double)*n*6);
00111 if(s==NULL){ ERROR("Out of memory in CGRelax"); abort(); }
00112 }
00113 else s=buffer;
00114
00115 rss=s+n;
00116 rsg=rss+n;
00117 ginit=rsg+n;
00118 xopt=ginit+n;
00119 gopt=xopt+n;
00120
00121 ddspln=gamden=0;
00122
00123 iterc=iterfm=iterrs=0;
00124
00125 func(n,x,f,g);ncalls=1;
00126
00127 INFO("relax: 1st potential call finished.");
00128
00129
00130
00131 for(i=n0;i<n1;i++) s[i]=-g[i];
00132
00133
00134 for(sum=0,i=0;i<n;i++)
00135 sum+=g[i]*g[i];
00136
00137
00138
00139 f_old = *f; sum_old = sum;
00140
00141 if(sum<=acc) goto l_return;
00142
00143 gnew=-sum;
00144 fmin=*f;
00145 gsqrd=sum;
00146 nfopt=ncalls;
00147 for(i=n0;i<n1;i++)
00148 {
00149 xopt[i]=x[i];
00150 gopt[i]=g[i];
00151 }
00152
00153
00154
00155
00156
00157
00158 dfpr=dfpred;
00159 stmin=dfpred/gsqrd;
00160
00161 for(;;)
00162 {
00163 iterc++;
00164
00165
00166
00167
00168
00169
00170 finit=*f;
00171 for(i=n0;i<n1;i++)
00172 {
00173 ginit[i]=g[i];
00174 }
00175
00176
00177 gfirst=0;
00178 for(i=0;i<n;i++)
00179 {
00180 gfirst+=s[i]*g[i];
00181 }
00182
00183 if(gfirst >=0)
00184 {
00185
00186 ERROR("CGRelax: Search direction is uphill.");
00187 goto l_return;
00188 }
00189 gmin=gfirst;
00190 sbound=-1;
00191 nfbeg=ncalls;
00192 iretry=-1;
00193
00194
00195
00196
00197 stepch=Min(stmin, fabs(dfpr/gfirst));
00198 stmin=0;
00199
00200
00201
00202 for(;;)
00203 {
00204 step=stmin+stepch;
00205 for(i=n0;i<n1;i++)
00206 {
00207 x[i]=xopt[i]+stepch*s[i];
00208 }
00209
00210 temp=0;
00211 for(i=0;i<n;i++)
00212 {
00213 temp=Max(temp,fabs(x[i]-xopt[i]));
00214 }
00215
00216 if(temp <= 0)
00217 {
00218
00219 if(ncalls > nfbeg+1 || fabs(gmin/gfirst) > 0.2)
00220 {
00221 ERROR("CGRelax: Line search aborted, "
00222 "possible error in gradient.");
00223 goto l_return;
00224 }
00225 else break;
00226 }
00227 ncalls++;
00228
00229 func(n,x,f,g);
00230
00231
00232
00233 for(gnew=sum=0,i=0;i<n;i++)
00234 {
00235 gnew+=s[i]*g[i];
00236 sum+=g[i]*g[i];
00237 }
00238
00239
00240
00241
00242
00243 if((*f < fmin || (*f==fmin && gnew/gmin>=-1)))
00244 {
00245 fmin=*f;
00246 gsqrd=sum;
00247 nfopt=ncalls;
00248 for(i=n0;i<n1;i++)
00249 {
00250 xopt[i]=x[i];
00251 gopt[i]=g[i];
00252 }
00253
00254 }
00255
00256 INFO_Printf("%10d %22.18e %22.18e\n",iterc,*f,sum);
00257
00258
00259 if( (f_old==*f)&&(sum_old==sum) )
00260 {
00261 nrepeat ++;
00262 }
00263 else
00264 {
00265 nrepeat = 0;
00266 f_old = *f; sum_old = sum;
00267 }
00268 if(nrepeat>=MAXREPEAT)
00269 {
00270 ERROR("CGRelax: getting stuck, stop...");
00271 goto l_return;
00272 }
00273
00274 if(*f<=fmin && sum <= acc) goto l_return;
00275
00276 if(ncalls>=maxfn)
00277 {
00278 ERROR("CGRelax: Too many iterations, stop...");
00279 goto l_return;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289 temp=(*f+*f-fmin-fmin)/stepch-gnew-gmin;
00290 ddspln=(gnew-gmin)/stepch;
00291 if(ncalls > nfopt) sbound=step;
00292 else
00293 {
00294 if(gmin*gnew <= 0) sbound=stmin;
00295 stmin=step;
00296 gmin=gnew;
00297 stepch=-stepch;
00298 }
00299 if(*f!=fmin) ddspln+=(temp+temp)/stepch;
00300
00301
00302
00303 if(gmin==0) break;
00304 if(ncalls >= nfbeg+1)
00305 {
00306 if(fabs(gmin/gfirst) <=0.2) break;
00307
00308 l_retry:
00309 if(ncalls >= nfopt+MAXLIN)
00310 {
00311 ERROR("CGRelax: Line search aborted, "
00312 "possible error in gradient.");
00313 goto l_return;
00314 }
00315 }
00316
00317
00318
00319
00320
00321
00322 stepch=0.5*(sbound-stmin);
00323 if(sbound < -0.5) stepch=9*stmin;
00324 gspln=gmin+stepch*ddspln;
00325 if(gmin*gspln<0) stepch*=gmin/(gmin-gspln);
00326 }
00327
00328 if(ncalls!=nfopt)
00329 {
00330 *f=fmin;
00331 for(i=n0;i<n1;i++)
00332 {
00333 x[i]=xopt[i];
00334 g[i]=gopt[i];
00335 }
00336
00337 }
00338
00339
00340 for(sum=0,i=0;i<n;i++)
00341 sum+=g[i]*ginit[i];
00342
00343 beta=(gsqrd-sum)/(gmin-gfirst);
00344
00345
00346
00347 if(fabs(beta*gmin) > 0.2*gsqrd)
00348 {
00349 iretry++;
00350 if(iretry<=0) goto l_retry;
00351 }
00352
00353
00354
00355 if(*f<finit) iterfm=iterc;
00356 else if(iterc >= iterfm+MXFCON)
00357 {
00358 ERROR("CGRelax: Cannot reduce value of F, aborting...");
00359 goto l_return;
00360 }
00361 dfpr=stmin*gfirst;
00362 if(iretry>0)
00363 {
00364 for(i=n0;i<n1;i++) s[i]=-g[i];
00365
00366 iterrs=0;
00367 continue;
00368 }
00369
00370 if(iterrs!=0 && iterc-iterrs<n && fabs(sum)<0.2*gsqrd)
00371 {
00372
00373
00374
00375
00376 for(gama=sum=0,i=0;i<n;i++)
00377 {
00378 gama+=g[i]*rsg[i];
00379 sum+=g[i]*rss[i];
00380 }
00381
00382
00383 gama/=gamden;
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 if(fabs(beta*gmin+gama*sum) < 0.2*gsqrd)
00395 {
00396
00397 for(i=n0;i<n1;i++) s[i]=-g[i]+beta*s[i]+gama*rss[i];
00398
00399 continue;
00400 }
00401 }
00402
00403 gamden=gmin-gfirst;
00404
00405 for(i=n0;i<n1;i++)
00406 {
00407 rss[i]=s[i];
00408 rsg[i]=g[i]-ginit[i];
00409 s[i]=-g[i]+beta*s[i];
00410 }
00411
00412
00413
00414
00415
00416
00417
00418 iterrs=iterc;
00419 }
00420 l_return:
00421
00422 if(buffer==NULL) MP_Free(s);
00423 }
00424
00425 #ifdef _TEST
00426
00427 #ifdef __cplusplus
00428 extern "C"
00429 {
00430 #endif
00431 void zxcgr_(void (*func)(int*,double*,double*,double*),
00432 int *n,double *acc,int *maxfn,double *dfpred,
00433 double x[],double g[],double *f,double w[],int *ier);
00434 #ifdef __cplusplus
00435 };
00436 #endif
00437
00438
00439 int ncalls;
00440 double acc=1e-10;
00441 #define Sqr(x) ((x)*(x))
00442 void values(int n, double *x, double *f, double *g)
00443 {
00444 ncalls++;
00445 ASSERT(n==2);
00446 *f=cos(x[0]-0.5)*cos(Sqr(x[1]+1))+Sqr(x[0]-0.5)/100;
00447 g[0]=-sin(x[0]-0.5)*cos(Sqr(x[1]+1))+2*(x[0]-0.5)/100;
00448 g[1]=-cos(x[0]-0.5)*sin(Sqr(x[1]+1))*2*(x[1]+1);
00449
00450
00451
00452 printf("Values(%f,%f)=%f(%f,%f)\n",x[0],x[1],*f,
00453 g[0]/sqrt(acc),g[1]/sqrt(acc));
00454 }
00455
00456 void fvalue(int *n, double *x, double *f, double *g)
00457 {
00458 values(*n,x,f,g);
00459 }
00460
00461 double X[2],G[2],F,W[100];
00462
00463
00464 int main()
00465 {
00466 double x0,x1;
00467 int n, maxfn;
00468 int ier;
00469 double dfpred;
00470
00471 srand(time(NULL));
00472 x0=rand()/100000000.0;
00473 x1=rand()/100000000.0;
00474 n=2;
00475 dfpred=0.02;
00476 maxfn=1000;
00477
00478 X[0]=x0;
00479 X[1]=x1;
00480 ncalls=0;
00481 zxcgr_(fvalue,&n,&acc,&maxfn,&dfpred,X,G,&F,W,&ier);
00482 printf("Output:%f(%f,%f)[%f,%f] <%d> ier=%d\n",
00483 F,X[0],X[1],G[0]/sqrt(acc),G[1]/sqrt(acc),ncalls,ier);
00484
00485 X[0]=x0;
00486 X[1]=x1;
00487 ncalls=0;
00488 CGRelax(values, n, acc, maxfn, dfpred,X,G,&F, NULL);
00489 printf("Output:%f(%f,%f)[%f,%f] <%d>\n",
00490 F,X[0],X[1],G[0]/sqrt(acc),G[1]/sqrt(acc),ncalls);
00491 return 0;
00492 }
00493
00494 #endif