00001 #ifndef __INCLUDE_SFIT_CC__ 00002 #define __INCLUDE_SFIT_CC__ 00003 #include "sfit.h" 00004 00005 int CCF2SFit::nmaxpars=10; 00006 bool CCF2SFit::MCsourceflag=0; 00007 00008 void CParInfo::Set(string nameset,double xset,double errorset, 00009 double xminset,double xmaxset){ 00010 strcpy(name,nameset.c_str()); 00011 currentx=xset; 00012 error=errorset; 00013 xmin=xminset; 00014 xmax=xmaxset; 00015 } 00016 CParInfo::CParInfo(){ 00017 name=new char[20]; 00018 } 00019 CParInfo::~CParInfo(){ 00020 delete [] name; 00021 } 00022 00023 void CCF2SFit::SetCalcFlag(int calcflagset){ 00024 calcflag=calcflagset; 00025 } 00026 00027 void CCF2SFit::SetMCSourceFlag(bool MCsourceflagset){ 00028 MCsourceflag=MCsourceflagset; 00029 } 00030 00031 void CCF2SFit::SetPar(string parstring,double xset){ 00032 int i; 00033 char parname[20]; 00034 strcpy(parname,parstring.c_str()); 00035 i=0; 00036 while(Misc::comparestrings(par[i]->name,parname)==0 && i<nmaxpars){ 00037 i+=1; 00038 } 00039 if(i<nmaxpars) par[i]->currentx=xset; 00040 else printf("Can not set %s, parameter with that name does not exist\n", 00041 parname); 00042 } 00043 00044 void CCF2SFit::SetPar(string parstring,double xset,double errorset, 00045 double xminset,double xmaxset){ 00046 int i; 00047 char parname[20]; 00048 strcpy(parname,parstring.c_str()); 00049 i=0; 00050 while(Misc::comparestrings(par[i]->name,parname)==0 && i<nmaxpars){ 00051 i+=1; 00052 } 00053 if(i<nmaxpars) par[i]->Set(parstring,xset,errorset,xminset,xmaxset); 00054 else printf("Can not set %s, parameter with that name does not exist\n", 00055 parname); 00056 } 00057 00058 void CCF2SFit::AddPar(string parstring,double xset,double errorset, 00059 double xminset,double xmaxset){ 00060 if(npars>nfreepars) SwitchPars(nfreepars,npars); 00061 nfreepars+=1; 00062 npars+=1; 00063 if(nfreepars<nmaxpars){ 00064 par[nfreepars-1]->Set(parstring,xset,errorset,xminset,xmaxset); 00065 parameter::set(sourcecalc->spars,parstring,xset); 00066 } 00067 else{ 00068 printf("Too Many Parameters! Increase static int CCF2SFit::nmaxpars\n"); 00069 exit(1); 00070 } 00071 ErrorMatrix[nfreepars-1][nfreepars-1]=errorset*errorset; 00072 StepMatrix[nfreepars-1][nfreepars-1]=errorset; 00073 } 00074 00075 void CCF2SFit::UseBestPars(){ 00076 int i; 00077 currentchisquared=bestchisquared; 00078 for(i=0;i<nfreepars;i++) par[i]->currentx=par[i]->bestx; 00079 } 00080 00081 void CCF2SFit::SetL(int lxset,int lyset,int lzset){ 00082 lx=lxset; 00083 ly=lyset; 00084 lz=lzset; 00085 } 00086 00087 void CCF2SFit::SwitchPars(int i,int j){ 00088 int k; 00089 CParInfo *partemp; 00090 partemp=par[j]; 00091 par[j]=par[i]; 00092 par[i]=partemp; 00093 00094 for(k=0;k<nmaxpars;k++){ 00095 SwitchValues(&ErrorMatrix[i][k],&ErrorMatrix[j][k]); 00096 SwitchValues(&ErrorMatrix[k][i],&ErrorMatrix[k][j]); 00097 SwitchValues(&StepMatrix[i][k],&StepMatrix[j][k]); 00098 SwitchValues(&StepMatrix[k][i],&StepMatrix[k][j]); 00099 } 00100 } 00101 00102 void CCF2SFit::SwitchValues(double *a,double *b){ 00103 double dummy; 00104 dummy=*a; 00105 *a=*b; 00106 *b=dummy; 00107 } 00108 00109 void CCF2SFit::FreePar(string parstring){ 00110 int i; 00111 char parname[20]; 00112 strcpy(parname,parstring.c_str()); 00113 i=nfreepars; 00114 while(Misc::comparestrings(par[i]->name,parname)==0 && i<npars){ 00115 i+=1; 00116 } 00117 if(i==nmaxpars) printf("Par %s already free or does not exist\n", 00118 parstring.c_str()); 00119 else{ 00120 if(i!=nfreepars) SwitchPars(i,nfreepars); 00121 par[nfreepars]->fixed=0; 00122 printf("Freeing par[%d], name=%s\n",nfreepars,par[nfreepars]->name); 00123 nfreepars+=1; 00124 } 00125 } 00126 00127 void CCF2SFit::FixPar(string parstring){ 00128 int i; 00129 char parname[20]; 00130 strcpy(parname,parstring.c_str()); 00131 i=0; 00132 while(Misc::comparestrings(par[i]->name,parname)==0 && i<nfreepars){ 00133 i+=1; 00134 } 00135 if(i==nfreepars) printf("Par %s already fixed or does not exist\n", 00136 parstring.c_str()); 00137 else{ 00138 if(i!=nfreepars-1) SwitchPars(i,nfreepars-1); 00139 nfreepars-=1; 00140 par[nfreepars]->fixed=1; 00141 printf("Fixing par[%d], name=%s\n",nfreepars,par[nfreepars]->name); 00142 } 00143 00144 } 00145 00146 void CCF2SFit::PrintPars(){ 00147 int i; 00148 printf("ipar name value error min max fixed\n"); 00149 for(i=0;i<npars;i++){ 00150 printf("%2d : %12s %11.4e %11.4e %11.4e %11.4e %d\n", 00151 i,par[i]->name,par[i]->currentx,par[i]->error, 00152 par[i]->xmin,par[i]->xmax,par[i]->fixed); 00153 } 00154 } 00155 00156 void CCF2SFit::Init(){ 00157 int i,j; 00158 currentchisquared=1.0E20; 00159 bestchisquared=1.0E20; 00160 nfreepars=npars=0; 00161 ncalls=0; 00162 randy=new CRandom(-1234); 00163 par=new CParInfo *[nmaxpars]; 00164 ErrorMatrix=new double *[nmaxpars]; 00165 StepMatrix=new double *[nmaxpars]; 00166 for(i=0;i<nmaxpars;i++){ 00167 par[i]=new CParInfo(); 00168 par[i]->bestx=0.0; 00169 par[i]->xmin=-1.0E10; par[i]->xmax=1.0E10; 00170 ErrorMatrix[i]=new double[nmaxpars]; 00171 StepMatrix[i]=new double[nmaxpars]; 00172 par[i]->fixed=0; 00173 for(j=0;j<nmaxpars;j++){ 00174 ErrorMatrix[i][j]=0.0; 00175 StepMatrix[i][j]=0.0; 00176 } 00177 } 00178 printf("SFit Initialized\n"); 00179 } 00180 00181 void CCF2SFit::InitErrorMatrix(){ 00182 int i,j; 00183 for(i=0;i<nfreepars;i++){ 00184 for(j=0;j<nfreepars;j++){ 00185 if(i!=j){ 00186 ErrorMatrix[i][j]=StepMatrix[i][j]=0.0; 00187 } 00188 else{ 00189 StepMatrix[i][j]=par[i]->error; 00190 ErrorMatrix[i][j]=par[i]->error*par[i]->error; 00191 } 00192 } 00193 } 00194 } 00195 00196 void CCF2SFit::UpdateStepMatrix(){ 00197 int i,j; 00198 double *SMeigenval; 00199 CGSLMatrix_Real *matrixcalc; 00200 matrixcalc=new CGSLMatrix_Real(nfreepars); 00201 SMeigenval=new double[nfreepars]; 00202 matrixcalc->EigenFind(ErrorMatrix,StepMatrix,SMeigenval); 00203 for(i=0;i<nfreepars;i++){ 00204 if(SMeigenval[i]<-1.0E-10){ 00205 printf("FATAL: In UpdateStepSize, negative eigenvalue, =%g\n", 00206 SMeigenval[i]); 00207 exit(1); 00208 } 00209 } 00210 for(i=0;i<nfreepars;i++){ 00211 par[i]->error=0.0; 00212 for(j=0;j<nfreepars;j++){ 00213 StepMatrix[i][j]=StepMatrix[i][j] 00214 *sqrt(fabs(SMeigenval[j])); 00215 par[i]->error+=StepMatrix[i][j]*StepMatrix[i][j]; 00216 } 00217 par[i]->error=sqrt(par[i]->error); 00218 } 00219 delete [] SMeigenval; 00220 delete(matrixcalc); 00221 } 00222 00223 00224 void CCF2SFit::PrintErrorMatrix(){ 00225 int ia,ib; 00226 printf("________ < delX_i delX_j > ________\n"); 00227 for(ia=0;ia<nfreepars;ia++){ 00228 for(ib=0;ib<nfreepars;ib++) printf("%9.2e ",ErrorMatrix[ia][ib]); 00229 printf("\n"); 00230 } 00231 printf("___________________________________\n"); 00232 } 00233 00234 void CCF2SFit::PrintStepMatrix(){ 00235 int ia,ib; 00236 printf("________ < StepMatrix_ij > ________\n"); 00237 for(ia=0;ia<nfreepars;ia++){ 00238 for(ib=0;ib<nfreepars;ib++) printf("%9.2e ",StepMatrix[ia][ib]); 00239 printf("\n"); 00240 } 00241 printf("___________________________________\n"); 00242 } 00243 00244 CCF2SFit::CCF2SFit(){ 00245 sourceCH=NULL; 00246 source3D=NULL; 00247 lista=NULL; 00248 listb=NULL; 00249 kernel=NULL; 00250 kernelwf=NULL; 00251 wf=NULL; 00252 cexp3D=NULL; 00253 cerror3D=NULL; 00254 ctheory3D=NULL; 00255 cexpCH=NULL; 00256 cerrorCH=NULL; 00257 ctheoryCH=NULL; 00258 Init(); 00259 } 00260 00261 CCF2SFit::CCF2SFit(CCHArray *sourceCHset,C3DArray *source3Dset, 00262 CMCList *listaset,CMCList *listbset, 00263 CKernel *kernelset,CKernelWF *kernelwfset, 00264 CWaveFunction *wfset, 00265 C3DArray *cexp3Dset,C3DArray *cerror3Dset, 00266 C3DArray *ctheory3Dset,CCHArray *cexpCHset, 00267 CCHArray *cerrorCHset,CCHArray *ctheoryCHset){ 00268 sourceCH=sourceCHset; 00269 source3D=source3Dset; 00270 lista=listaset; 00271 listb=listbset; 00272 kernel=kernelset; 00273 kernelwf=kernelwfset; 00274 wf=wfset; 00275 cexp3D=cexp3Dset; 00276 cerror3D=cerror3Dset; 00277 ctheory3D=ctheory3D; 00278 cexpCH=cexpCHset; 00279 cerrorCH=cerrorCHset; 00280 ctheoryCH=ctheoryCHset; 00281 Init(); 00282 } 00283 00284 00285 CCF2SFit::~CCF2SFit(){ 00286 int i; 00287 delete [] par; 00288 for(i=0;i<nmaxpars;i++){ 00289 delete [] ErrorMatrix[i]; 00290 delete [] StepMatrix[i]; 00291 } 00292 delete [] ErrorMatrix; 00293 delete [] StepMatrix; 00294 } 00295 00296 00297 double CCF2SFit::GetChiSquared(double *xx){ 00298 double chisquared=0.0; 00299 int i; 00300 double *x; 00301 ncalls+=1; 00302 x=new double[nfreepars]; 00303 for(i=0;i<nfreepars;i++) x[i]=xx[i]; 00304 00305 printf("In GetChiSquare, x[] = "); 00306 for(i=0;i<nfreepars;i++) printf("%g,",x[i]); 00307 printf(" ncalls=%d\n",ncalls); 00308 for(i=0;i<nfreepars;i++){ 00309 parameter::set(sourcecalc->spars,par[i]->name,x[i]); 00310 } 00311 if(calcflag==1){ 00312 sourcecalc->CalcS(lx,ly,lz,sourceCH); 00313 S2CF::s2c(sourceCH,kernel,ctheoryCH); 00314 chisquared=CFCalc::GetChiSquared(lx,ly,lz,cexpCH,cerrorCH,ctheoryCH); 00315 } 00316 else if(calcflag==2){ 00317 sourcecalc->CalcS(sourceCH); 00318 S2CF::s2c(sourceCH,kernel,ctheoryCH); 00319 ArrayCalc::Calc3DArrayFromAExpArray(ctheoryCH,ctheory3D); 00320 chisquared=CFCalc::GetChiSquared(cexp3D,cerror3D,ctheory3D); 00321 } 00322 else if(calcflag==3){ 00323 sourcecalc->CalcS(lista,listb); 00324 S2CF::s2c(lista,listb,kernelwf,ctheory3D); 00325 chisquared=CFCalc::GetChiSquared(cexp3D,cerror3D,ctheory3D); 00326 } 00327 else if(calcflag==4){ 00328 sourcecalc->CalcS(lista,listb); 00329 S2CF::s2c(lista,listb,wf,ctheory3D); 00330 chisquared=CFCalc::GetChiSquared(cexp3D,cerror3D,ctheory3D); 00331 } 00332 if(chisquared<bestchisquared){ 00333 bestchisquared=chisquared; 00334 for(i=0;i<nfreepars;i++) par[i]->bestx=x[i]; 00335 } 00336 return chisquared; 00337 delete [] x; 00338 } 00339 00340 void CCF2SFit::Newton(int maxtries){ 00341 bool success; 00342 int i,j,k,itry,nrescale,nsuccess; 00343 double **curvature,*slope; 00344 double *x,*xnew,*xa,*xb,*xc,*xd,*delx,*dx; 00345 double chi2,chi2a,chi2b,chi2c,chi2d,newchi2,scheck; 00346 CGSLMatrix_Real *matrixcalc; 00347 matrixcalc=new CGSLMatrix_Real(nfreepars); 00348 slope=new double[nfreepars]; 00349 x=new double[nfreepars]; 00350 xnew=new double[nfreepars]; 00351 xa=new double[nfreepars]; 00352 xb=new double[nfreepars]; 00353 xc=new double[nfreepars]; 00354 xd=new double[nfreepars]; 00355 delx=new double[nfreepars]; 00356 dx=new double[nfreepars]; 00357 curvature=new double*[nfreepars]; 00358 for(i=0;i<nfreepars;i++) curvature[i]=new double[nfreepars]; 00359 00360 for(i=0;i<nfreepars;i++){ 00361 dx[i]=par[i]->error; 00362 x[i]=par[i]->currentx; 00363 } 00364 00365 nsuccess=itry=0; 00366 do{ 00367 itry+=1; 00368 chi2=GetChiSquared(x); 00369 for(i=1;i<nfreepars;i++){ 00370 for(j=0;j<i;j++){ 00371 for(k=0;k<nfreepars;k++) xa[k]=xb[k]=xc[k]=xd[k]=x[k]; 00372 xa[i]+=dx[i]; xa[j]+=dx[j]; 00373 xb[i]+=dx[i]; xb[j]-=dx[j]; 00374 xc[i]-=dx[i]; xc[j]+=dx[j]; 00375 xd[i]-=dx[i]; xd[j]-=dx[j]; 00376 chi2a=GetChiSquared(xa); 00377 chi2b=GetChiSquared(xb); 00378 chi2c=GetChiSquared(xc); 00379 chi2d=GetChiSquared(xd); 00380 curvature[i][j]=(chi2a+chi2d-chi2b-chi2c)/(4.0*dx[i]*dx[j]); 00381 curvature[j][i]=curvature[i][j]; 00382 printf("___ itry=%d, Curvature[%d][%d]=%g ___\n", 00383 itry,i,j,curvature[i][j]); 00384 } 00385 } 00386 for(i=0;i<nfreepars;i++){ 00387 for(k=0;k<nfreepars;k++) xa[k]=xb[k]=x[k]; 00388 xa[i]+=dx[i]; 00389 xb[i]-=dx[i]; 00390 chi2a=GetChiSquared(xa); 00391 chi2b=GetChiSquared(xb); 00392 curvature[i][i]=(chi2a-2*chi2+chi2b)/(dx[i]*dx[i]); 00393 printf("___ itry=%d, Curvature[%d][%d]=%g ___\n",itry,i,i,curvature[i][i]); 00394 slope[i]=(chi2a-chi2b)/(2.0*dx[i]); 00395 } 00396 matrixcalc->SolveLinearEqs(slope,curvature,delx); 00397 nrescale=0; 00398 TRY_RESCALED: 00399 printf("delx[] = "); 00400 for(i=0;i<nfreepars;i++){ 00401 printf("%g ",delx[i]); 00402 xnew[i]=x[i]-delx[i]; 00403 } 00404 printf("\n"); 00405 00406 for(i=0;i<nfreepars;i++){ 00407 if(par[i]->fixed==0){ 00408 if(xnew[i]<par[i]->xmin || xnew[i]>par[i]->xmax){ 00409 for(j=0;j<nfreepars;j++) delx[j]=0.5*delx[j]; 00410 printf("Stepped outside min/max, will rescale delx[]\n"); 00411 if(nrescale>4) exit(1); 00412 nrescale+=1; 00413 goto TRY_RESCALED; 00414 } 00415 } 00416 } 00417 00418 newchi2=GetChiSquared(xnew); 00419 if(newchi2>chi2){ 00420 for(j=0;j<nfreepars;j++){ 00421 delx[j]=0.5*delx[j]; 00422 } 00423 printf("new chi^2 bigger than previous, will rescale delx[]\n"); 00424 goto TRY_RESCALED; 00425 } 00426 00427 success=1; 00428 scheck=0.0; 00429 for(i=0;i<nfreepars;i++){ 00430 for(j=0;j<nfreepars;j++){ 00431 scheck+=curvature[i][j]*delx[i]*delx[j]; 00432 } 00433 } 00434 if(scheck<1.0) success=1; 00435 00436 if(success){ 00437 printf("SUCCESS!!!!!!!!!!!\n"); 00438 nsuccess+=1; 00439 CalcErrorMatrixFromCurvature(curvature); 00440 for(i=0;i<nfreepars;i++) dx[i]=par[i]->error; 00441 } 00442 00443 chi2=newchi2; 00444 for(i=0;i<nfreepars;i++) x[i]=xnew[i]; 00445 } while(itry<maxtries && nsuccess<2); 00446 00447 currentchisquared=chi2; 00448 for(i=0;i<nfreepars;i++) par[i]->currentx=x[i]; 00449 00450 delete [] dx; 00451 delete [] x; 00452 delete [] xnew; 00453 delete [] delx; 00454 delete [] xa; 00455 delete [] xb; 00456 delete [] xc; 00457 delete [] xd; 00458 delete [] slope; 00459 for(i=0;i<nfreepars;i++) delete [] curvature[i]; 00460 delete [] curvature; 00461 delete(matrixcalc); 00462 } 00463 00464 void CCF2SFit::CalcErrorMatrixFromCurvature(double **C){ 00465 int i,j,k; 00466 CGSLMatrix_Real *matrixcalc; 00467 double **U; 00468 double *EigenVal; 00469 matrixcalc=new CGSLMatrix_Real(nfreepars); 00470 EigenVal=new double[nfreepars]; 00471 U=new double *[nfreepars]; 00472 for(i=0;i<nfreepars;i++) U[i]=new double[nfreepars]; 00473 matrixcalc->EigenFind(C,U,EigenVal); 00474 00475 for(i=0;i<nfreepars;i++){ 00476 for(j=0;j<=i;j++){ 00477 if(i<nfreepars && j<nfreepars){ 00478 ErrorMatrix[i][j]=0.0; 00479 for(k=0;k<nfreepars;k++){ 00480 ErrorMatrix[i][j]+=U[i][k]*U[j][k]/EigenVal[k]; 00481 } 00482 } 00483 else ErrorMatrix[i][j]=0.0; 00484 if(i!=j) ErrorMatrix[j][i]=ErrorMatrix[i][j]; 00485 } 00486 par[i]->error=sqrt(fabs(ErrorMatrix[i][i])); 00487 } 00488 00489 for(i=0;i<nfreepars;i++) delete [] U[i]; 00490 delete [] U; 00491 delete [] EigenVal; 00492 delete(matrixcalc); 00493 } 00494 00495 void CCF2SFit::Metropolis(int maxcalls){ 00496 int icall,i,j,Nsuccess=0; 00497 bool success; 00498 double stepscale,step,chisquared; 00499 double *x,*xran,*xbar; 00500 x=new double[nfreepars]; 00501 xran=new double[nfreepars]; 00502 xbar=new double[nfreepars]; 00503 for(i=0;i<nfreepars;i++){ 00504 x[i]=par[i]->currentx; 00505 xbar[i]=0.0; 00506 for(j=0;j<nfreepars;j++) ErrorMatrix[i][j]=0.0; 00507 } 00508 stepscale=1.0/sqrt(double(nfreepars)); 00509 for(icall=0;icall<maxcalls;icall++){ 00510 00511 GETNEWXRAN: 00512 if(MCsourceflag){ 00513 for(i=0;i<nfreepars;i++) x[i]=par[i]->currentx; 00514 currentchisquared=GetChiSquared(x); 00515 } 00516 for(j=0;j<nfreepars;j++) xran[j]=randy->gauss(); 00517 for(i=0;i<nfreepars;i++){ 00518 if(par[i]->fixed==0){ 00519 x[i]=par[i]->currentx; 00520 for(j=0;j<nfreepars;j++){ 00521 step=StepMatrix[i][j]*xran[j]*stepscale; 00522 x[i]+=step; 00523 } 00524 } 00525 } 00526 for(i=0;i<nfreepars;i++) 00527 if(x[i]<par[i]->xmin || x[i]>par[i]->xmax) goto GETNEWXRAN; 00528 00529 chisquared=GetChiSquared(x); 00530 success=0; 00531 if(chisquared<currentchisquared){ 00532 success=1; 00533 } 00534 else if(randy->ran()<exp(-0.5*(chisquared-currentchisquared))){ 00535 success=1; 00536 } 00537 00538 if(success==1){ 00539 Nsuccess+=1; 00540 currentchisquared=chisquared; 00541 for(i=0;i<nfreepars;i++) par[i]->currentx=x[i]; 00542 printf("SUCCESS, Nsuccess=%d\n",Nsuccess); 00543 } 00544 00545 for(i=0;i<nfreepars;i++){ 00546 xbar[i]+=x[i]; 00547 for(j=0;j<nfreepars;j++) ErrorMatrix[i][j]+=x[i]*x[j]; 00548 } 00549 } 00550 00551 for(i=0;i<nfreepars;i++){ 00552 par[i]->xbar=xbar[i]/double(maxcalls); 00553 for(j=0;j<nfreepars;j++) ErrorMatrix[i][j]=ErrorMatrix[i][j]/double(maxcalls); 00554 } 00555 for(i=0;i<nfreepars;i++) 00556 for(j=0;j<nfreepars;j++) ErrorMatrix[i][j]=(ErrorMatrix[i][j]-par[i]->xbar*par[j]->xbar) 00557 *double(Nsuccess)/double(Nsuccess-1); 00558 00559 printf("Best chi^2=%g, Best x[] = ",bestchisquared); 00560 for(i=0;i<nfreepars;i++) printf("%g ",par[i]->bestx); 00561 printf("\n"); 00562 00563 delete [] x; 00564 delete [] xran; 00565 delete [] xbar; 00566 } 00567 00568 void CCF2SFit::SteepestDescent(int maxtries){ 00569 int i,j,itry,nfailure,nsuccess; 00570 double chisquared,newchisquared,chi2a,chi2b,qstep; 00571 double d2chi2dq2,dchi2dq_mag,dq; 00572 double *delx,*delq,*x,*xa,*xb,*qxratio,*xnew; 00573 double *dchi2dq; 00574 delx=new double[nfreepars]; 00575 x=new double[nfreepars]; 00576 xa=new double[nfreepars]; 00577 xb=new double[nfreepars]; 00578 xnew=new double[nfreepars]; 00579 delq=new double[nfreepars]; 00580 qxratio=new double[nfreepars]; 00581 dchi2dq=new double[nfreepars]; 00582 for(i=0;i<nfreepars;i++){ 00583 qxratio[i]=par[i]->error; 00584 if(par[i]->fixed) qxratio[i]=0.0; 00585 x[i]=par[i]->currentx; 00586 dchi2dq[i]=delx[i]=0.0; 00587 } 00588 dq=1.0; 00589 chisquared=GetChiSquared(x); 00590 00591 nsuccess=0; 00592 itry=0; 00593 do{ 00594 itry+=1; 00595 dchi2dq_mag=0.0; 00596 for(i=0;i<nfreepars;i++){ 00597 if(par[i]->fixed==0){ 00598 delx[i]=qxratio[i]*dq; 00599 for(j=0;j<nfreepars;j++){ 00600 xa[j]=x[j]; 00601 } 00602 xa[i]=x[i]+delx[i]; 00603 chi2a=GetChiSquared(xa); 00604 dchi2dq[i]=(chi2a-chisquared)*qxratio[i]/delx[i]; 00605 dchi2dq_mag+=dchi2dq[i]*dchi2dq[i]; 00606 } 00607 } 00608 dchi2dq_mag=sqrt(dchi2dq_mag); 00609 00610 for(i=0;i<nfreepars;i++){ 00611 if(par[i]->fixed==0){ 00612 delq[i]=-dq*dchi2dq[i]/dchi2dq_mag; 00613 delx[i]=delq[i]*qxratio[i]; 00614 xa[i]=x[i]-0.5*delx[i]; 00615 xb[i]=x[i]+0.5*delx[i]; 00616 printf("xa[%d]=%g, xb[%d]=%g\n",i,xa[i],i,xb[i]); 00617 } 00618 } 00619 chi2a=GetChiSquared(xa); 00620 chi2b=GetChiSquared(xb); 00621 d2chi2dq2=4.0*(chi2b+chi2a-2.0*chisquared)/(dq*dq); 00622 qstep=dchi2dq_mag/d2chi2dq2; 00623 if(qstep<0.0){ 00624 qstep=dq; 00625 printf("Warning: curvature in q has wrong sign\n"); 00626 printf("chi2a=%g, chi2=%g, chi2b=%g\n",chi2a,chisquared,chi2b); 00627 exit(1); 00628 } 00629 if(qstep>10.0*dq) qstep=10.0*dq; 00630 TRYNEWQSTEP: 00631 nfailure=0; 00632 for(i=0;i<nfreepars;i++){ 00633 if(par[i]->fixed==0){ 00634 delq[i]=-qstep*dchi2dq[i]/dchi2dq_mag; 00635 xnew[i]=x[i]+delq[i]*qxratio[i]; 00636 } 00637 } 00638 newchisquared=GetChiSquared(xnew); 00639 if(newchisquared>chisquared){ 00640 printf("new chi^2 not so good\n"); 00641 nfailure+=1; 00642 if(nfailure>5){ 00643 printf("STEEPEST DESCENT FAILURE\n"); 00644 exit(1); 00645 } 00646 qstep=0.5*qstep; 00647 goto TRYNEWQSTEP; 00648 } 00649 if(qstep<2.0*dq){ 00650 nsuccess+=1; 00651 printf("Looks like we might be getting close\n"); 00652 dq=dq/3.0; 00653 } 00654 chisquared=newchisquared; 00655 for(i=0;i<nfreepars;i++){ 00656 if(par[i]->fixed==0) x[i]=xnew[i]; 00657 } 00658 }while(itry<maxtries && nsuccess<2); 00659 00660 chisquared=GetChiSquared(x); 00661 currentchisquared=chisquared; 00662 for(i=0;i<nfreepars;i++){ 00663 if(par[i]->fixed==0) par[i]->currentx=x[i]; 00664 } 00665 00666 delete [] xa; 00667 delete [] xb; 00668 delete [] x; 00669 delete [] xnew; 00670 delete [] delx; 00671 delete [] delq; 00672 delete [] dchi2dq; 00673 delete [] qxratio; 00674 } 00675 00676 #endif 00677