00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #include <stdlib.h>
00057 #include "TVirtualFitter.h"
00058 #include "TSystem.h"
00059 #include "TROOT.h"
00060 #include "TBenchmark.h"
00061 #include "TMath.h"
00062 #include "TStopwatch.h"
00063 #include "Riostream.h"
00064 #include "TVectorD.h"
00065 #include "TMatrixD.h"
00066
00067 Int_t stressFit(const char *theFitter="Minuit", Int_t N=2000);
00068 Int_t gVerbose = -1;
00069 Double_t gAbsTolerance = 0.005;
00070
00071
00072 void StatusPrint(Int_t id,const TString &title,Bool_t status)
00073 {
00074
00075 const Int_t kMAX = 65;
00076 Char_t number[4];
00077 sprintf(number,"%2d",id);
00078 TString header = TString("Test ")+number+" : "+title;
00079 const Int_t nch = header.Length();
00080 for (Int_t i = nch; i < kMAX; i++) header += '.';
00081 cout << header << (status ? "OK" : "FAILED") << endl;
00082 }
00083
00084
00085 void RosenBrock(Int_t &, Double_t *, Double_t &f, Double_t *par, Int_t )
00086 {
00087 const Double_t x = par[0];
00088 const Double_t y = par[1];
00089 const Double_t tmp1 = y-x*x;
00090 const Double_t tmp2 = 1-x;
00091 f = 100*tmp1*tmp1+tmp2*tmp2;
00092 }
00093
00094
00095 Bool_t RunRosenBrock()
00096 {
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 Bool_t ok = kTRUE;
00111 TVirtualFitter *min = TVirtualFitter::Fitter(0,2);
00112 min->SetFCN(RosenBrock);
00113
00114 Double_t arglist[100];
00115 arglist[0] = gVerbose;
00116 min->ExecuteCommand("SET PRINT",arglist,1);
00117
00118 min->SetParameter(0,"x",-1.2,0.01,0,0);
00119 min->SetParameter(1,"y", 1.0,0.01,0,0);
00120
00121 arglist[0] = 0;
00122 min->ExecuteCommand("SET NOW",arglist,0);
00123 arglist[0] = 1000;
00124 arglist[1] = 0.001;
00125 min->ExecuteCommand("MIGRAD",arglist,0);
00126 min->ExecuteCommand("MIGRAD",arglist,2);
00127 min->ExecuteCommand("MINOS",arglist,0);
00128
00129 Double_t parx,pary;
00130 Double_t we,al,bl;
00131 Char_t parName[32];
00132 min->GetParameter(0,parName,parx,we,al,bl);
00133 min->GetParameter(1,parName,pary,we,al,bl);
00134
00135 ok = ( TMath::Abs(parx-1.) < gAbsTolerance &&
00136 TMath::Abs(pary-1.) < gAbsTolerance );
00137
00138 delete min;
00139
00140 return ok;
00141 }
00142
00143
00144 void Wood4(Int_t &, Double_t *, Double_t &f, Double_t *par, Int_t )
00145 {
00146 const Double_t w = par[0];
00147 const Double_t x = par[1];
00148 const Double_t y = par[2];
00149 const Double_t z = par[3];
00150
00151 const Double_t w1 = w-1;
00152 const Double_t x1 = x-1;
00153 const Double_t y1 = y-1;
00154 const Double_t z1 = z-1;
00155 const Double_t tmp1 = x-w*w;
00156 const Double_t tmp2 = z-y*y;
00157
00158 f = 100*tmp1*tmp1+w1*w1+90*tmp2*tmp2+y1*y1+10.1*(x1*x1+z1*z1)+19.8*x1*z1;
00159 }
00160
00161
00162 Bool_t RunWood4()
00163 {
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 Bool_t ok = kTRUE;
00181 TVirtualFitter *min = TVirtualFitter::Fitter(0,4);
00182 min->SetFCN(Wood4);
00183
00184 Double_t arglist[100];
00185 arglist[0] = gVerbose;
00186 min->ExecuteCommand("SET PRINT",arglist,1);
00187
00188 min->SetParameter(0,"w",-3.0,0.01,0,0);
00189 min->SetParameter(1,"x",-1.0,0.01,0,0);
00190 min->SetParameter(2,"y",-3.0,0.01,0,0);
00191 min->SetParameter(3,"z",-1.0,0.01,0,0);
00192
00193 arglist[0] = 0;
00194 min->ExecuteCommand("SET NOW",arglist,0);
00195 arglist[0] = 1000;
00196 arglist[1] = 0.001;
00197 min->ExecuteCommand("MIGRAD",arglist,0);
00198 min->ExecuteCommand("MIGRAD",arglist,2);
00199 min->ExecuteCommand("MINOS",arglist,0);
00200
00201 Double_t parw,parx,pary,parz;
00202 Double_t we,al,bl;
00203 Char_t parName[32];
00204 min->GetParameter(1,parName,parw,we,al,bl);
00205 min->GetParameter(0,parName,parx,we,al,bl);
00206 min->GetParameter(1,parName,pary,we,al,bl);
00207 min->GetParameter(1,parName,parz,we,al,bl);
00208
00209 ok = ( TMath::Abs(parw-1.) < gAbsTolerance &&
00210 TMath::Abs(parx-1.) < gAbsTolerance &&
00211 TMath::Abs(pary-1.) < gAbsTolerance &&
00212 TMath::Abs(parz-1.) < gAbsTolerance );
00213
00214 delete min;
00215
00216 return ok;
00217 }
00218
00219
00220 void Powell(Int_t &, Double_t *, Double_t &f, Double_t *par, Int_t )
00221 {
00222 const Double_t w = par[0];
00223 const Double_t x = par[1];
00224 const Double_t y = par[2];
00225 const Double_t z = par[3];
00226
00227 const Double_t tmp1 = w+10*x;
00228 const Double_t tmp2 = y-z;
00229 const Double_t tmp3 = x-2*y;
00230 const Double_t tmp4 = w-z;
00231
00232 f = tmp1*tmp1+5*tmp2*tmp2+tmp3*tmp3*tmp3*tmp3+10*tmp4*tmp4*tmp4*tmp4;
00233 }
00234
00235
00236 Bool_t RunPowell()
00237 {
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 Bool_t ok = kTRUE;
00250 TVirtualFitter *min = TVirtualFitter::Fitter(0,4);
00251 min->SetFCN(Powell);
00252
00253 Double_t arglist[100];
00254 arglist[0] = gVerbose;
00255 min->ExecuteCommand("SET PRINT",arglist,1);
00256
00257 min->SetParameter(0,"w",+3.0,0.01,0,0);
00258 min->SetParameter(1,"x",-1.0,0.01,0,0);
00259 min->SetParameter(2,"y", 0.0,0.01,0,0);
00260 min->SetParameter(3,"z",+1.0,0.01,0,0);
00261
00262 arglist[0] = 0;
00263 min->ExecuteCommand("SET NOW",arglist,0);
00264 arglist[0] = 1000;
00265 arglist[1] = 0.001;
00266 min->ExecuteCommand("MIGRAD",arglist,0);
00267 min->ExecuteCommand("MIGRAD",arglist,2);
00268 min->ExecuteCommand("MINOS",arglist,0);
00269
00270 Double_t parw,parx,pary,parz;
00271 Double_t we,al,bl;
00272 Char_t parName[32];
00273 min->GetParameter(1,parName,parw,we,al,bl);
00274 min->GetParameter(0,parName,parx,we,al,bl);
00275 min->GetParameter(1,parName,pary,we,al,bl);
00276 min->GetParameter(1,parName,parz,we,al,bl);
00277
00278 ok = ( TMath::Abs(parw-0.) < gAbsTolerance &&
00279 TMath::Abs(parx-0.) < 10.*gAbsTolerance &&
00280 TMath::Abs(pary-0.) < gAbsTolerance &&
00281 TMath::Abs(parz-0.) < gAbsTolerance );
00282
00283 delete min;
00284
00285 return ok;
00286 }
00287
00288
00289 void Fletcher(Int_t &, Double_t *, Double_t &f, Double_t *par, Int_t )
00290 {
00291 const Double_t x = par[0];
00292 const Double_t y = par[1];
00293 const Double_t z = par[2];
00294
00295 Double_t psi;
00296 if (x > 0)
00297 psi = TMath::ATan(y/x)/2/TMath::Pi();
00298 else if (x < 0)
00299 psi = 0.5+TMath::ATan(y/x)/2/TMath::Pi();
00300 else
00301 psi = 0.0;
00302
00303 const Double_t tmp1 = z-10*psi;
00304 const Double_t tmp2 = TMath::Sqrt(x*x+y*y)-1;
00305
00306 f = 100*(tmp1*tmp1+tmp2*tmp2)+z*z;
00307 }
00308
00309
00310 Bool_t RunFletcher()
00311 {
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 Bool_t ok = kTRUE;
00328 TVirtualFitter *min = TVirtualFitter::Fitter(0,3);
00329 min->SetFCN(Fletcher);
00330
00331 Double_t arglist[100];
00332 arglist[0] = gVerbose;
00333 min->ExecuteCommand("SET PRINT",arglist,1);
00334
00335 min->SetParameter(0,"x",-1.0,0.01,0,0);
00336 min->SetParameter(1,"y", 0.0,0.01,0,0);
00337 min->SetParameter(2,"z", 0.0,0.01,0,0);
00338
00339 arglist[0] = 0;
00340 min->ExecuteCommand("SET NOW",arglist,0);
00341 arglist[0] = 1000;
00342 arglist[1] = 0.001;
00343 min->ExecuteCommand("MIGRAD",arglist,0);
00344 min->ExecuteCommand("MIGRAD",arglist,2);
00345 min->ExecuteCommand("MINOS",arglist,0);
00346
00347 Double_t parx,pary,parz;
00348 Double_t we,al,bl;
00349 Char_t parName[32];
00350 min->GetParameter(0,parName,parx,we,al,bl);
00351 min->GetParameter(1,parName,pary,we,al,bl);
00352 min->GetParameter(1,parName,parz,we,al,bl);
00353
00354 ok = ( TMath::Abs(parx-1.) < gAbsTolerance &&
00355 TMath::Abs(pary-0.) < gAbsTolerance &&
00356 TMath::Abs(parz-0.) < gAbsTolerance );
00357
00358 delete min;
00359
00360 return ok;
00361 }
00362
00363
00364 void GoldStein1(Int_t &, Double_t *, Double_t &f, Double_t *par, Int_t )
00365 {
00366 const Double_t x = par[0];
00367 const Double_t y = par[1];
00368
00369 const Double_t tmp1 = x+y+1;
00370 const Double_t tmp2 = 19-14*x+3*x*x-14*y+6*x*y+3*y*y;
00371 const Double_t tmp3 = 2*x-3*y;
00372 const Double_t tmp4 = 18-32*x+12*x*x+48*y-36*x*y+27*y*y;
00373
00374 f = (1+tmp1*tmp1*tmp2)*(30+tmp3*tmp3*tmp4);
00375 }
00376
00377
00378 Bool_t RunGoldStein1()
00379 {
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 Bool_t ok = kTRUE;
00397 TVirtualFitter *min = TVirtualFitter::Fitter(0,2);
00398 min->SetFCN(GoldStein1);
00399
00400 Double_t arglist[100];
00401 arglist[0] = gVerbose;
00402 min->ExecuteCommand("SET PRINT",arglist,1);
00403
00404 min->SetParameter(0,"x",-0.3999,0.01,-2.0,+2.0);
00405 min->SetParameter(1,"y",-0.6,0.01,-2.0,+2.0);
00406
00407 arglist[0] = 0;
00408 min->ExecuteCommand("SET NOW",arglist,0);
00409 arglist[0] = 1000;
00410 arglist[1] = 0.001;
00411 min->ExecuteCommand("MIGRAD",arglist,0);
00412 min->ExecuteCommand("MIGRAD",arglist,2);
00413 min->ExecuteCommand("MIGRAD",arglist,2);
00414 min->ExecuteCommand("MINOS",arglist,0);
00415
00416 Double_t parx,pary;
00417 Double_t we,al,bl;
00418 Char_t parName[32];
00419 min->GetParameter(0,parName,parx,we,al,bl);
00420 min->GetParameter(1,parName,pary,we,al,bl);
00421
00422 ok = ( TMath::Abs(parx-0.) < gAbsTolerance &&
00423 TMath::Abs(pary+1.) < gAbsTolerance );
00424
00425 delete min;
00426
00427 return ok;
00428 }
00429
00430
00431 void GoldStein2(Int_t &, Double_t *, Double_t &f, Double_t *par, Int_t )
00432 {
00433 const Double_t x = par[0];
00434 const Double_t y = par[1];
00435
00436 const Double_t tmp1 = x*x+y*y-25;
00437 const Double_t tmp2 = TMath::Sin(4*x-3*y);
00438 const Double_t tmp3 = 2*x+y-10;
00439
00440 f = TMath::Exp(0.5*tmp1*tmp1)+tmp2*tmp2*tmp2*tmp2+0.5*tmp3*tmp3;
00441 }
00442
00443
00444 Bool_t RunGoldStein2()
00445 {
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 Bool_t ok = kTRUE;
00457 TVirtualFitter *min = TVirtualFitter::Fitter(0,2);
00458 min->SetFCN(GoldStein2);
00459
00460 Double_t arglist[100];
00461 arglist[0] = gVerbose;
00462 min->ExecuteCommand("SET PRINT",arglist,1);
00463
00464 min->SetParameter(0,"x",+1.0,0.01,-5.0,+5.0);
00465 min->SetParameter(1,"y",+3.2,0.01,-5.0,+5.0);
00466
00467 arglist[0] = 0;
00468 min->ExecuteCommand("SET NOW",arglist,0);
00469 arglist[0] = 1000;
00470 arglist[1] = 0.01;
00471 min->ExecuteCommand("MIGRAD",arglist,0);
00472 min->ExecuteCommand("MIGRAD",arglist,2);
00473 min->ExecuteCommand("MINOS",arglist,0);
00474
00475 Double_t parx,pary;
00476 Double_t we,al,bl;
00477 Char_t parName[32];
00478 min->GetParameter(0,parName,parx,we,al,bl);
00479 min->GetParameter(1,parName,pary,we,al,bl);
00480
00481 ok = ( TMath::Abs(parx-3.) < gAbsTolerance &&
00482 TMath::Abs(pary-4.) < gAbsTolerance );
00483
00484 delete min;
00485
00486 return ok;
00487 }
00488
00489 Double_t seed = 3;
00490 Int_t nf;
00491 TMatrixD A;
00492 TMatrixD B;
00493 TVectorD x0;
00494 TVectorD sx0;
00495 TVectorD cx0;
00496 TVectorD sx;
00497 TVectorD cx;
00498 TVectorD v0;
00499 TVectorD v;
00500 TVectorD r;
00501
00502
00503 void TrigoFletcher(Int_t &, Double_t *, Double_t &f, Double_t *par, Int_t )
00504 {
00505 Int_t i;
00506 for (i = 0; i < nf ; i++) {
00507 cx0[i] = TMath::Cos(x0[i]);
00508 sx0[i] = TMath::Sin(x0[i]);
00509 cx [i] = TMath::Cos(par[i]);
00510 sx [i] = TMath::Sin(par[i]);
00511 }
00512
00513 v0 = A*sx0+B*cx0;
00514 v = A*sx +B*cx;
00515 r = v0-v;
00516
00517 f = r * r;
00518 }
00519
00520
00521 Bool_t RunTrigoFletcher()
00522 {
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 const Double_t pi = TMath::Pi();
00544 Bool_t ok = kTRUE;
00545 Double_t delta = 0.1;
00546
00547 for (nf = 5; nf<32;nf +=5) {
00548 TVirtualFitter *min = TVirtualFitter::Fitter(0,nf);
00549 min->SetFCN(TrigoFletcher);
00550
00551 Double_t arglist[100];
00552 arglist[0] = gVerbose;
00553 min->ExecuteCommand("SET PRINT",arglist,1);
00554 A.ResizeTo(nf,nf);
00555 B.ResizeTo(nf,nf);
00556 x0.ResizeTo(nf);
00557 sx0.ResizeTo(nf);
00558 cx0.ResizeTo(nf);
00559 sx.ResizeTo(nf);
00560 cx.ResizeTo(nf);
00561 v0.ResizeTo(nf);
00562 v.ResizeTo(nf);
00563 r.ResizeTo(nf);
00564 A.Randomize(-100.,100,seed);
00565 B.Randomize(-100.,100,seed);
00566 for (Int_t i = 0; i < nf; i++) {
00567 for (Int_t j = 0; j < nf; j++) {
00568 A(i,j) = Int_t(A(i,j));
00569 B(i,j) = Int_t(B(i,j));
00570 }
00571 }
00572
00573 x0.Randomize(-pi,pi,seed);
00574 TVectorD x1(nf); x1.Randomize(-delta*pi,delta*pi,seed);
00575 x1+= x0;
00576
00577 for (Int_t i = 0; i < nf; i++)
00578 min->SetParameter(i,Form("x_%d",i),x1[i],0.01,-pi*(1+delta),+pi*(1+delta));
00579
00580 arglist[0] = 0;
00581 min->ExecuteCommand("SET NOW",arglist,0);
00582 arglist[0] = 1000;
00583 arglist[1] = 0.01;
00584 min->ExecuteCommand("MIGRAD",arglist,0);
00585 min->ExecuteCommand("MIGRAD",arglist,2);
00586 min->ExecuteCommand("MINOS",arglist,0);
00587
00588 Double_t par,we,al,bl;
00589 Char_t parName[32];
00590 for (Int_t i = 0; i < nf; i++) {
00591 min->GetParameter(i,parName,par,we,al,bl);
00592 ok = ok && ( TMath::Abs(par) -TMath::Abs(x0[i]) < gAbsTolerance );
00593 if (!ok) printf("nf=%d, i=%d, par=%g, x0=%g\n",nf,i,par,x0[i]);
00594 }
00595 delete min;
00596 }
00597
00598 return ok;
00599 }
00600
00601
00602 Int_t stressFit(const char *theFitter, Int_t N)
00603 {
00604 TVirtualFitter::SetDefaultFitter(theFitter);
00605
00606 cout << "******************************************************************" <<endl;
00607 cout << "* Minimization - S T R E S S suite *" <<endl;
00608 cout << "******************************************************************" <<endl;
00609 cout << "******************************************************************" <<endl;
00610
00611 TStopwatch timer;
00612 timer.Start();
00613
00614 cout << "* Starting S T R E S S with fitter : "<<TVirtualFitter::GetDefaultFitter() <<endl;
00615 cout << "******************************************************************" <<endl;
00616
00617 gBenchmark->Start("stressFit");
00618
00619 Bool_t okRosenBrock = kTRUE;
00620 Bool_t okWood = kTRUE;
00621 Bool_t okPowell = kTRUE;
00622 Bool_t okFletcher = kTRUE;
00623 Bool_t okGoldStein1 = kTRUE;
00624 Bool_t okGoldStein2 = kTRUE;
00625 Bool_t okTrigoFletcher = kTRUE;
00626 Int_t i;
00627 for (i = 0; i < N; i++) okWood = RunWood4();
00628 StatusPrint(1,"Wood",okWood);
00629 for (i = 0; i < N; i++) okRosenBrock = RunRosenBrock();
00630 StatusPrint(2,"RosenBrock",okRosenBrock);
00631 for (i = 0; i < N; i++) okPowell = RunPowell();
00632 StatusPrint(3,"Powell",okPowell);
00633 for (i = 0; i < N; i++) okFletcher = RunFletcher();
00634 StatusPrint(4,"Fletcher",okFletcher);
00635 for (i = 0; i < N; i++) okGoldStein1 = RunGoldStein1();
00636 StatusPrint(5,"GoldStein1",okGoldStein1);
00637 for (i = 0; i < N; i++) okGoldStein2 = RunGoldStein2();
00638 StatusPrint(6,"GoldStein2",okGoldStein2);
00639 okTrigoFletcher = RunTrigoFletcher();
00640 StatusPrint(7,"TrigoFletcher",okTrigoFletcher);
00641
00642 gBenchmark->Stop("stressFit");
00643
00644
00645
00646 Bool_t UNIX = strcmp(gSystem->GetName(), "Unix") == 0;
00647 printf("******************************************************************\n");
00648 if (UNIX) {
00649 TString sp = gSystem->GetFromPipe("uname -a");
00650 sp.Resize(60);
00651 printf("* SYS: %s\n",sp.Data());
00652 if (strstr(gSystem->GetBuildNode(),"Linux")) {
00653 sp = gSystem->GetFromPipe("lsb_release -d -s");
00654 printf("* SYS: %s\n",sp.Data());
00655 }
00656 if (strstr(gSystem->GetBuildNode(),"Darwin")) {
00657 sp = gSystem->GetFromPipe("sw_vers -productVersion");
00658 sp += " Mac OS X ";
00659 printf("* SYS: %s\n",sp.Data());
00660 }
00661 } else {
00662 const Char_t *os = gSystem->Getenv("OS");
00663 if (!os) printf("* SYS: Windows 95\n");
00664 else printf("* SYS: %s %s \n",os,gSystem->Getenv("PROCESSOR_IDENTIFIER"));
00665 }
00666
00667 printf("******************************************************************\n");
00668 gBenchmark->Print("stressFit");
00669 #ifdef __CINT__
00670 Double_t reftime = 86.34;
00671 #else
00672 Double_t reftime = 12.07;
00673 #endif
00674 const Double_t rootmarks = 800.*reftime/gBenchmark->GetCpuTime("stressFit");
00675
00676 printf("******************************************************************\n");
00677 printf("* ROOTMARKS =%6.1f * Root%-8s %d/%d\n",rootmarks,gROOT->GetVersion(),
00678 gROOT->GetVersionDate(),gROOT->GetVersionTime());
00679 printf("******************************************************************\n");
00680
00681 return 0;
00682 }
00683
00684
00685 #ifndef __CINT__
00686
00687 int main(int argc,const char *argv[])
00688 {
00689 gBenchmark = new TBenchmark();
00690 const char *fitter = "Minuit";
00691 if (argc > 1) fitter = argv[1];
00692 if (strcmp(fitter,"Minuit") && strcmp(fitter,"Minuit2") && strcmp(fitter,"Fumili")) {
00693 printf("stressFit illegal option %s, using Minuit instead\n",fitter);
00694 fitter = "Minuit";
00695 }
00696 Int_t N = 2000;
00697 if (argc > 2) N = atoi(argv[2]);
00698 stressFit(fitter,N);
00699 return 0;
00700 }
00701
00702 #endif