00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "BAT/BCEngineMCMC.h"
00011
00012 #include "BAT/BCParameter.h"
00013 #include "BAT/BCDataPoint.h"
00014 #include "BAT/BCLog.h"
00015
00016 #include <TH1D.h>
00017 #include <TH2D.h>
00018 #include <TTree.h>
00019 #include <TRandom3.h>
00020 #include <TPrincipal.h>
00021
00022 #include <iostream>
00023
00024 #include <math.h>
00025
00026
00027 #define DEBUG 0
00028
00029
00030
00031 BCEngineMCMC::BCEngineMCMC()
00032 {
00033
00034 fMCMCNParameters = 0;
00035 fMCMCFlagWriteChainToFile = false;
00036 fMCMCFlagPreRun = false;
00037 fMCMCEfficiencyMin = 0.15;
00038 fMCMCEfficiencyMax = 0.50;
00039
00040 this -> MCMCSetValuesDefault();
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 fMCMCRandom = new TRandom3(0);
00056
00057
00058
00059 }
00060
00061
00062
00063 BCEngineMCMC::BCEngineMCMC(int n)
00064 {
00065
00066 fMCMCNChains = n;
00067
00068
00069 BCEngineMCMC();
00070 }
00071
00072
00073
00074 BCEngineMCMC::~BCEngineMCMC()
00075 {
00076
00077 if (fMCMCRandom) delete fMCMCRandom;
00078
00079
00080 if (fMCMCPCA) delete fMCMCPCA;
00081
00082
00083 for (int i = 0; i < int(fMCMCH1Marginalized.size()); ++i)
00084 if (fMCMCH1Marginalized[i])
00085 delete fMCMCH1Marginalized[i];
00086
00087 fMCMCH1Marginalized.clear();
00088
00089 for (int i = 0; i < int(fMCMCH2Marginalized.size()); ++i)
00090 if (fMCMCH2Marginalized[i])
00091 delete fMCMCH2Marginalized[i];
00092
00093 fMCMCH2Marginalized.clear();
00094
00095
00096
00097 }
00098
00099
00100
00101 BCEngineMCMC::BCEngineMCMC(const BCEngineMCMC & enginemcmc)
00102 {
00103 enginemcmc.Copy(*this);
00104 }
00105
00106
00107
00108 BCEngineMCMC & BCEngineMCMC::operator = (const BCEngineMCMC & enginemcmc)
00109 {
00110 if (this != &enginemcmc)
00111 enginemcmc.Copy(* this);
00112
00113 return * this;
00114 }
00115
00116
00117
00118 TH2D * BCEngineMCMC::MCMCGetH2Marginalized(int index1, int index2)
00119 {
00120 int counter = 0;
00121 int index = 0;
00122
00123
00124 for(int i = 0; i < fMCMCNParameters; i++)
00125 for (int j = 0; j < i; ++j)
00126 {
00127 if(j == index1 && i == index2)
00128 index = counter;
00129 counter++;
00130 }
00131
00132 return fMCMCH2Marginalized[index];
00133 }
00134
00135
00136
00137 std::vector <double> BCEngineMCMC::MCMCGetMaximumPoint(int i)
00138 {
00139
00140 std::vector <double> x;
00141
00142
00143 if (i < 0 || i >= fMCMCNChains)
00144 return x;
00145
00146
00147 for (int j = 0; j < fMCMCNParameters; ++j)
00148 x.push_back(fMCMCMaximumPoints.at(i * fMCMCNParameters + j));
00149
00150 return x;
00151 }
00152
00153
00154
00155 void BCEngineMCMC::MCMCSetNChains(int n)
00156 {
00157 fMCMCNChains = n;
00158
00159
00160 this -> MCMCInitialize();
00161 }
00162
00163
00164
00165 void BCEngineMCMC::MCMCSetInitialPosition(int chain, std::vector<double> x0)
00166 {
00167
00168 if (chain >= fMCMCNChains)
00169 {
00170 fMCMCInitialPosition.clear();
00171 return;
00172 }
00173
00174 if (int(x0.size()) == fMCMCNParameters)
00175 {
00176 fMCMCInitialPosition.clear();
00177 for (int j = 0; j < fMCMCNChains; ++j)
00178 for (int i = 0; i < fMCMCNParameters; ++i)
00179 fMCMCInitialPosition.push_back(x0.at(i));
00180 }
00181 else
00182 return;
00183
00184 bool flagin = true;
00185 for (int j = 0; j < fMCMCNChains; ++j)
00186 for (int i = 0; i < fMCMCNParameters; ++i)
00187 if (fMCMCInitialPosition[j * fMCMCNParameters + i] < fMCMCBoundaryMin[i] ||
00188 fMCMCInitialPosition[j * fMCMCNParameters + i] > fMCMCBoundaryMax[i])
00189 flagin = false;
00190
00191 if (flagin == false)
00192 {
00193 fMCMCInitialPosition.clear();
00194 return;
00195 }
00196
00197 else
00198 for (int i = 0; i < fMCMCNParameters; ++i)
00199 fMCMCInitialPosition[chain * fMCMCNParameters + i] = x0.at(i);
00200
00201
00202 this -> MCMCSetFlagInitialPosition(2);
00203 }
00204
00205
00206
00207 void BCEngineMCMC::MCMCSetInitialPosition(std::vector<double> x0)
00208 {
00209 for (int i = 0; i < fMCMCNChains; ++i)
00210 this -> MCMCSetInitialPosition(i, x0);
00211 }
00212
00213
00214
00215 void BCEngineMCMC::MCMCSetInitialPositions(std::vector<double> x0s)
00216 {
00217 if (int(fMCMCInitialPosition.size()) != (fMCMCNChains * fMCMCNParameters))
00218 return;
00219
00220 if (int(x0s.size()) != (fMCMCNChains * fMCMCNParameters))
00221 return;
00222
00223
00224 for (int i = 0; i < (fMCMCNChains * fMCMCNParameters); ++i)
00225 fMCMCInitialPosition[i] = x0s.at(i);
00226
00227
00228 this -> MCMCSetFlagInitialPosition(2);
00229 }
00230
00231
00232
00233 void BCEngineMCMC::MCMCSetMarkovChainTrees(std::vector <TTree *> trees)
00234 {
00235
00236 fMCMCTrees.clear();
00237
00238
00239 for (int i = 0; i < int(trees.size()); ++i)
00240 fMCMCTrees.push_back(trees[i]);
00241 }
00242
00243
00244
00245 void BCEngineMCMC::Copy(BCEngineMCMC & enginemcmc) const
00246 {}
00247
00248
00249
00250 void BCEngineMCMC::MCMCTrialFunction(std::vector <double> &x)
00251 {
00252
00253 for (int i = 0; i < fMCMCNParameters; ++i)
00254 x[i] = fMCMCTrialFunctionScale * 2.0 * (0.5 - fMCMCRandom -> Rndm());
00255 }
00256
00257
00258
00259 void BCEngineMCMC::MCMCTrialFunctionSingle(int ichain, int iparameter, std::vector <double> &x)
00260 {
00261
00262
00263
00264 x[iparameter] = fMCMCTrialFunctionScaleFactor[ichain * fMCMCNParameters + iparameter] * 2.0 * (0.5 - fMCMCRandom -> Rndm());
00265 }
00266
00267
00268
00269 double BCEngineMCMC::MCMCTrialFunctionIndependent(std::vector <double> &xnew, std::vector <double> &xold, bool newpoint)
00270 {
00271
00272 if (newpoint)
00273 for (int i = 0; i < fMCMCNParameters; ++i)
00274 xnew[i] = fMCMCRandom -> Rndm() * (fMCMCBoundaryMax.at(i) - fMCMCBoundaryMin.at(i));
00275
00276 double prob = 1.0;
00277 for (int i = 0; i < fMCMCNParameters; ++i)
00278 prob /= fMCMCBoundaryMax.at(i) - fMCMCBoundaryMin.at(i);
00279
00280 return prob;
00281 }
00282
00283
00284
00285 void BCEngineMCMC::MCMCTrialFunctionAuto(std::vector <double> &x)
00286 {
00287
00288 for (int i = 0; i < fMCMCNParameters; ++i)
00289 x[i] = fMCMCRandom -> Gaus(fMCMCPCAMean[i], sqrt(fMCMCPCAVariance[i]));
00290 }
00291
00292
00293
00294 std::vector <double> BCEngineMCMC::MCMCGetTrialFunctionScaleFactor(int ichain)
00295 {
00296
00297 std::vector <double> x;
00298
00299
00300 if (ichain < 0 || ichain >= fMCMCNChains)
00301 return x;
00302
00303
00304 for (int j = 0; j < fMCMCNParameters; ++j)
00305 x.push_back(fMCMCTrialFunctionScaleFactor.at(ichain * fMCMCNParameters + j));
00306
00307 return x;
00308 }
00309
00310
00311
00312 double BCEngineMCMC::MCMCGetTrialFunctionScaleFactor(int ichain, int ipar)
00313 {
00314
00315 if (ichain < 0 || ichain >= fMCMCNChains)
00316 return 0;
00317
00318
00319 if (ipar < 0 || ipar >= fMCMCNParameters)
00320 return 0;
00321
00322
00323 return fMCMCTrialFunctionScaleFactor.at(ichain * fMCMCNChains + ipar);
00324 }
00325
00326
00327
00328 std::vector <double> BCEngineMCMC::MCMCGetx(int ichain)
00329 {
00330
00331 std::vector <double> x;
00332
00333
00334 if (ichain < 0 || ichain >= fMCMCNChains)
00335 return x;
00336
00337
00338 for (int j = 0; j < fMCMCNParameters; ++j)
00339 x.push_back(fMCMCx.at(ichain * fMCMCNParameters + j));
00340
00341 return x;
00342 }
00343
00344
00345
00346 double BCEngineMCMC::MCMCGetx(int ichain, int ipar)
00347 {
00348
00349 if (ichain < 0 || ichain >= fMCMCNChains)
00350 return 0;
00351
00352
00353 if (ipar < 0 || ipar >= fMCMCNParameters)
00354 return 0;
00355
00356
00357 return fMCMCx.at(ichain * fMCMCNParameters + ipar);
00358 }
00359
00360
00361
00362 double BCEngineMCMC::MCMCGetLogProbx(int ichain)
00363 {
00364
00365 if (ichain < 0 || ichain >= fMCMCNChains)
00366 return -1;
00367
00368
00369 return fMCMCLogProbx.at(ichain);
00370 }
00371
00372
00373
00374 bool BCEngineMCMC::MCMCGetProposalPointMetropolis(int chain, std::vector <double> &x, bool pca)
00375 {
00376
00377 this -> MCMCTrialFunction(x);
00378
00379
00380 if (pca == false)
00381 {
00382
00383 for (int i = 0; i < fMCMCNParameters; ++i)
00384 x[i] = fMCMCx[chain * fMCMCNParameters + i] + x[i] * (fMCMCBoundaryMax.at(i) - fMCMCBoundaryMin.at(i));
00385 }
00386 else
00387 {
00388
00389 double * newp = new double[fMCMCNParameters];
00390 double * newx = new double[fMCMCNParameters];
00391
00392 for (int i = 0; i < fMCMCNParameters; i++)
00393 {
00394 newp[i] = 0.;
00395 newx[i] = 0.;
00396 }
00397
00398
00399 this -> MCMCTrialFunctionAuto(x);
00400
00401
00402 for (int i = 0; i < fMCMCNParameters; i++)
00403 newx[i] = fMCMCx[chain * fMCMCNParameters + i];
00404
00405
00406 fMCMCPCA -> X2P(newx, newp);
00407
00408
00409 for (int i = 0; i < fMCMCNParameters; i++)
00410 newp[i] += fMCMCTrialFunctionScale * x[i];
00411
00412
00413
00414 fMCMCPCA -> P2X(newp, newx, fMCMCNDimensionsPCA);
00415
00416
00417 for (int i = 0; i < fMCMCNParameters; ++i)
00418 x[i] = newx[i];
00419
00420 delete [] newp;
00421 delete [] newx;
00422 }
00423
00424
00425 for (int i = 0; i < fMCMCNParameters; ++i)
00426 if ((x[i] < fMCMCBoundaryMin[i]) || (x[i] > fMCMCBoundaryMax[i]))
00427 return false;
00428
00429 return true;
00430 }
00431
00432
00433 bool BCEngineMCMC::MCMCGetProposalPointMetropolis(int chain, int parameter, std::vector <double> &x, bool pca)
00434 {
00435
00436
00437 this -> MCMCTrialFunctionSingle(chain, parameter, x);
00438
00439
00440 if (pca == false)
00441 {
00442
00443 for (int i = 0; i < fMCMCNParameters; ++i)
00444 if (i != parameter)
00445 x[i] = fMCMCx[chain * fMCMCNParameters + i];
00446
00447
00448 x[parameter] = fMCMCx[chain * fMCMCNParameters + parameter] + x[parameter] * (fMCMCBoundaryMax.at(parameter) - fMCMCBoundaryMin.at(parameter));
00449 }
00450 else
00451 {
00452
00453 double * newp = new double[fMCMCNParameters];
00454 double * newx = new double[fMCMCNParameters];
00455
00456 for (int i = 0; i < fMCMCNParameters; i++)
00457 {
00458 newp[i] = 0.;
00459 newx[i] = 0.;
00460 }
00461
00462
00463 for (int i = 0; i < fMCMCNParameters; i++)
00464 newx[i] = fMCMCx[chain * fMCMCNParameters + i];
00465
00466
00467 fMCMCPCA -> X2P(newx, newp);
00468
00469
00470 newp[parameter] += x[parameter] * sqrt(fMCMCPCAVariance[parameter]);
00471
00472
00473
00474 fMCMCPCA -> P2X(newp, newx, fMCMCNDimensionsPCA);
00475
00476
00477 for (int i = 0; i < fMCMCNParameters; ++i)
00478 x[i] = newx[i];
00479
00480 delete [] newp;
00481 delete [] newx;
00482 }
00483
00484
00485 for (int i = 0; i < fMCMCNParameters; ++i)
00486 if ((x[i] < fMCMCBoundaryMin[i]) || (x[i] > fMCMCBoundaryMax[i]))
00487 return false;
00488
00489 return true;
00490 }
00491
00492
00493
00494 bool BCEngineMCMC::MCMCGetProposalPointMetropolisHastings(int chain, std::vector <double> &xnew, std::vector <double> &xold)
00495 {
00496
00497 this -> MCMCTrialFunctionIndependent(xnew, xold, true);
00498
00499
00500 for (int i = 0; i < fMCMCNParameters; ++i)
00501 if ((xnew[i] < fMCMCBoundaryMin[i]) || (xnew[i] > fMCMCBoundaryMax[i]))
00502 return false;
00503
00504 return true;
00505 }
00506
00507
00508
00509 void BCEngineMCMC::MCMCGetNewPointPCA()
00510 {
00511
00512 for (int i = 0; i < fMCMCNParameters; ++i)
00513 fMCMCx[i] = fMCMCBoundaryMin.at(i) + (fMCMCBoundaryMax.at(i) - fMCMCBoundaryMin.at(i)) * 2.0 * (0.5 - fMCMCRandom -> Rndm());
00514 }
00515
00516
00517
00518 bool BCEngineMCMC::MCMCGetNewPointMetropolis(int chain, int parameter, bool pca)
00519 {
00520
00521 int index = chain * fMCMCNParameters;
00522
00523
00524 int counter = 0;
00525
00526 while (!this -> MCMCGetProposalPointMetropolis(chain, parameter, fMCMCxLocal, pca) && counter < 1000)
00527 counter++;
00528
00529
00530 double p0 = fMCMCLogProbx[chain];
00531 double p1 = this -> LogEval(fMCMCxLocal);
00532
00533
00534 bool accept = false;
00535
00536
00537 if (p1 >= p0)
00538 accept = true;
00539
00540 else
00541 {
00542 double r = log(fMCMCRandom -> Rndm());
00543
00544 if(r < p1 - p0)
00545 accept = true;
00546 }
00547
00548
00549 if(accept)
00550 {
00551
00552 fMCMCNTrialsTrue[chain * fMCMCNParameters + parameter]++;
00553
00554
00555 for(int i = 0; i < fMCMCNParameters; ++i)
00556 {
00557
00558 fMCMCx[index + i] = fMCMCxLocal[i];
00559
00560
00561 fMCMCLogProbx[chain] = p1;
00562 }
00563 }
00564 else
00565 {
00566
00567 fMCMCNTrialsFalse[chain * fMCMCNParameters + parameter]++;
00568 }
00569
00570
00571 fMCMCNIterations[chain]++;
00572
00573 return accept;
00574 }
00575
00576
00577
00578 bool BCEngineMCMC::MCMCGetNewPointMetropolis(int chain, bool pca)
00579 {
00580
00581 int index = chain * fMCMCNParameters;
00582
00583
00584 int counter = 0;
00585
00586 while (!this -> MCMCGetProposalPointMetropolis(chain, fMCMCxLocal, pca) && counter < 1000)
00587 counter++;
00588
00589
00590 double p0 = fMCMCLogProbx[chain];
00591 double p1 = this -> LogEval(fMCMCxLocal);
00592
00593
00594 bool accept = false;
00595
00596
00597 if (p1 >= p0)
00598 accept = true;
00599
00600
00601 else
00602 {
00603 double r = log(fMCMCRandom -> Rndm());
00604
00605 if(r < p1 - p0)
00606 accept = true;
00607 }
00608
00609
00610 if(accept)
00611 {
00612
00613 for (int i = 0; i < fMCMCNParameters; ++i)
00614 fMCMCNTrialsTrue[chain * fMCMCNParameters + i]++;
00615
00616
00617 for(int i = 0; i < fMCMCNParameters; ++i)
00618 {
00619
00620 fMCMCx[index + i] = fMCMCxLocal[i];
00621
00622
00623 fMCMCLogProbx[chain] = p1;
00624 }
00625 }
00626 else
00627 {
00628
00629 for (int i = 0; i < fMCMCNParameters; ++i)
00630 fMCMCNTrialsFalse[chain * fMCMCNParameters + i]++;
00631 }
00632
00633
00634 fMCMCNIterations[chain]++;
00635
00636 return accept;
00637 }
00638
00639
00640
00641 bool BCEngineMCMC::MCMCGetNewPointMetropolisHastings(int chain)
00642 {
00643
00644 int index = chain * fMCMCNParameters;
00645
00646
00647 std::vector <double> xold;
00648 for (int i = 0; i < fMCMCNParameters; ++i)
00649 xold.push_back(fMCMCxLocal.at(i));
00650
00651
00652 int counter = 0;
00653 while (!this -> MCMCGetProposalPointMetropolisHastings(chain, fMCMCxLocal, xold) && counter < 1000)
00654 counter++;
00655
00656
00657 double p0 = fMCMCLogProbx[chain] + log(this -> MCMCTrialFunctionIndependent(xold, fMCMCxLocal, false));
00658 double p1 = this -> LogEval(fMCMCxLocal) + log(this -> MCMCTrialFunctionIndependent(xold, fMCMCxLocal, false));
00659
00660
00661 bool accept = false;
00662
00663
00664 if (p1 >= p0)
00665 accept = true;
00666
00667 else
00668 {
00669 if( log(fMCMCRandom -> Rndm()) < p1 - p0)
00670 accept = true;
00671 }
00672
00673
00674 if(accept)
00675 {
00676
00677 for (int i = 0; i < fMCMCNParameters; ++i)
00678 fMCMCNTrialsTrue[chain * fMCMCNParameters + i]++;
00679
00680
00681 for(int i = 0; i < fMCMCNParameters; ++i)
00682 {
00683
00684 fMCMCx[index + i] = fMCMCxLocal[i];
00685
00686
00687 fMCMCLogProbx[chain] = p1;
00688 }
00689 }
00690 else
00691 {
00692
00693 for (int i = 0; i < fMCMCNParameters; ++i)
00694 fMCMCNTrialsFalse[chain * fMCMCNParameters + i]++;
00695 }
00696
00697
00698 fMCMCNIterations[chain]++;
00699
00700 return accept;
00701 }
00702
00703
00704
00705 void BCEngineMCMC::MCMCUpdateStatisticsModeConvergence()
00706 {
00707 double * mode_minimum = new double[fMCMCNParameters];
00708 double * mode_maximum = new double[fMCMCNParameters];
00709 double * mode_average = new double[fMCMCNParameters];
00710
00711
00712 for (int j = 0; j < fMCMCNParameters; ++j)
00713 {
00714 mode_minimum[j] = fMCMCMaximumPoints[j];
00715 mode_maximum[j] = fMCMCMaximumPoints[j];
00716 mode_average[j] = 0;
00717 }
00718
00719
00720 for (int i = 0; i < fMCMCNChains; ++i)
00721 for (int j = 0; j < fMCMCNParameters; ++j)
00722 {
00723 if (fMCMCMaximumPoints[i * fMCMCNParameters + j] < mode_minimum[j])
00724 mode_minimum[j] = fMCMCMaximumPoints[i * fMCMCNParameters + j];
00725
00726 if (fMCMCMaximumPoints[i * fMCMCNParameters + j] > mode_maximum[j])
00727 mode_maximum[j] = fMCMCMaximumPoints[i * fMCMCNParameters + j];
00728
00729 mode_average[j] += fMCMCMaximumPoints[i * fMCMCNParameters + j] / double(fMCMCNChains);
00730 }
00731
00732 for (int j = 0; j < fMCMCNParameters; ++j)
00733 fMCMCNumericalPrecisionModeValues[j] = (mode_maximum[j] - mode_minimum[j]);
00734
00735
00736 delete [] mode_minimum;
00737 delete [] mode_maximum;
00738 delete [] mode_average;
00739 }
00740
00741
00742
00743 void BCEngineMCMC::MCMCUpdateStatisticsCheckMaximum()
00744 {
00745
00746 for (int i = 0; i < fMCMCNChains; ++i)
00747 {
00748 if (fMCMCLogProbx[i] > fMCMCMaximumLogProb[i] || fMCMCNIterations[i] == 1)
00749 {
00750 fMCMCMaximumLogProb[i] = fMCMCLogProbx[i];
00751 for (int j = 0; j < fMCMCNParameters; ++j)
00752 fMCMCMaximumPoints[i * fMCMCNParameters + j] = fMCMCx[i * fMCMCNParameters + j];
00753 }
00754 }
00755 }
00756
00757
00758
00759 void BCEngineMCMC::MCMCUpdateStatisticsFillHistograms()
00760 {
00761
00762 for (int i = 0; i < fMCMCNChains; ++i)
00763 {
00764
00765 for (int j = 0; j < fMCMCNParameters; ++j)
00766 fMCMCH1Marginalized[j] -> Fill(fMCMCx[i * fMCMCNParameters + j]);
00767
00768
00769 int counter = 0;
00770
00771 for (int j = 0; j < fMCMCNParameters; ++j)
00772 for (int k = 0; k < j; ++k)
00773 {
00774 fMCMCH2Marginalized[counter] -> Fill(
00775 fMCMCx[i * fMCMCNParameters + k],
00776 fMCMCx[i * fMCMCNParameters + j]);
00777 counter ++;
00778 }
00779 }
00780 }
00781
00782
00783
00784 void BCEngineMCMC::MCMCUpdateStatisticsTestConvergenceAllChains()
00785 {
00786
00787 int npoints = fMCMCNTrialsTrue[0] + fMCMCNTrialsFalse[0];
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 if (fMCMCNChains > 1 && npoints > 1)
00798 {
00799
00800 bool flag_convergence = true;
00801
00802
00803 for (int iparameters = 0; iparameters < fMCMCNParameters; ++iparameters)
00804 {
00805 double sum = 0;
00806 double sum2 = 0;
00807 double sumv = 0;
00808
00809
00810 for (int ichains = 0; ichains < fMCMCNChains; ++ichains)
00811 {
00812
00813 int index = ichains * fMCMCNParameters + iparameters;
00814
00815
00816 fMCMCMeanx[index] += (fMCMCx[index] - fMCMCMeanx[index]) / double(npoints);
00817
00818
00819 fMCMCVariancex[index] = (1.0 - 1/double(npoints)) * fMCMCVariancex[index]
00820 + (fMCMCx[index] - fMCMCMeanx[index]) * (fMCMCx[index] - fMCMCMeanx[index]) / double(npoints - 1);
00821
00822 sum += fMCMCMeanx[index];
00823 sum2 += fMCMCMeanx[index] * fMCMCMeanx[index];
00824 sumv += fMCMCVariancex[index];
00825 }
00826
00827
00828 double mean = sum / double(fMCMCNChains);
00829 double B = (sum2 / double(fMCMCNChains) - mean * mean) * double(fMCMCNChains) / double(fMCMCNChains-1) * double(npoints);
00830 double W = sumv * double(npoints) / double(npoints - 1) / double(fMCMCNChains);
00831
00832 double r = 100.0;
00833
00834 if (W > 0)
00835 {
00836 r = sqrt( ( (1-1/double(npoints)) * W + 1/double(npoints) * B ) / W);
00837
00838 fMCMCRValueParameters[iparameters] = r;
00839 }
00840
00841
00842
00843
00844 if (! ((fMCMCRValueParameters[iparameters]-1.0) < fMCMCRValueParametersCriterion))
00845 flag_convergence = false;
00846 }
00847
00848
00849 double sum = 0;
00850 double sum2 = 0;
00851 double sumv = 0;
00852
00853
00854 for (int i = 0; i < fMCMCNChains; ++i)
00855 {
00856
00857 fMCMCMean[i] += (fMCMCLogProbx[i] - fMCMCMean[i]) / double(npoints);
00858
00859
00860 if (npoints > 1)
00861 fMCMCVariance[i] = (1.0 - 1/double(npoints)) * fMCMCVariance[i]
00862 + (fMCMCLogProbx[i] - fMCMCMean[i]) * (fMCMCLogProbx[i] - fMCMCMean[i]) / double(npoints - 1);
00863
00864 sum += fMCMCMean[i];
00865 sum2 += fMCMCMean[i] * fMCMCMean[i]; ;
00866 sumv += fMCMCVariance[i];
00867 }
00868
00869
00870 double mean = sum / double(fMCMCNChains);
00871 double B = (sum2 / double(fMCMCNChains) - mean * mean) * double(fMCMCNChains) / double(fMCMCNChains-1) * double(npoints);
00872 double W = sumv * double(npoints) / double(npoints - 1) / double(fMCMCNChains);
00873 double r = 100.0;
00874
00875 if (W > 0)
00876 {
00877 r = sqrt( ( (1-1/double(npoints)) * W + 1/double(npoints) * B ) / W);
00878
00879 fMCMCRValue = r;
00880 }
00881
00882
00883 if (! ((fMCMCRValue-1.0) < fMCMCRValueCriterion))
00884 flag_convergence = false;
00885
00886
00887 if (fMCMCNIterationsConvergenceGlobal == -1 && flag_convergence == true)
00888 fMCMCNIterationsConvergenceGlobal = fMCMCNIterations[0] / fMCMCNParameters;
00889 }
00890
00891 }
00892
00893
00894
00895 void BCEngineMCMC::MCMCUpdateStatisticsWriteChains()
00896 {
00897
00898 for (int i = 0; i < fMCMCNChains; ++i)
00899 fMCMCTrees[i] -> Fill();
00900 }
00901
00902
00903
00904 void BCEngineMCMC::MCMCUpdateStatistics()
00905 {
00906
00907 this -> MCMCUpdateStatisticsCheckMaximum();
00908
00909
00910 this -> MCMCUpdateStatisticsFillHistograms();
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920 if (fMCMCFlagWriteChainToFile)
00921 this -> MCMCUpdateStatisticsWriteChains();
00922 }
00923
00924
00925
00926 double BCEngineMCMC::LogEval(std::vector <double> parameters)
00927 {
00928
00929
00930 return 0.0;
00931 }
00932
00933
00934
00935 int BCEngineMCMC::MCMCMetropolisPreRun()
00936 {
00937
00938 BCLog::Out(BCLog::summary, BCLog::summary, "Pre-run Metropolis MCMC...");
00939
00940
00941 this -> MCMCInitialize();
00942 this -> MCMCInitializeMarkovChains();
00943
00944
00945 int ndigits = (int)log10(fMCMCNParameters) +1;
00946 if(ndigits<4)
00947 ndigits=4;
00948
00949
00950 if (fMCMCNIterationsBurnIn > 0)
00951 BCLog::Out(BCLog::detail, BCLog::detail,
00952 Form(" --> Start burn-in run with %i iterations", fMCMCNIterationsBurnIn));
00953
00954
00955 if (fMCMCFlagOrderParameters)
00956 {
00957 for (int i = 0; i < fMCMCNIterationsBurnIn; ++i)
00958 for (int j = 0; j < fMCMCNChains; ++j)
00959 for (int k = 0; k < fMCMCNParameters; ++k)
00960 this -> MCMCGetNewPointMetropolis(j, k, false);
00961 }
00962
00963 else
00964 {
00965 for (int i = 0; i < fMCMCNIterationsBurnIn; ++i)
00966 {
00967
00968 for (int ichains = 0; ichains < fMCMCNChains; ++ichains)
00969
00970 this -> MCMCGetNewPointMetropolis(ichains, false);
00971 }
00972 }
00973
00974
00975 this -> MCMCResetRunStatistics();
00976 fMCMCNIterationsConvergenceGlobal = -1;
00977
00978
00979 double * dataall = 0;
00980 double * sum = 0;
00981 double * sum2 = 0;
00982
00983
00984 if (fMCMCFlagPCA)
00985 {
00986 BCLog::Out(BCLog::detail, BCLog::detail, " --> PCA switched on");
00987
00988
00989 fMCMCPCA = new TPrincipal(fMCMCNParameters, "D");
00990
00991
00992 dataall = new double[fMCMCNParameters * fMCMCNIterationsPCA];
00993
00994
00995 sum = new double[fMCMCNParameters];
00996 sum2 = new double[fMCMCNParameters];
00997
00998
00999 for (int i = 0; i < fMCMCNParameters; ++i)
01000 {
01001 sum[i] = 0.0;
01002 sum2[i] = 0.0;
01003 }
01004
01005 if (fMCMCFlagPCATruncate == true)
01006 {
01007 fMCMCNDimensionsPCA = 0;
01008
01009 const double * ma = fMCMCPCA -> GetEigenValues() -> GetMatrixArray();
01010
01011 for (int i = 0; i < fMCMCNParameters; ++i)
01012 if (ma[i]/ma[0] > fMCMCPCAMinimumRatio)
01013 fMCMCNDimensionsPCA++;
01014
01015 BCLog::Out(BCLog::detail, BCLog::detail,
01016 Form(" --> Use %i out of %i dimensions", fMCMCNDimensionsPCA, fMCMCNParameters));
01017 }
01018 else
01019 fMCMCNDimensionsPCA = fMCMCNParameters;
01020 }
01021 else
01022 BCLog::Out(BCLog::detail, BCLog::detail, " --> No PCA run");
01023
01024
01025 this -> MCMCResetRunStatistics();
01026 fMCMCNIterationsConvergenceGlobal = -1;
01027
01028
01029 BCLog::Out(BCLog::summary, BCLog::summary,
01030 Form(" --> Perform MCMC pre-run with %i chains, each with maximum %i iterations", fMCMCNChains, fMCMCNIterationsMax));
01031
01032 bool tempflag_writetofile = fMCMCFlagWriteChainToFile;
01033
01034
01035 fMCMCFlagWriteChainToFile = false;
01036
01037 int counter = 0;
01038 int counterupdate = 0;
01039 bool convergence = false;
01040 bool flagefficiency = false;
01041
01042 std::vector <double> efficiency;
01043
01044 for (int i = 0; i < fMCMCNParameters; ++i)
01045 for (int j = 0; j < fMCMCNChains; ++j)
01046 efficiency.push_back(0.);
01047
01048 if (fMCMCFlagPCA)
01049 {
01050 fMCMCNIterationsPreRunMin = fMCMCNIterationsPCA;
01051 fMCMCNIterationsMax = fMCMCNIterationsPCA;
01052 }
01053
01054
01055 while (counter < fMCMCNIterationsPreRunMin || (counter < fMCMCNIterationsMax && !(convergence && flagefficiency)))
01056 {
01057
01058 convergence = false;
01059
01060
01061 fMCMCNIterationsConvergenceGlobal = -1;
01062
01063
01064 if (fMCMCFlagOrderParameters)
01065 {
01066
01067 for (int iparameters = 0; iparameters < fMCMCNParameters; ++iparameters)
01068 {
01069
01070 for (int ichains = 0; ichains < fMCMCNChains; ++ichains)
01071 {
01072 this -> MCMCGetNewPointMetropolis(ichains, iparameters, false);
01073
01074
01075 if (fMCMCFlagPCA)
01076 {
01077
01078 double * data = new double[fMCMCNParameters];
01079
01080
01081 for (int j = 0; j < fMCMCNParameters; ++j)
01082 {
01083 data[j] = fMCMCx[j];
01084 dataall[ichains * fMCMCNParameters + j] = fMCMCx[j];
01085 }
01086
01087
01088 fMCMCPCA -> AddRow(data);
01089
01090
01091 delete [] data;
01092
01093 }
01094 }
01095
01096
01097 this -> MCMCUpdateStatisticsCheckMaximum();
01098
01099
01100
01101
01102
01103 }
01104 }
01105
01106
01107 else
01108 {
01109
01110 for (int ichains = 0; ichains < fMCMCNChains; ++ichains)
01111
01112 this -> MCMCGetNewPointMetropolis(ichains, false);
01113
01114
01115 if (fMCMCFlagPCA)
01116 {
01117
01118 double * data = new double[fMCMCNParameters];
01119
01120
01121 for (int j = 0; j < fMCMCNParameters; ++j)
01122 {
01123
01124 for (int ichains = 0; ichains < fMCMCNChains; ++ichains)
01125 {
01126 data[j] = fMCMCx[j];
01127 dataall[ichains * fMCMCNParameters + j] = fMCMCx[j];
01128 }
01129 }
01130
01131
01132 fMCMCPCA -> AddRow(data);
01133
01134
01135 delete [] data;
01136 }
01137
01138
01139 this -> MCMCUpdateStatisticsCheckMaximum();
01140
01141
01142
01143
01144 }
01145
01146
01147
01148
01149 if (counterupdate % (fMCMCNIterationsUpdate*(fMCMCNParameters+1)) == 0 && counterupdate > 0 && counter >= fMCMCNIterationsPreRunMin)
01150 {
01151
01152 BCLog::Out(BCLog::detail, BCLog::detail,
01153 Form(" --> Iteration %i", fMCMCNIterations[0] / fMCMCNParameters));
01154
01155 bool rvalues_ok = true;
01156 static bool has_converged = false;
01157
01158
01159
01160
01161
01162 fMCMCNIterationsConvergenceGlobal = -1;
01163
01164 this -> MCMCUpdateStatisticsTestConvergenceAllChains();
01165
01166
01167
01168
01169
01170 if (fMCMCNIterationsConvergenceGlobal > 0)
01171 convergence = true;
01172
01173
01174 if (convergence && fMCMCNChains > 1)
01175 BCLog::Out(BCLog::detail, BCLog::detail,
01176 Form(" * Convergence status: Set of %i Markov chains converged within %i iterations.", fMCMCNChains, fMCMCNIterationsConvergenceGlobal));
01177 else if (!convergence && fMCMCNChains > 1)
01178 {
01179 BCLog::Out(BCLog::detail, BCLog::detail,
01180 Form(" * Convergence status: Set of %i Markov chains did not converge after %i iterations.", fMCMCNChains, counter));
01181
01182 BCLog::Out(BCLog::detail, BCLog::detail, " - R-Values:");
01183 for (int iparameter = 0; iparameter < fMCMCNParameters; ++iparameter)
01184 {
01185 if(fabs(fMCMCRValueParameters[iparameter]-1.) < fMCMCRValueParametersCriterion)
01186 BCLog::Out(BCLog::detail, BCLog::detail,
01187 Form( TString::Format(" parameter %%%di : %%.06f",ndigits), iparameter, fMCMCRValueParameters.at(iparameter)));
01188 else
01189 {
01190 BCLog::Out(BCLog::detail, BCLog::detail,
01191 Form( TString::Format(" parameter %%%di : %%.06f <--",ndigits), iparameter, fMCMCRValueParameters.at(iparameter)));
01192 rvalues_ok = false;
01193 }
01194 }
01195 if(fabs(fMCMCRValue-1.) < fMCMCRValueCriterion)
01196 BCLog::Out(BCLog::detail, BCLog::detail, Form(" log-likelihood : %.06f", fMCMCRValue));
01197 else
01198 {
01199 BCLog::Out(BCLog::detail, BCLog::detail, Form(" log-likelihood : %.06f <--", fMCMCRValue));
01200 rvalues_ok = false;
01201 }
01202 }
01203
01204 if(!has_converged)
01205 if(rvalues_ok)
01206 has_converged = true;
01207
01208
01209
01210
01211
01212
01213 flagefficiency = true;
01214
01215 bool flagprintefficiency = true;
01216
01217
01218 for (int ichains = 0; ichains < fMCMCNChains; ++ichains)
01219 {
01220
01221 for (int iparameter = 0; iparameter < fMCMCNParameters; ++iparameter)
01222 {
01223
01224 int ipc = ichains * fMCMCNParameters + iparameter;
01225
01226
01227 efficiency[ipc] = double(fMCMCNTrialsTrue[ipc]) / double(fMCMCNTrialsTrue[ipc] + fMCMCNTrialsFalse[ipc]);
01228
01229
01230 if (efficiency[ipc] < fMCMCEfficiencyMin && fMCMCTrialFunctionScaleFactor[ipc] > .01)
01231 {
01232 if (flagprintefficiency)
01233 {
01234 BCLog::Out(BCLog::detail, BCLog::detail,
01235 Form(" * Efficiency status: Efficiencies not within pre-defined range."));
01236 BCLog::Out(BCLog::detail, BCLog::detail,
01237 Form(" - Efficiencies:"));
01238 flagprintefficiency = false;
01239 }
01240
01241 double fscale=2.;
01242 if(has_converged && fMCMCEfficiencyMin/efficiency[ipc] > 2.)
01243 fscale = 4.;
01244 fMCMCTrialFunctionScaleFactor[ipc] /= fscale;
01245
01246 BCLog::Out(BCLog::detail, BCLog::detail,
01247 Form(" Efficiency of parameter %i dropped below %.2lf%% (eps = %.2lf%%) in chain %i. Set scale to %.4g",
01248 iparameter, 100. * fMCMCEfficiencyMin, 100. * efficiency[ipc], ichains, fMCMCTrialFunctionScaleFactor[ipc]));
01249 }
01250
01251
01252 else if (efficiency[ipc] > fMCMCEfficiencyMax && (fMCMCTrialFunctionScaleFactor[ipc] < 1. || (fMCMCFlagPCA && fMCMCTrialFunctionScaleFactor[ipc] < 10.)))
01253 {
01254 if (flagprintefficiency)
01255 {
01256 BCLog::Out(BCLog::detail, BCLog::detail,
01257 Form(" * Efficiency status: Efficiencies not within pre-defined ranges."));
01258 BCLog::Out(BCLog::detail, BCLog::detail,
01259 Form(" - Efficiencies:"));
01260 flagprintefficiency = false;
01261 }
01262
01263 fMCMCTrialFunctionScaleFactor[ipc] *= 2.;
01264
01265 BCLog::Out(BCLog::detail, BCLog::detail,
01266 Form(" Efficiency of parameter %i above %.2lf%% (eps = %.2lf%%) in chain %i. Set scale to %.4g",
01267 iparameter, 100.0 * fMCMCEfficiencyMax, 100.0 * efficiency[ipc], ichains, fMCMCTrialFunctionScaleFactor[ipc]));
01268 }
01269
01270
01271 if ((efficiency[ipc] < fMCMCEfficiencyMin && fMCMCTrialFunctionScaleFactor[ipc] > .01)
01272 || (efficiency[ipc] > fMCMCEfficiencyMax && fMCMCTrialFunctionScaleFactor[ipc] < 1.))
01273 flagefficiency = false;
01274
01275
01276 counterupdate = 0;
01277 fMCMCNTrialsTrue[ipc] = 0;
01278 fMCMCNTrialsFalse[ipc] = 0;
01279 }
01280
01281
01282 fMCMCMean[ichains] = 0;
01283 fMCMCVariance[ichains] = 0;
01284 }
01285
01286
01287 if (flagefficiency)
01288 BCLog::Out(BCLog::detail, BCLog::detail,
01289 Form(" * Efficiency status: Efficiencies within pre-defined ranges."));
01290
01291 }
01292
01293
01294 counter++;
01295 counterupdate++;
01296
01297
01298
01299
01300
01301 }
01302
01303
01304
01305
01306
01307
01308 if (fMCMCNIterationsConvergenceGlobal > 0)
01309 fMCMCFlagConvergenceGlobal = true;
01310 else
01311 fMCMCFlagConvergenceGlobal = false;
01312
01313
01314 if (fMCMCFlagConvergenceGlobal && fMCMCNChains > 1 && !flagefficiency)
01315 BCLog::Out(BCLog::summary, BCLog::summary,
01316 Form(" --> Set of %i Markov chains converged within %i iterations but could not adjust scales.", fMCMCNChains, fMCMCNIterationsConvergenceGlobal));
01317
01318 else if (fMCMCFlagConvergenceGlobal && fMCMCNChains > 1 && flagefficiency)
01319 BCLog::Out(BCLog::summary, BCLog::summary,
01320 Form(" --> Set of %i Markov chains converged within %i iterations and could adjust scales.", fMCMCNChains, fMCMCNIterationsConvergenceGlobal));
01321
01322 else if (!fMCMCFlagConvergenceGlobal && (fMCMCNChains > 1) && flagefficiency)
01323 BCLog::Out(BCLog::summary, BCLog::summary,
01324 Form(" --> Set of %i Markov chains did not converge within %i iterations.", fMCMCNChains, fMCMCNIterationsMax));
01325
01326 else if (!fMCMCFlagConvergenceGlobal && (fMCMCNChains > 1) && !flagefficiency)
01327 BCLog::Out(BCLog::summary, BCLog::summary,
01328 Form(" --> Set of %i Markov chains did not converge within %i iterations and could not adjust scales.", fMCMCNChains, fMCMCNIterationsMax));
01329
01330 else if(fMCMCNChains == 1)
01331 BCLog::Out(BCLog::summary, BCLog::summary,
01332 " --> No convergence criterion for a single chain defined.");
01333
01334 else
01335 BCLog::Out(BCLog::summary, BCLog::summary,
01336 " --> Only one Markov chain. No global convergence criterion defined.");
01337
01338 BCLog::Out(BCLog::summary, BCLog::summary,
01339 Form(" --> Markov chains ran for %i iterations.", counter));
01340
01341
01342
01343 std::vector <double> efficiencies;
01344
01345 for (int i = 0; i < fMCMCNParameters; ++i)
01346 efficiencies.push_back(0.);
01347
01348 BCLog::Out(BCLog::detail, BCLog::detail, " --> Average efficiencies:");
01349 for (int i = 0; i < fMCMCNParameters; ++i)
01350 {
01351 for (int j = 0; j < fMCMCNChains; ++j)
01352 efficiencies[i] += efficiency[j * fMCMCNParameters + i] / double(fMCMCNChains);
01353
01354 BCLog::Out(BCLog::detail, BCLog::detail,
01355 Form( TString::Format(" --> parameter %%%di : %%.02f%%%%",ndigits), i, 100. * efficiencies[i]));
01356 }
01357
01358
01359
01360 std::vector <double> scalefactors;
01361
01362 for (int i = 0; i < fMCMCNParameters; ++i)
01363 scalefactors.push_back(0.0);
01364
01365 BCLog::Out(BCLog::detail, BCLog::detail, " --> Average scale factors:");
01366 for (int i = 0; i < fMCMCNParameters; ++i)
01367 {
01368 for (int j = 0; j < fMCMCNChains; ++j)
01369 scalefactors[i] += fMCMCTrialFunctionScaleFactor[j * fMCMCNParameters + i] / double(fMCMCNChains);
01370
01371 BCLog::Out(BCLog::detail, BCLog::detail,
01372 Form( TString::Format(" --> parameter %%%di : %%.02f%%%%",ndigits), i, 100. * scalefactors[i]));
01373 }
01374
01375
01376
01377 if (fMCMCFlagPCA)
01378 {
01379
01380
01381 fMCMCPCA -> MakePrincipals();
01382
01383
01384 for (int i = 0; i < fMCMCNIterationsPCA; ++i)
01385 {
01386 double * data = new double[fMCMCNParameters];
01387 double * p = new double[fMCMCNParameters];
01388
01389 for (int j = 0; j < fMCMCNParameters; ++j)
01390 data[j] = dataall[i * fMCMCNParameters + j];
01391
01392 fMCMCPCA -> X2P(data, p);
01393
01394 for (int j = 0; j < fMCMCNParameters; ++j)
01395 {
01396 sum[j] += p[j];
01397 sum2[j] += p[j] * p[j];
01398 }
01399
01400 delete [] data;
01401 delete [] p;
01402 }
01403
01404 delete [] dataall;
01405
01406 fMCMCPCAMean.clear();
01407 fMCMCPCAVariance.clear();
01408
01409
01410 for (int j = 0; j < fMCMCNParameters; ++j)
01411 {
01412 fMCMCPCAMean.push_back(sum[j] / double(fMCMCNIterationsPCA) / double(fMCMCNChains));
01413 fMCMCPCAVariance.push_back(sum2[j] / double(fMCMCNIterationsPCA) / double(fMCMCNChains) - fMCMCPCAMean[j] * fMCMCPCAMean[j]);
01414 }
01415
01416
01417 int neigenvalues = fMCMCPCA -> GetEigenValues() -> GetNoElements();
01418
01419 const double * eigenv = fMCMCPCA -> GetEigenValues() -> GetMatrixArray();
01420
01421 bool flageigenvalues = true;
01422
01423 for (int i = 0; i < neigenvalues; ++i)
01424 if (isnan(eigenv[i]))
01425 flageigenvalues = false;
01426
01427
01428 if (flageigenvalues)
01429 BCLog::Out(BCLog::detail, BCLog::detail, " --> PCA : All eigenvalues ok.");
01430 else
01431 {
01432 BCLog::Out(BCLog::detail, BCLog::detail, " --> PCA : Not all eigenvalues ok. Don't use PCA.");
01433 fMCMCFlagPCA = false;
01434 }
01435
01436
01437 for (int i = 0; i < fMCMCNParameters; ++i)
01438 for (int j = 0; j < fMCMCNChains; ++j)
01439 fMCMCTrialFunctionScaleFactor[j * fMCMCNParameters + i] = 1.0;
01440
01441 if (DEBUG)
01442 {
01443 fMCMCPCA -> Print("MSEV");
01444
01445 for (int j = 0; j < fMCMCNParameters; ++j)
01446 std::cout << fMCMCPCAMean.at(j) << " " << sqrt(fMCMCPCAVariance.at(j)) << std::endl;
01447 }
01448
01449 }
01450
01451
01452
01453
01454
01455
01456 fMCMCFlagWriteChainToFile = tempflag_writetofile;
01457
01458
01459 fMCMCFlagPreRun = true;
01460
01461 return 1;
01462
01463 }
01464
01465
01466
01467 int BCEngineMCMC::MCMCMetropolis()
01468 {
01469
01470 if (!fMCMCFlagPreRun)
01471 this -> MCMCMetropolisPreRun();
01472
01473
01474 BCLog::Out(BCLog::summary, BCLog::summary, "Run Metropolis MCMC...");
01475
01476 if (fMCMCFlagPCA)
01477 BCLog::Out(BCLog::detail, BCLog::detail, " --> PCA switched on");
01478
01479
01480 this -> MCMCResetRunStatistics();
01481
01482
01483 BCLog::Out(BCLog::summary, BCLog::summary,
01484 Form(" --> Perform MCMC run with %i chains, each with %i iterations.", fMCMCNChains, fMCMCNIterationsRun));
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496 int nwrite = fMCMCNIterationsRun/10;
01497 if(nwrite < 100)
01498 nwrite=100;
01499 else if(nwrite < 500)
01500 nwrite=1000;
01501 else if(nwrite < 10000)
01502 nwrite=1000;
01503 else
01504 nwrite=10000;
01505
01506
01507 for (int iiterations = 0; iiterations < fMCMCNIterationsRun; ++iiterations)
01508 {
01509 if ( (iiterations+1)%nwrite == 0 )
01510 BCLog::Out(BCLog::detail, BCLog::detail,
01511 Form(" --> iteration number %i (%.2f%%)", iiterations+1, (double)(iiterations+1)/(double)fMCMCNIterationsRun*100.));
01512
01513
01514 if (fMCMCFlagOrderParameters)
01515 {
01516
01517 for (int iparameters = 0; iparameters < fMCMCNParameters; ++iparameters)
01518 {
01519
01520 for (int ichains = 0; ichains < fMCMCNChains; ++ichains)
01521 this -> MCMCGetNewPointMetropolis(ichains, iparameters, fMCMCFlagPCA);
01522
01523
01524 this -> MCMCUpdateStatistics();
01525
01526
01527 this -> MCMCIterationInterface();
01528 }
01529 }
01530
01531 else
01532 {
01533
01534 for (int ichains = 0; ichains < fMCMCNChains; ++ichains)
01535
01536 this -> MCMCGetNewPointMetropolis(ichains, false);
01537
01538
01539 this -> MCMCUpdateStatistics();
01540
01541
01542 this -> MCMCIterationInterface();
01543 }
01544 }
01545
01546
01547 BCLog::Out(BCLog::summary, BCLog::summary,
01548 Form(" --> Markov chains ran for %i iterations.", fMCMCNIterationsRun));
01549
01550
01551
01552
01553 double probmax = fMCMCMaximumLogProb.at(0);
01554 int probmaxindex = 0;
01555
01556
01557 for (int i = 1; i < fMCMCNChains; ++i)
01558 if (fMCMCMaximumLogProb.at(i) > probmax)
01559 {
01560 probmax = fMCMCMaximumLogProb.at(i);
01561 probmaxindex = i;
01562 }
01563
01564 BCLog::Out(BCLog::detail, BCLog::detail, " --> Global mode from MCMC:");
01565 int ndigits = (int) log10(fMCMCNParameters);
01566 for (int i = 0; i < fMCMCNParameters; ++i)
01567 BCLog::Out(BCLog::detail, BCLog::detail,
01568 Form( TString::Format(" --> parameter %%%di: %%.4g", ndigits+1),
01569 i, fMCMCMaximumPoints[probmaxindex * fMCMCNParameters + i]));
01570
01571
01572 fMCMCFlagPreRun = false;
01573
01574 return 1;
01575 }
01576
01577
01578
01579 int BCEngineMCMC::MCMCMetropolisHastings()
01580 {
01581 BCLog::Out(BCLog::summary, BCLog::summary, "Run Metropolis-Hastings MCMC.");
01582
01583
01584 this -> MCMCInitializeMarkovChains();
01585
01586
01587 BCLog::Out(BCLog::detail, BCLog::detail, Form(" --> Start burn-in run with %i iterations.", fMCMCNIterationsBurnIn));
01588 for (int i = 0; i < fMCMCNIterationsBurnIn; ++i)
01589 for (int j = 0; j < fMCMCNChains; ++j)
01590 this -> MCMCGetNewPointMetropolisHastings(j);
01591
01592
01593 this -> MCMCResetRunStatistics();
01594
01595
01596 BCLog::Out(BCLog::detail, BCLog::detail, Form(" --> Perform MCMC run with %i iterations.", fMCMCNIterationsMax));
01597 for (int i = 0; i < fMCMCNIterationsMax; ++i)
01598 {
01599 for (int j = 0; j < fMCMCNChains; ++j)
01600
01601 this -> MCMCGetNewPointMetropolisHastings(j);
01602
01603
01604 this -> MCMCUpdateStatistics();
01605
01606
01607 this -> MCMCIterationInterface();
01608 }
01609
01610 if (fMCMCNIterationsConvergenceGlobal > 0)
01611 BCLog::Out(BCLog::detail, BCLog::detail,
01612 Form(" --> Set of %i Markov chains converged within %i iterations.", fMCMCNChains, fMCMCNIterationsConvergenceGlobal));
01613 else
01614 BCLog::Out(BCLog::detail, BCLog::detail,
01615 Form(" --> Set of %i Markov chains did not converge within %i iterations.", fMCMCNChains, fMCMCNIterationsMax));
01616
01617
01618 if (DEBUG)
01619 {
01620 for (int i = 0; i < fMCMCNChains; ++i)
01621 {
01622 std::cout << i << " " << fMCMCMaximumLogProb[i] << std::endl;
01623 for (int j = 0; j < fMCMCNParameters; ++j)
01624 std::cout << fMCMCMaximumPoints[i * fMCMCNParameters + j] << " ";
01625 std::cout << std::endl;
01626 }
01627 }
01628
01629 return 1;
01630 }
01631
01632
01633
01634 void BCEngineMCMC::MCMCResetRunStatistics()
01635 {
01636
01637
01638
01639 for (int j = 0; j < fMCMCNChains; ++j)
01640 {
01641 fMCMCNIterations[j] = 0;
01642 fMCMCNTrialsTrue[j] = 0;
01643 fMCMCNTrialsFalse[j] = 0;
01644 fMCMCMean[j] = 0;
01645 fMCMCVariance[j] = 0;
01646
01647 for (int k = 0; k < fMCMCNParameters; ++k)
01648 {
01649 fMCMCNTrialsTrue[j * fMCMCNParameters + k] = 0;
01650 fMCMCNTrialsFalse[j * fMCMCNParameters + k] = 0;
01651 }
01652 }
01653
01654
01655 for (int i = 0; i < int(fMCMCH1Marginalized.size()); ++i)
01656 fMCMCH1Marginalized[i] -> Reset();
01657
01658 for (int i = 0; i < int(fMCMCH2Marginalized.size()); ++i)
01659 fMCMCH2Marginalized[i] -> Reset();
01660
01661
01662
01663
01664
01665
01666
01667 fMCMCRValue = 100;
01668 }
01669
01670
01671
01672 int BCEngineMCMC::MCMCAddParameter(double min, double max)
01673 {
01674
01675 fMCMCBoundaryMin.push_back(min);
01676 fMCMCBoundaryMax.push_back(max);
01677
01678
01679 fMCMCNParameters++;
01680
01681
01682 return fMCMCNParameters;
01683 }
01684
01685
01686
01687 void BCEngineMCMC::MCMCInitializeMarkovChains()
01688 {
01689
01690 std::vector <double> x0;
01691
01692 for (int j = 0; j < fMCMCNChains; ++j)
01693 {
01694 x0.clear();
01695 for (int i = 0; i < fMCMCNParameters; ++i)
01696 x0.push_back(fMCMCx[j * fMCMCNParameters + i]);
01697 fMCMCLogProbx[j] = this -> LogEval(x0);
01698 }
01699
01700 x0.clear();
01701 }
01702
01703
01704
01705 int BCEngineMCMC::MCMCInitialize()
01706 {
01707
01708 fMCMCNIterations.clear();
01709 fMCMCNIterationsConvergenceLocal.clear();
01710 fMCMCNTrialsTrue.clear();
01711 fMCMCNTrialsFalse.clear();
01712 fMCMCTrialFunctionScaleFactor.clear();
01713 fMCMCMean.clear();
01714 fMCMCVariance.clear();
01715 fMCMCMeanx.clear();
01716 fMCMCVariancex.clear();
01717 fMCMCx.clear();
01718 fMCMCLogProbx.clear();
01719 fMCMCMaximumPoints.clear();
01720 fMCMCMaximumLogProb.clear();
01721
01722 fMCMCNumericalPrecisionModeValues.clear();
01723 fMCMCNIterationsConvergenceGlobal = -1;
01724 fMCMCFlagConvergenceGlobal = false;
01725 fMCMCRValueParameters.clear();
01726
01727 for (int i = 0; i < int(fMCMCH1Marginalized.size()); ++i)
01728 if (fMCMCH1Marginalized[i])
01729 delete fMCMCH1Marginalized[i];
01730
01731 for (int i = 0; i < int(fMCMCH2Marginalized.size()); ++i)
01732 if (fMCMCH2Marginalized[i])
01733 delete fMCMCH2Marginalized[i];
01734
01735
01736 fMCMCH1Marginalized.clear();
01737 fMCMCH2Marginalized.clear();
01738
01739
01740
01741
01742
01743
01744
01745
01746 fMCMCNIterationsConvergenceLocal.assign(fMCMCNChains, -1);
01747 fMCMCNIterations.assign(fMCMCNChains, 0);
01748 fMCMCMean.assign(fMCMCNChains, 0);
01749 fMCMCVariance.assign(fMCMCNChains, 0);
01750 fMCMCLogProbx.assign(fMCMCNChains, -1.0);
01751 fMCMCMaximumLogProb.assign(fMCMCNChains, -1.0);
01752
01753 fMCMCNumericalPrecisionModeValues.assign(fMCMCNParameters, 0.0);
01754
01755 fMCMCNTrialsTrue.assign(fMCMCNChains * fMCMCNParameters, 0);
01756 fMCMCNTrialsFalse.assign(fMCMCNChains * fMCMCNParameters, 0);
01757 fMCMCMaximumPoints.assign(fMCMCNChains * fMCMCNParameters, 0.);
01758 fMCMCMeanx.assign(fMCMCNChains * fMCMCNParameters, 0);
01759 fMCMCVariancex.assign(fMCMCNChains * fMCMCNParameters, 0);
01760
01761 fMCMCRValueParameters.assign(fMCMCNParameters, 0.);
01762
01763 if (fMCMCTrialFunctionScaleFactorStart.size() == 0)
01764 fMCMCTrialFunctionScaleFactor.assign(fMCMCNChains * fMCMCNParameters, 1.0);
01765 else
01766 for (int i = 0; i < fMCMCNChains; ++i)
01767 for (int j = 0; j < fMCMCNParameters; ++j)
01768 fMCMCTrialFunctionScaleFactor.push_back(fMCMCTrialFunctionScaleFactorStart.at(j));
01769
01770
01771 for (int j = 0; j < fMCMCNChains; ++j)
01772 for (int i = 0; i < fMCMCNParameters; ++i)
01773 switch(fMCMCFlagInitialPosition)
01774 {
01775
01776 case 0 :
01777 fMCMCx.push_back(fMCMCBoundaryMin[i] + .5 * (fMCMCBoundaryMax[i] - fMCMCBoundaryMin[i]));
01778 break;
01779
01780 case 1 :
01781 fMCMCx.push_back(fMCMCBoundaryMin[i] + fMCMCRandom -> Rndm() * (fMCMCBoundaryMax[i] - fMCMCBoundaryMin[i]));
01782 break;
01783
01784 case 2 :
01785 if (int(fMCMCInitialPosition.size()) == fMCMCNParameters * fMCMCNChains)
01786 fMCMCx.push_back(fMCMCInitialPosition[j * fMCMCNParameters + i]);
01787 else
01788 fMCMCx.push_back(fMCMCBoundaryMin[i] + .5 * (fMCMCBoundaryMax[i] - fMCMCBoundaryMin[i]));
01789 break;
01790
01791 default:
01792 fMCMCx.push_back(fMCMCBoundaryMin[i] + 0.5 * (fMCMCBoundaryMax[i] - fMCMCBoundaryMin[i]));
01793 break;
01794 }
01795
01796
01797 fMCMCxLocal.clear();
01798 for (int i = 0; i < fMCMCNParameters; ++i)
01799 fMCMCxLocal.push_back(fMCMCx[i]);
01800
01801
01802 for(int i = 0; i < fMCMCNParameters; ++i)
01803 {
01804 double hmin1 = fMCMCBoundaryMin.at(i);
01805 double hmax1 = fMCMCBoundaryMax.at(i);
01806
01807 TH1D * h1 = new TH1D(TString::Format("h1_%d_parameter_%i", BCLog::GetHIndex() ,i), "", fMCMCH1NBins[i], hmin1, hmax1);
01808 fMCMCH1Marginalized.push_back(h1);
01809 }
01810
01811 for(int i = 0; i < fMCMCNParameters; ++i)
01812 for (int k = 0; k < i; ++k)
01813 {
01814 double hmin1 = fMCMCBoundaryMin.at(k);
01815 double hmax1 = fMCMCBoundaryMax.at(k);
01816 double hmin2 = fMCMCBoundaryMin.at(i);
01817 double hmax2 = fMCMCBoundaryMax.at(i);
01818
01819 TH2D * h2 = new TH2D(Form("h2_%d_parameters_%i_vs_%i", BCLog::GetHIndex(), i, k), "",
01820 fMCMCH1NBins[i], hmin1, hmax1,
01821 fMCMCH1NBins[k], hmin2, hmax2);
01822 fMCMCH2Marginalized.push_back(h2);
01823 }
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837 return 1;
01838 }
01839
01840
01841
01842 int BCEngineMCMC::SetMarginalized(int index, TH1D * h)
01843 {
01844 if((int)fMCMCH1Marginalized.size()<=index)
01845 return 0;
01846
01847 if(h==0)
01848 return 0;
01849
01850 if((int)fMCMCH1Marginalized.size()==index)
01851 fMCMCH1Marginalized.push_back(h);
01852 else
01853 fMCMCH1Marginalized[index]=h;
01854
01855 return index;
01856 }
01857
01858
01859
01860 int BCEngineMCMC::SetMarginalized(int index1, int index2, TH2D * h)
01861 {
01862 int counter = 0;
01863 int index = 0;
01864
01865
01866 for(int i = 0; i < fMCMCNParameters; i++)
01867 for (int j = 0; j < i; ++j)
01868 {
01869 if(j == index1 && i == index2)
01870 index = counter;
01871 counter++;
01872 }
01873
01874 if((int)fMCMCH2Marginalized.size()<=index)
01875 return 0;
01876
01877 if(h==0)
01878 return 0;
01879
01880 if((int)fMCMCH2Marginalized.size()==index)
01881 fMCMCH2Marginalized.push_back(h);
01882 else
01883 fMCMCH2Marginalized[index]=h;
01884
01885 return index;
01886 }
01887
01888
01889
01890 void BCEngineMCMC::MCMCSetValuesDefault()
01891 {
01892 this -> MCMCSetValuesDetail();
01893 }
01894
01895
01896
01897 void BCEngineMCMC::MCMCSetValuesQuick()
01898 {
01899 fMCMCNChains = 1;
01900 fMCMCNIterationsMax = 1000;
01901 fMCMCNIterationsRun = 10000;
01902 fMCMCNIterationsBurnIn = 0;
01903 fMCMCNIterationsPCA = 0;
01904 fMCMCNIterationsPreRunMin = 0;
01905 fMCMCFlagIterationsAuto = false;
01906 fMCMCTrialFunctionScale = 1.0;
01907 fMCMCFlagInitialPosition = 1;
01908 fMCMCRValueCriterion = 0.1;
01909 fMCMCRValueParametersCriterion = 0.1;
01910 fMCMCNIterationsConvergenceGlobal = -1;
01911 fMCMCFlagConvergenceGlobal = false;
01912 fMCMCRValue = 100;
01913 fMCMCFlagPCA = false;
01914 fMCMCFlagPCATruncate = false;
01915 fMCMCPCA = 0;
01916 fMCMCPCAMinimumRatio = 1e-7;
01917 fMCMCNIterationsUpdate = 1000;
01918 fMCMCFlagOrderParameters = true;
01919 }
01920
01921
01922
01923 void BCEngineMCMC::MCMCSetValuesDetail()
01924 {
01925 fMCMCNChains = 5;
01926 fMCMCNIterationsMax = 1000000;
01927 fMCMCNIterationsRun = 100000;
01928 fMCMCNIterationsBurnIn = 0;
01929 fMCMCNIterationsPCA = 10000;
01930 fMCMCNIterationsPreRunMin = 500;
01931 fMCMCFlagIterationsAuto = false;
01932 fMCMCTrialFunctionScale = 1.0;
01933 fMCMCFlagInitialPosition = 1;
01934 fMCMCRValueCriterion = 0.1;
01935 fMCMCRValueParametersCriterion = 0.1;
01936 fMCMCNIterationsConvergenceGlobal = -1;
01937 fMCMCFlagConvergenceGlobal = false;
01938 fMCMCRValue = 100;
01939 fMCMCFlagPCA = false;
01940 fMCMCFlagPCATruncate = false;
01941 fMCMCPCA = 0;
01942 fMCMCPCAMinimumRatio = 1e-7;
01943 fMCMCNIterationsUpdate = 1000;
01944 fMCMCFlagOrderParameters = true;
01945 }
01946
01947
01948