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