00001
00002
00003
00004
00005 #if defined(unix) || defined(__unix) || defined(__unix__)
00006
00007
00008
00009
00010
00011 #define _INCLUDE_POSIX_SOURCE
00012 #endif
00013 #include "cddefines.h"
00014 #include "version.h"
00015 #include "optimize.h"
00016 #ifdef __unix
00017 #include <stddef.h>
00018 #include <sys/types.h>
00019 #include <sys/wait.h>
00020 #include <unistd.h>
00021 #endif
00022
00023 #define F0 1.4142136f
00024 #define F1 0.7071068f
00025 #define F2 0.1f
00026
00027
00028
00029
00030
00031
00032
00033 STATIC void phygrm(realnum a2[][LIMPAR],long);
00034 STATIC void wr_continue(realnum,long,realnum a2[][LIMPAR],const realnum[],const realnum[],
00035 const realnum[],const realnum[],realnum,realnum,realnum,long,long,const realnum[],
00036 const realnum[],const char[],const char[],const char[],const char*);
00037 STATIC void rd_continue(realnum*,long*,realnum a2[][LIMPAR],realnum[],realnum[],realnum[],realnum[],
00038 realnum*,realnum*,realnum*,long*,long*,realnum[],realnum[],char[],char[],char[],const char*);
00039 #ifdef __unix
00040 STATIC void cpfile(const char*);
00041 STATIC void wr_block(void*,size_t,const char*);
00042 STATIC void rd_block(void*,size_t,const char*);
00043 #endif
00044
00045
00046 void optimize_phymir(realnum xc[],
00047 realnum del[],
00048 long int nvarPhymir,
00049 realnum *ymin,
00050 realnum toler)
00051 {
00052 #define DELTA(i,j) (((i) == (j)) ? 1.f : 0.f)
00053
00054 char chDum1[STDLEN],
00055 chDum2[STDLEN],
00056 chDum3[STDLEN];
00057 bool lgFinish,
00058 lgNegd2,
00059 lgNewCnt,
00060 lgRead;
00061 long int i,
00062 imax,
00063 j,
00064 jj,
00065 jmin=0,
00066 limcp,
00067 nvarcp;
00068 realnum a2[LIMPAR][LIMPAR],
00069 amax,
00070 c1[LIMPAR],
00071 c2[LIMPAR],
00072 d1,
00073 d2,
00074 diff,
00075 dmax=0.f,
00076 dold=0.f,
00077 r1,
00078 r2,
00079 sgn,
00080 temp,
00081 vers,
00082 vpusedPhymir,
00083 xcold[LIMPAR],
00084 xhlp[LIMPAR],
00085 xnrm,
00086 xp[LIMPAR][2*LIMPAR + 1],
00087 yp[2*LIMPAR + 1];
00088 # ifdef __unix
00089 long int currentCPU;
00090 int stat;
00091 char fnam1[20],
00092 fnam2[20];
00093 pid_t pid;
00094 # endif
00095
00096 DEBUG_ENTRY( "optimize_phymir()" );
00097
00098 if( nvarPhymir > LIMPAR )
00099 {
00100 fprintf( ioQQQ, "optimize_phymir: too many parameters are varied, increase LIMPAR\n" );
00101 cdEXIT(EXIT_FAILURE);
00102 }
00103
00104
00105 memset( chDum1, '\0', STDLEN );
00106 memset( chDum2, '\0', STDLEN );
00107 memset( chDum3, '\0', STDLEN );
00108
00109 for( i=0; i < LIMPAR; ++i )
00110 {
00111 c1[i] = -FLT_MAX;
00112 c2[i] = -FLT_MAX;
00113 xcold[i] = -FLT_MAX;
00114 for( j=0; j < LIMPAR; ++j )
00115 {
00116 a2[i][j] = -FLT_MAX;
00117 }
00118 }
00119
00120 optimize.nOptimiz = 0;
00121 # ifdef __unix
00122 currentCPU = 0;
00123 # endif
00124 lgFinish = false;
00125 lgRead = optimize.lgOptCont;
00126 if( optimize.lgOptCont )
00127 goto L_20;
00128
00129
00130 dmax = 0.f;
00131 for( i=0; i < nvarPhymir; i++ )
00132 {
00133 temp = (realnum)fabs(del[i]);
00134 dmax = MAX2(dmax,temp);
00135 }
00136
00137 dold = dmax;
00138 for( i=0; i < nvarPhymir; i++ )
00139 {
00140 xcold[i] = xc[i] + 10.f*toler;
00141 c1[i] = (realnum)fabs(del[i])/dmax;
00142 c2[i] = c1[i];
00143 xp[i][0] = xc[i];
00144 optimize.vparm[0][i] = xc[i];
00145
00146 if( optimize.lgParallel )
00147 {
00148 vpusedPhymir = MIN2(optimize.vparm[0][i],optimize.varang[i][1]);
00149 vpusedPhymir = MAX2(vpusedPhymir,optimize.varang[i][0]);
00150 optimize.varmax[i] = MAX2(optimize.varmax[i],vpusedPhymir);
00151 optimize.varmin[i] = MIN2(optimize.varmin[i],vpusedPhymir);
00152 }
00153 }
00154 # ifdef __unix
00155 if( optimize.lgParallel )
00156 {
00157
00158 fflush(NULL);
00159 pid = fork();
00160 if( pid == 0 )
00161 {
00162
00163 sprintf(fnam1,"chi2_%ld",0L);
00164 sprintf(fnam2,"output_%ld",0L);
00165
00166 ioQQQ = open_data( fnam2, "w", AS_LOCAL_ONLY );
00167
00168 yp[0] = FLT_MAX;
00169 wr_block(&yp[0],(size_t)sizeof(realnum),fnam1);
00170 yp[0] = (realnum)optimize_func(xc);
00171 wr_block(&yp[0],(size_t)sizeof(realnum),fnam1);
00172 fclose( ioQQQ );
00173 ioQQQ = NULL;
00174 cdEXIT(EXIT_SUCCESS);
00175 }
00176 else
00177 {
00178
00179 pid = wait(&stat);
00180 sprintf(fnam1,"chi2_%ld",0L);
00181 sprintf(fnam2,"output_%ld",0L);
00182 rd_block(&yp[0],(size_t)sizeof(realnum),fnam1);
00183 remove(fnam1);
00184 cpfile(fnam2);
00185 remove(fnam2);
00186 }
00187
00188 optimize.nOptimiz++;
00189 }
00190 else
00191 {
00192 yp[0] = (realnum)optimize_func(xc);
00193 }
00194 # else
00195
00196 yp[0] = (realnum)optimize_func(xc);
00197 # endif
00198 *ymin = yp[0];
00199 jmin = 0;
00200
00201 L_10:
00202 for( i=0; i < nvarPhymir; i++ )
00203 {
00204 for( j=0; j < nvarPhymir; j++ )
00205 {
00206 a2[j][i] = DELTA(i,j);
00207 }
00208 }
00209
00210 L_20:
00211 if( lgRead )
00212 {
00213 rd_continue(&vers,&limcp,a2,c1,c2,xc,xcold,&dmax,&dold,ymin,&nvarcp,&optimize.nOptimiz,
00214 optimize.varmax,optimize.varmin,chDum1,chDum2,chDum3,CNTFILE);
00215 if( nvarcp != nvarPhymir )
00216 {
00217 printf( "optimize continue - wrong number of free parameters, sorry\n" );
00218 cdEXIT(EXIT_FAILURE);
00219 }
00220 for( i=0; i < nvarPhymir; i++ )
00221 {
00222 xp[i][0] = xc[i];
00223 }
00224 yp[0] = *ymin;
00225 jmin = 0;
00226 lgRead = false;
00227 }
00228 else
00229 {
00230
00231 strncpy(chDum1,t_version::Inst().chDate,STDLEN-1);
00232 strncpy(chDum2,t_version::Inst().chVersion,STDLEN-1);
00233 strncpy(chDum3,cpu.host_name(),STDLEN-1);
00234 wr_continue(VRSNEW,LIMPAR,a2,c1,c2,xc,xcold,dmax,dold,*ymin,nvarPhymir,optimize.nOptimiz,
00235 optimize.varmax,optimize.varmin,chDum1,chDum2,chDum3,CNTFILE);
00236 }
00237
00238 if( lgFinish )
00239 {
00240 return;
00241 }
00242
00243 if( optimize.nOptimiz >= optimize.nIterOptim )
00244 {
00245 fprintf( ioQQQ, " Optimizer exceeding maximum iterations.\n This can be reset with the OPTIMIZE ITERATIONS command.\n" );
00246 return;
00247 }
00248
00249 for( j=0; j < nvarPhymir; j++ )
00250 {
00251 sgn = 1.f;
00252 for( jj=2*j+1; jj <= 2*j+2; jj++ )
00253 {
00254 sgn = -sgn;
00255 for( i=0; i < nvarPhymir; i++ )
00256 {
00257 xp[i][jj] = xc[i] + sgn*dmax*c2[j]*a2[j][i];
00258 xhlp[i] = xp[i][jj];
00259 optimize.vparm[0][i] = xhlp[i];
00260
00261 if( optimize.lgParallel )
00262 {
00263 vpusedPhymir = MIN2(optimize.vparm[0][i],optimize.varang[i][1]);
00264 vpusedPhymir = MAX2(vpusedPhymir,optimize.varang[i][0]);
00265 optimize.varmax[i] = MAX2(optimize.varmax[i],vpusedPhymir);
00266 optimize.varmin[i] = MIN2(optimize.varmin[i],vpusedPhymir);
00267 }
00268 }
00269 # ifdef __unix
00270 if( optimize.lgParallel )
00271 {
00272 currentCPU++;
00273 if( currentCPU > optimize.useCPU )
00274 {
00275
00276 pid = wait(&stat);
00277 currentCPU--;
00278 }
00279
00280 fflush(NULL);
00281 pid = fork();
00282 if( pid == 0 )
00283 {
00284
00285 sprintf(fnam1,"chi2_%ld",jj);
00286 sprintf(fnam2,"output_%ld",jj);
00287
00288 ioQQQ = open_data( fnam2, "w", AS_LOCAL_ONLY );
00289
00290 yp[jj] = FLT_MAX;
00291 wr_block(&yp[jj],(size_t)sizeof(realnum),fnam1);
00292 yp[jj] = (realnum)optimize_func(xhlp);
00293 wr_block(&yp[jj],(size_t)sizeof(realnum),fnam1);
00294 fclose( ioQQQ );
00295 ioQQQ = NULL;
00296 cdEXIT(EXIT_SUCCESS);
00297 }
00298
00299 optimize.nOptimiz++;
00300 }
00301 else
00302 {
00303 yp[jj] = (realnum)optimize_func(xhlp);
00304 }
00305 # else
00306
00307 yp[jj] = (realnum)optimize_func(xhlp);
00308 # endif
00309 }
00310 }
00311 # ifdef __unix
00312
00313 if( optimize.lgParallel )
00314 {
00315 while( currentCPU > 0 )
00316 {
00317 pid = wait(&stat);
00318 currentCPU--;
00319 }
00320 }
00321 # endif
00322
00323 for( jj=1; jj <= 2*nvarPhymir; jj++ )
00324 {
00325 # ifdef __unix
00326 if( optimize.lgParallel )
00327 {
00328 sprintf(fnam1,"chi2_%ld",jj);
00329 sprintf(fnam2,"output_%ld",jj);
00330 rd_block(&yp[jj],(size_t)sizeof(realnum),fnam1);
00331 remove(fnam1);
00332 cpfile(fnam2);
00333 remove(fnam2);
00334 }
00335 # endif
00336 if( yp[jj] < *ymin )
00337 {
00338 *ymin = yp[jj];
00339 jmin = jj;
00340 }
00341 }
00342
00343 lgNewCnt = jmin > 0;
00344
00345 lgNegd2 = false;
00346 xnrm = 0.f;
00347 for( i=0; i < nvarPhymir; i++ )
00348 {
00349 d1 = yp[2*i+2] - yp[2*i+1];
00350 d2 = 0.5f*yp[2*i+2] - yp[0] + 0.5f*yp[2*i+1];
00351 if( d2 <= 0.f )
00352 lgNegd2 = true;
00353 xhlp[i] = -dmax*c2[i]*(MAX2(MIN2((0.25f*d1)/MAX2(d2,1.e-10f),F0),-F0) - DELTA(2*i+1,jmin) + DELTA(2*i+2,jmin));
00354 xnrm += POW2(xhlp[i]);
00355 }
00356 xnrm = (realnum)sqrt(xnrm);
00357
00358 imax = 0;
00359 amax = 0.f;
00360 for( j=0; j < nvarPhymir; j++ )
00361 {
00362 for( i=0; i < nvarPhymir; i++ )
00363 {
00364 if( xnrm > 0.f )
00365 {
00366 if( j == 0 )
00367 {
00368 a2[0][i] *= xhlp[0];
00369 }
00370 else
00371 {
00372 a2[0][i] += xhlp[j]*a2[j][i];
00373 a2[j][i] = DELTA(i,j);
00374 if( j == nvarPhymir-1 && (realnum)fabs(a2[0][i]) > amax )
00375 {
00376 imax = i;
00377 amax = (realnum)fabs(a2[0][i]);
00378 }
00379 }
00380 }
00381 else
00382 {
00383 a2[j][i] = DELTA(i,j);
00384 }
00385 }
00386 }
00387
00388 if( imax > 0 )
00389 {
00390 a2[imax][0] = 1.f;
00391 a2[imax][imax] = 0.f;
00392 }
00393
00394 phygrm(a2,nvarPhymir);
00395
00396
00397 for( i=0; i < nvarPhymir; i++ )
00398 {
00399 c2[i] = 0.f;
00400 for( j=0; j < nvarPhymir; j++ )
00401 {
00402 c2[i] += POW2(a2[i][j]/c1[j]);
00403 }
00404 c2[i] = 1.f/sqrt(c2[i]);
00405 xc[i] = xp[i][jmin];
00406 xp[i][0] = xc[i];
00407 }
00408 yp[0] = yp[jmin];
00409 jmin = 0;
00410
00411 if( lgNegd2 )
00412 {
00413
00414
00415
00416 r1 = F1;
00417 r2 = F1;
00418 }
00419 else
00420 {
00421 r1 = F2;
00422 if( lgNewCnt )
00423 {
00424
00425 r2 = sqrt(1.f/F1);
00426 }
00427 else
00428 {
00429
00430
00431 r2 = sqrt(F1);
00432 }
00433 }
00434 dmax = MIN2(MAX2(xnrm/c2[0],dmax*r1),dmax*r2);
00435
00436 dmax = MIN2(dmax,dold);
00437
00438 if( dmax > toler )
00439 goto L_20;
00440
00441 diff = 0.f;
00442 for( i=0; i < nvarPhymir; i++ )
00443 {
00444 diff += POW2(xc[i] - xcold[i]);
00445 xcold[i] = xc[i];
00446 c2[i] = c1[i];
00447 }
00448 diff = sqrt(diff);
00449 dmax = dold;
00450 lgFinish = diff <= toler;
00451 goto L_10;
00452 # undef DELTA
00453 }
00454
00455 STATIC void phygrm(realnum a[][LIMPAR],
00456 long int n)
00457 {
00458 long int i,
00459 j,
00460 k;
00461 realnum ip;
00462
00463 DEBUG_ENTRY( "phygrm()" );
00464
00465
00466 for( i=0; i < n; i++ )
00467 {
00468 ip = 0.f;
00469 for( k=0; k < n; k++ )
00470 ip += POW2(a[i][k]);
00471 ip = sqrt(ip);
00472 for( k=0; k < n; k++ )
00473 a[i][k] /= ip;
00474 for( j=i+1; j < n; j++ )
00475 {
00476 ip = 0.f;
00477 for( k=0; k < n; k++ )
00478 ip += a[i][k]*a[j][k];
00479 for( k=0; k < n; k++ )
00480 a[j][k] -= ip*a[i][k];
00481 }
00482 }
00483 return;
00484 }
00485
00486 STATIC void wr_continue(realnum vers,
00487 long dim,
00488 realnum a2[][LIMPAR],
00489 const realnum c1[],
00490 const realnum c2[],
00491 const realnum xc[],
00492 const realnum xcold[],
00493 realnum dmax,
00494 realnum dold,
00495 realnum ymin,
00496 long nvar,
00497 long noptim,
00498 const realnum varmax[],
00499 const realnum varmin[],
00500 const char chDum1[],
00501 const char chDum2[],
00502 const char chDum3[],
00503 const char *fnam)
00504 {
00505 bool lgErr;
00506 int res;
00507 size_t num;
00508 FILE *fdes;
00509
00510 DEBUG_ENTRY( "wr_continue()" );
00511
00512 try
00513 {
00514 fdes = open_data( fnam, "wb", AS_LOCAL_ONLY );
00515 }
00516 catch( cloudy_exit )
00517 {
00518 return;
00519 }
00520 lgErr = false;
00521 num = 1;
00522 lgErr = lgErr || ( fwrite(&vers,sizeof(realnum),num,fdes) != num );
00523 lgErr = lgErr || ( fwrite(&dim,sizeof(long),num,fdes) != num );
00524 num = (size_t)(LIMPAR*LIMPAR);
00525 lgErr = lgErr || ( fwrite(a2,sizeof(realnum),num,fdes) != num );
00526 num = (size_t)LIMPAR;
00527 lgErr = lgErr || ( fwrite(c1,sizeof(realnum),num,fdes) != num );
00528 lgErr = lgErr || ( fwrite(c2,sizeof(realnum),num,fdes) != num );
00529 lgErr = lgErr || ( fwrite(xc,sizeof(realnum),num,fdes) != num );
00530 lgErr = lgErr || ( fwrite(xcold,sizeof(realnum),num,fdes) != num );
00531 num = 1;
00532 lgErr = lgErr || ( fwrite(&dmax,sizeof(realnum),num,fdes) != num );
00533 lgErr = lgErr || ( fwrite(&dold,sizeof(realnum),num,fdes) != num );
00534 lgErr = lgErr || ( fwrite(&ymin,sizeof(realnum),num,fdes) != num );
00535 lgErr = lgErr || ( fwrite(&nvar,sizeof(long),num,fdes) != num );
00536 lgErr = lgErr || ( fwrite(&noptim,sizeof(long),num,fdes) != num );
00537 num = (size_t)LIMPAR;
00538 lgErr = lgErr || ( fwrite(varmax,sizeof(realnum),num,fdes) != num );
00539 lgErr = lgErr || ( fwrite(varmin,sizeof(realnum),num,fdes) != num );
00540 num = (size_t)STDLEN;
00541 lgErr = lgErr || ( fwrite(chDum1,sizeof(char),num,fdes) != num );
00542 lgErr = lgErr || ( fwrite(chDum2,sizeof(char),num,fdes) != num );
00543 lgErr = lgErr || ( fwrite(chDum3,sizeof(char),num,fdes) != num );
00544 fclose(fdes);
00545 if( lgErr )
00546 {
00547 printf( "error writing file: %s\n",fnam );
00548 res = remove(fnam);
00549
00550 if( false) fprintf(ioQQQ,"%i\n", res );
00551 }
00552 return;
00553 }
00554
00555 STATIC void rd_continue(realnum *vers,
00556 long *dim,
00557 realnum a2[][LIMPAR],
00558 realnum c1[],
00559 realnum c2[],
00560 realnum xc[],
00561 realnum xcold[],
00562 realnum *dmax,
00563 realnum *dold,
00564 realnum *ymin,
00565 long *nvar,
00566 long *noptim,
00567 realnum varmax[],
00568 realnum varmin[],
00569 char chDum1[],
00570 char chDum2[],
00571 char chDum3[],
00572 const char *fnam)
00573 {
00574 bool lgErr;
00575 size_t num;
00576 FILE *fdes;
00577
00578 DEBUG_ENTRY( "rd_continue()" );
00579
00580 fdes = open_data( fnam, "rb", AS_LOCAL_ONLY );
00581 lgErr = false;
00582 num = 1;
00583 lgErr = lgErr || ( fread(vers,sizeof(realnum),num,fdes) != num );
00584 if( lgErr || *vers != VRSNEW )
00585 {
00586 printf( "optimize continue - file has incompatible version, sorry\n" );
00587 cdEXIT(EXIT_FAILURE);
00588 }
00589 lgErr = lgErr || ( fread(dim,sizeof(long),num,fdes) != num );
00590 if( lgErr || *dim != LIMPAR )
00591 {
00592 printf( "optimize continue - arrays have wrong dimension, sorry\n" );
00593 cdEXIT(EXIT_FAILURE);
00594 }
00595 num = (size_t)(LIMPAR*LIMPAR);
00596 lgErr = lgErr || ( fread(a2,sizeof(realnum),num,fdes) != num );
00597 num = (size_t)LIMPAR;
00598 lgErr = lgErr || ( fread(c1,sizeof(realnum),num,fdes) != num );
00599 lgErr = lgErr || ( fread(c2,sizeof(realnum),num,fdes) != num );
00600 lgErr = lgErr || ( fread(xc,sizeof(realnum),num,fdes) != num );
00601 lgErr = lgErr || ( fread(xcold,sizeof(realnum),num,fdes) != num );
00602 num = 1;
00603 lgErr = lgErr || ( fread(dmax,sizeof(realnum),num,fdes) != num );
00604 lgErr = lgErr || ( fread(dold,sizeof(realnum),num,fdes) != num );
00605 lgErr = lgErr || ( fread(ymin,sizeof(realnum),num,fdes) != num );
00606 lgErr = lgErr || ( fread(nvar,sizeof(long),num,fdes) != num );
00607 lgErr = lgErr || ( fread(noptim,sizeof(long),num,fdes) != num );
00608 num = (size_t)LIMPAR;
00609 lgErr = lgErr || ( fread(varmax,sizeof(realnum),num,fdes) != num );
00610 lgErr = lgErr || ( fread(varmin,sizeof(realnum),num,fdes) != num );
00611 num = (size_t)STDLEN;
00612 lgErr = lgErr || ( fread(chDum1,sizeof(char),num,fdes) != num );
00613 lgErr = lgErr || ( fread(chDum2,sizeof(char),num,fdes) != num );
00614 lgErr = lgErr || ( fread(chDum3,sizeof(char),num,fdes) != num );
00615 fclose(fdes);
00616 if( lgErr )
00617 {
00618 printf( "error reading file: %s\n",fnam );
00619 cdEXIT(EXIT_FAILURE);
00620 }
00621 return;
00622 }
00623
00624 #ifdef __unix
00625
00626 STATIC void cpfile(const char *fnam)
00627 {
00628 char chr;
00629
00630 FILE *fdes;
00631
00632 DEBUG_ENTRY( "cpfile()" );
00633
00634
00635
00636 fdes = open_data( fnam, "r", AS_LOCAL_ONLY_TRY );
00637 if( fdes == NULL )
00638 return;
00639 chr = (char)fgetc(fdes);
00640 while( ! feof(fdes) )
00641 {
00642 fputc( chr , ioQQQ );
00643 chr = (char)fgetc(fdes);
00644 }
00645 fclose(fdes);
00646 return;
00647 }
00648
00649 STATIC void wr_block(void *ptr,
00650 size_t len,
00651 const char *fnam)
00652 {
00653 FILE *fdes;
00654
00655 DEBUG_ENTRY( "wr_block()" );
00656
00657
00658
00659 fdes = open_data( fnam, "wb", AS_LOCAL_ONLY );
00660 if( fwrite(ptr,len,(size_t)1,fdes) != 1 ) {
00661 printf( "error writing on file: %s\n",fnam );
00662 fclose(fdes);
00663 cdEXIT(EXIT_FAILURE);
00664 }
00665 fclose(fdes);
00666 return;
00667 }
00668
00669 STATIC void rd_block(void *ptr,
00670 size_t len,
00671 const char *fnam)
00672 {
00673 FILE *fdes;
00674
00675 DEBUG_ENTRY( "rd_block()" );
00676
00677
00678
00679 fdes = open_data( fnam, "rb", AS_LOCAL_ONLY );
00680 if( fread(ptr,len,(size_t)1,fdes) != 1 ) {
00681 printf( "error reading on file: %s\n",fnam );
00682 fclose(fdes);
00683 cdEXIT(EXIT_FAILURE);
00684 }
00685 fclose(fdes);
00686 return;
00687 }
00688
00689 #endif