11 #include "BCEngineMCMC.h"
17 #include "BCParameter.h"
102 case BCEngineMCMC::kLow:
114 case BCEngineMCMC::kMedium:
126 case BCEngineMCMC::kHigh:
138 case BCEngineMCMC::kVeryHigh:
168 for (
unsigned i = 0; i < fMCMCH2Marginalized.size(); ++i)
169 delete fMCMCH2Marginalized[i];
170 fMCMCH2Marginalized.clear();
182 fMCMCPointerToGetProposalPoint = other.fMCMCPointerToGetProposalPoint;
232 fMCMCThreadLocalStorage = other.fMCMCThreadLocalStorage;
241 for (
unsigned i = 0; i < other.fMCMCH2Marginalized.size(); ++i) {
242 if (other.fMCMCH2Marginalized.at(i))
243 fMCMCH2Marginalized.push_back(
new TH2D(*(other.fMCMCH2Marginalized.at(i))));
245 fMCMCH2Marginalized.push_back(0);
248 for (
unsigned i = 0; i < other.
fMCMCTrees.size(); ++i) {
293 BCLog::OutError(Form(
"BCEngineMCMC::MCMCGetH1Marginalized. Index %u out of range.", index));
299 BCLog::OutWarning(Form(
"BCEngineMCMC::MCMCGetH1Marginalized: marginal distribution not computed/stored for par. %d", index));
318 BCLog::OutError(Form(
"BCEngineMCMC::MCMCGetH2Marginalized. Index %u out of range.", i));
322 BCLog::OutError(Form(
"BCEngineMCMC::MCMCGetH2Marginalized. Index %u out of range.", j));
326 BCLog::OutError(Form(
"BCEngineMCMC::MCMCGetH2Marginalized. Called with identical indices %u.", i));
332 unsigned indexTemp = i;
342 TH2D * h = fMCMCH2Marginalized.at(
GetNParameters() * i - (i * i + 3 * i) / 2 + j - 1);
356 BCLog::OutError(
"BCIntegrate::GetBestFitParameterMarginalized : MCMC not yet run, returning center of the range.");
365 std::vector<double> x;
394 unsigned n = x0s.size();
396 for (
unsigned i = 0; i < n; ++i)
407 std::vector<double> y0s;
410 for (
unsigned i = 0; i < x0s.size(); ++i)
411 for (
unsigned j = 0; j < x0s.at(i).size(); ++j)
412 y0s.push_back((x0s.at(i)).at(j));
431 for (
unsigned i = 0; i < trees.size(); ++i)
449 if (
size_t(
fMCMCNChains) != fMCMCThreadLocalStorage.size())
450 BCLog::OutError(Form(
"#chains does not match #(thread local storages): %d vs %u",
451 fMCMCNChains,
unsigned(fMCMCThreadLocalStorage.size())));
456 fMCMCThreadLocalStorage[i].rng->SetSeed(
fRandom->GetSeed() + i);
457 fMCMCThreadLocalStorage[i].rng->Rndm();
469 fMCMCTrees.push_back(
new TTree(TString::Format(
"MarkovChainTree_%i", i),
"MarkovChainTree"));
477 fMCMCTrees[i]->Branch(TString::Format(
"Parameter%i", j),
479 TString::Format(
"parameter %i/D", j));
500 return fMCMCThreadLocalStorage[ichain].rng->BreitWigner(0.0,
508 std::vector<double> x;
540 std::vector<double> x;
620 x[ipar] += proposal *
fParameters[ipar]->GetRangeWidth();
651 double p1 =
LogEval(fMCMCThreadLocalStorage[chain].xLocal);
662 double r = log(fMCMCThreadLocalStorage[chain].rng->Rndm());
678 fMCMCx[index + i] = fMCMCThreadLocalStorage[chain].xLocal[i];
713 double p1 =
LogEval(fMCMCThreadLocalStorage[chain].xLocal);
725 double r = log(fMCMCThreadLocalStorage[chain].rng->Rndm());
742 fMCMCx[index + i] = fMCMCThreadLocalStorage[chain].xLocal[i];
781 for (
unsigned i = 0; i < nentries; ++i) {
816 unsigned counter = 0;
821 if (TH2D * h = fMCMCH2Marginalized[counter])
834 bool flag_convergence =
true;
841 for (
unsigned iparameters = 0; iparameters <
fParameters.
Size(); ++iparameters){
846 for (
unsigned ichains = 0; ichains <
fMCMCNChains; ++ichains) {
856 flag_convergence =
false;
865 flag_convergence =
false;
892 BCLog::OutSummary(
"Pre-run Metropolis MCMC...");
916 unsigned counterupdate = 1;
917 bool convergence =
false;
918 bool flagefficiency =
false;
933 for (
unsigned ichains = 0; ichains <
fMCMCNChains; ++ichains) {
935 for (
unsigned iparameter = 0; iparameter <
fParameters.
Size(); ++iparameter){
976 for (
unsigned iparameters = 0; iparameters <
fParameters.
Size(); ++iparameters)
982 unsigned chunk = 1; (void) chunk;
983 unsigned ichains; (void) ichains;
984 #pragma omp parallel for shared(chunk) private(ichains) schedule(static, chunk)
999 unsigned chunk = 1; (void) chunk;
1000 unsigned ichains; (void) ichains;
1001 #pragma omp parallel for shared(chunk) private(ichains) schedule(static, chunk)
1022 if (counterupdate > 1)
1037 bool rvalues_ok =
true;
1039 static bool has_converged =
false;
1057 if (convergence && fMCMCNChains > 1)
1059 else if (!convergence && fMCMCNChains > 1)
1061 BCLog::OutDetail(Form(
" * Convergence status: Set of %i Markov chains did not converge after %i iterations.", fMCMCNChains,
fMCMCCurrentIteration));
1063 BCLog::OutDetail(
" - R-Values:");
1064 for (
unsigned iparameter = 0; iparameter <
fParameters.
Size(); ++iparameter)
1069 BCLog::OutDetail(TString::Format(
" parameter %*i : %.06f",ndigits, iparameter,
fMCMCRValueParameters.at(iparameter)));
1073 BCLog::OutDetail(TString::Format(
" parameter %*i : %.06f <--",ndigits, iparameter,
fMCMCRValueParameters.at(iparameter)));
1075 BCLog::OutDetail(TString::Format(
" parameter %*i : MAX_DOUBLE <--",ndigits, iparameter));
1080 BCLog::OutDetail(Form(
" log-likelihood : %.06f",
fMCMCRValue));
1083 if (
fMCMCRValue != std::numeric_limits<double>::max() )
1084 BCLog::OutDetail(Form(
" log-likelihood : %.06f <--",
fMCMCRValue));
1086 BCLog::OutDetail(
" log-likelihood : MAX_DOUBLE <--");
1094 has_converged =
true;
1101 flagefficiency =
true;
1103 bool flagprintefficiency =
true;
1106 for (
unsigned ichains = 0; ichains <
fMCMCNChains; ++ichains)
1109 for (
unsigned iparameter = 0; iparameter <
fParameters.
Size(); ++iparameter)
1123 if (flagprintefficiency)
1125 BCLog::OutDetail(Form(
" * Efficiency status: Efficiencies not within pre-defined range."));
1126 BCLog::OutDetail(Form(
" - Efficiencies:"));
1127 flagprintefficiency =
false;
1135 BCLog::OutDetail(Form(
" Efficiency of parameter %i dropped below %.2f%% (eps = %.2f%%) in chain %i. Set scale to %.4g",
1142 if (flagprintefficiency)
1144 BCLog::OutDetail(Form(
" * Efficiency status: Efficiencies not within pre-defined ranges."));
1145 BCLog::OutDetail(Form(
" - Efficiencies:"));
1146 flagprintefficiency =
false;
1151 BCLog::OutDetail(Form(
" Efficiency of parameter %i above %.2f%% (eps = %.2f%%) in chain %i. Set scale to %.4g",
1158 flagefficiency =
false;
1164 BCLog::OutDetail(Form(
" * Efficiency status: Efficiencies within pre-defined ranges."));
1174 for (
unsigned ichains = 0; ichains <
fMCMCNChains; ++ichains) {
1176 for (
unsigned iparameter = 0; iparameter <
fParameters.
Size(); ++iparameter){
1208 BCLog::OutWarning(
" Convergence never checked !");
1209 BCLog::OutWarning(
" Increase maximum number of iterations in the pre-run /MCMCSetNIterationsMax()/");
1210 BCLog::OutWarning(
" or decrease maximum number of iterations for update /MCMCSetNIterationsUpdateMax()/");
1225 BCLog::OutSummary(Form(
" --> Set of %i Markov chains converged within %i iterations but could not adjust scales.", fMCMCNChains,
fMCMCNIterationsConvergenceGlobal));
1228 BCLog::OutSummary(Form(
" --> Set of %i Markov chains converged within %i iterations and all scales are adjusted.", fMCMCNChains,
fMCMCNIterationsConvergenceGlobal));
1231 BCLog::OutSummary(Form(
" --> Set of %i Markov chains did not converge within %i iterations.", fMCMCNChains,
fMCMCNIterationsMax));
1234 BCLog::OutSummary(Form(
" --> Set of %i Markov chains did not converge within %i iterations and could not adjust scales.", fMCMCNChains,
fMCMCNIterationsMax));
1236 else if(fMCMCNChains == 1)
1237 BCLog::OutSummary(
" --> No convergence criterion for a single chain defined.");
1240 BCLog::OutSummary(
" --> Only one Markov chain. No global convergence criterion defined.");
1246 std::vector<double> efficiencies;
1249 efficiencies.push_back(0.);
1251 BCLog::OutDetail(
" --> Average efficiencies:");
1260 BCLog::OutDetail(TString::Format(
" --> parameter %*d : %.02f%%",ndigits, i, 100. * efficiencies[i]));
1265 std::vector<double> scalefactors;
1268 scalefactors.push_back(0.0);
1270 BCLog::OutDetail(
" --> Average scale factors:");
1278 BCLog::OutDetail(TString::Format(
" --> parameter %*i : %.02f%%",ndigits, i, 100. * scalefactors[i]));
1299 BCLog::OutWarning(
"BCEngineMCMC::MCMCMetropolis. Number of free parameters <= 0. Do not run Metropolis.");
1307 BCLog::OutWarning(
"BCEngineMCMC::MCMCMetropolis. Not running prerun. This can cause trouble if the data have changed.");
1310 BCLog::OutSummary(
"Run Metropolis MCMC...");
1324 else if(nwrite < 500)
1326 else if(nwrite < 10000)
1341 for (
unsigned iparameters = 0; iparameters <
fParameters.
Size(); ++iparameters)
1348 unsigned chunk = 1; (void) chunk;
1349 unsigned ichains; (void) ichains;
1350 #pragma omp parallel for shared(chunk) private(ichains) schedule(static, chunk)
1351 for (
unsigned ichains = 0; ichains <
fMCMCNChains; ++ichains)
1384 unsigned chunk = 1; (void) chunk;
1385 unsigned ichains; (void) ichains;
1386 #pragma omp parallel for shared(chunk) private(ichains) schedule(static, chunk)
1387 for (
unsigned ichains = 0; ichains <
fMCMCNChains; ++ichains)
1418 BCLog::OutSummary(Form(
" --> Markov chains ran for %i iterations.",
fMCMCNIterationsRun));
1424 unsigned probmaxindex = 0;
1443 BCLog::OutDetail(
" --> Global mode from MCMC:");
1444 BCLog::OutDebug(Form(
" --> Posterior value: %g", probmax));
1483 for (
unsigned i = 0; i < fMCMCH2Marginalized.size(); ++i)
1484 if (fMCMCH2Marginalized[i])
1485 fMCMCH2Marginalized[i]->Reset();
1510 std::vector<double> x0;
1546 for (
unsigned i = 0; i < fMCMCH2Marginalized.size(); ++i)
1547 if (fMCMCH2Marginalized[i])
1548 delete fMCMCH2Marginalized[i];
1552 fMCMCH2Marginalized.clear();
1586 SyncThreadStorage();
1604 BCLog::OutError(
"BCEngine::MCMCInitialize : Length of vector containing initial positions does not have required length.");
1615 BCLog::OutError(
"BCEngine::MCMCInitialize : Initial position out of boundaries.");
1640 BCLog::OutWarning(
"BCEngineMCMC::MCMCInitialize. Inconsisten start value. Changed parameter value to fixed value.");
1667 if (p->FillHistograms() && ! p->Fixed()) {
1668 h1 =
new TH1D(TString::Format(
"h1_%d_parameter_%i",
BCLog::GetHIndex() ,i),
1671 h1->SetStats(kFALSE);
1688 if (p2->FillHistograms() && p1->FillHistograms() && ! p2->Fixed() && ! p1->Fixed()) {
1689 h2 =
new TH2D(Form(
"h2_%d_parameters_%i_vs_%i",
BCLog::GetHIndex(), i, j),
"",
1696 h2->SetStats(kFALSE);
1698 fMCMCH2Marginalized.push_back(h2);
1732 unsigned counter = 0;
1737 for (
unsigned j = 0; j < i; ++j)
1739 if(j == index1 && i == index2)
1744 if(fMCMCH2Marginalized.size()<=index)
1750 if(fMCMCH2Marginalized.size()==index)
1751 fMCMCH2Marginalized.push_back(h);
1753 fMCMCH2Marginalized[index]=h;
1759 BCEngineMCMC::MCMCThreadLocalStorage::MCMCThreadLocalStorage(
const unsigned & dim) :
1761 rng(new TRandom3(0))
1766 BCEngineMCMC::MCMCThreadLocalStorage::MCMCThreadLocalStorage(
const MCMCThreadLocalStorage & other) :
1767 xLocal(other.xLocal),
1768 rng(new TRandom3(*other.rng))
1773 BCEngineMCMC::MCMCThreadLocalStorage & BCEngineMCMC::MCMCThreadLocalStorage::operator = (
const MCMCThreadLocalStorage & other)
1775 xLocal = other.xLocal;
1782 rng =
new TRandom3(*other.rng);
1788 BCEngineMCMC::MCMCThreadLocalStorage::~MCMCThreadLocalStorage()
1793 void BCEngineMCMC::SyncThreadStorage()
1796 const int n = fMCMCThreadLocalStorage.size() -
fMCMCNChains;
1802 for (
int i = 0; i < -n; ++i){
1804 fMCMCThreadLocalStorage.push_back(MCMCThreadLocalStorage(
fParameters.
Size()));
1807 fMCMCThreadLocalStorage.back().rng->SetSeed(
fRandom->GetSeed() + fMCMCThreadLocalStorage.size());
1812 for (
int i = 0; i < n; ++i){
1813 fMCMCThreadLocalStorage.pop_back();
1818 for (
unsigned i = 0 ; i < fMCMCThreadLocalStorage.size(); ++i)
void MCMCSetValuesDetail()
std::vector< double > MCMCGetMaximumPoint(unsigned i) const
int SetMarginalized(unsigned index, TH1D *h)
virtual void ResetResults()
std::vector< double > fMCMCBestFitParameters
int fMCMCFlagInitialPosition
double GetLowerLimit() const
void MCMCSetRandomSeed(unsigned seed)
virtual void MCMCTrialFunction(unsigned ichain, std::vector< double > &x)
bool Add(BCParameter *par)
bool ValidIndex(unsigned index, const std::string caller="CheckIndex") const
BCH2D * MCMCGetH2Marginalized(unsigned i, unsigned j)
int MCMCMetropolisPreRun()
virtual void MCMCUserIterationInterface()
void MCMCResetRunStatistics()
const std::vector< double > & MCMCGetx() const
void MCMCInitializeMarkovChains()
std::vector< double > fMCMCx
std::vector< double > fMCMCInitialPosition
unsigned fMCMCNIterationsUpdate
std::vector< unsigned > fMCMCNIterations
unsigned int GetNFreeParameters()
void MCMCInChainCheckMaximum()
A class for handling 2D distributions.
std::vector< double > fMCMCprobMean
const std::vector< double > & GetBestFitParametersMarginalized() const
virtual double LogEval(const std::vector< double > ¶meters)
void MCMCSetInitialPositions(const std::vector< double > &x0s)
void MCMCInChainTestConvergenceAllChains()
std::vector< double > fMCMCprobVar
double fMCMCEfficiencyMax
void MCMCSetFlagFillHistograms(bool flag)
void MCMCSetFlagInitialPosition(int flag)
double fMCMCEfficiencyMin
unsigned fMCMCNIterationsPreRunMin
BCEngineMCMC & operator=(const BCEngineMCMC &engineMCMC)
int fMCMCNIterationsConvergenceGlobal
void SetHistogram(TH2D *hist)
void MCMCInitializeMarkovChainTrees()
void Copy(const BCEngineMCMC &enginemcmc)
void SetNbins(unsigned int nbins)
bool fMCMCFlagWritePreRunToFile
void SetHistogram(TH1D *hist)
unsigned fMCMCNIterationsRun
A class representing a parameter of a model.
virtual double MCMCTrialFunctionSingle(unsigned ichain, unsigned ipar)
std::vector< double > fMCMCxMean
unsigned fMCMCNIterationsUpdateMax
std::vector< double > fMarginalModes
bool fMCMCRValueUseStrict
An engine class for Markov Chain Monte Carlo.
bool MCMCGetProposalPointMetropolis(unsigned chain, std::vector< double > &x)
unsigned int GetNFixedParameters()
std::vector< double > fMCMCEfficiencies
void MCMCInChainFillHistograms()
unsigned int GetNParameters() const
const std::vector< double > & MCMCGetLogProbx() const
unsigned fMCMCNIterationsMax
bool fMCMCFlagConvergenceGlobal
virtual int AddParameter(const char *name, double min, double max, const char *latexname="")
const std::string & GetLatexName() const
std::vector< double > fMCMCxVar
BCH1D * MCMCGetH1Marginalized(unsigned i)
void MCMCSetNChains(unsigned n)
double GetUpperLimit() const
A class for handling 1D distributions.
virtual void MCMCCurrentPointInterface(std::vector< double > &, int, bool)
BCParameterSet fParameters
void MCMCSetValuesQuick()
bool fMCMCFlagWriteChainToFile
void MCMCSetMarkovChainTrees(const std::vector< TTree * > &trees)
double Rvalue(const std::vector< double > &chain_means, const std::vector< double > &chain_variances, const unsigned &chain_length, const bool &strict)
int fMCMCCurrentIteration
std::vector< double > fMCMCTrialFunctionScaleFactorStart
std::vector< int > fMCMCNTrialsTrue
std::vector< TTree * > fMCMCTrees
virtual void MCMCIterationInterface()
void MCMCSetValuesDefault()
std::vector< double > fMCMCprobMax
double fMCMCRValueParametersCriterion
std::vector< double > fMCMCxMax
const std::vector< double > & MCMCGetTrialFunctionScaleFactor() const
bool fMCMCFlagOrderParameters
std::vector< double > fMCMCRValueParameters
void MCMCInChainUpdateStatistics()
void MCMCInChainWriteChains()
double fMCMCRValueCriterion
std::vector< TH1D * > fMCMCH1Marginalized
std::vector< double > fMCMCTrialFunctionScaleFactor
void MCMCSetPrecision(BCEngineMCMC::Precision precision)
std::vector< double > fMCMCprob
bool MCMCGetNewPointMetropolis(unsigned chain=0)