BCModelManager.cxx
1 /*
2  * Copyright (C) 2007-2018, the BAT core developer team
3  * All rights reserved.
4  *
5  * For the licensing terms see doc/COPYING.
6  * For documentation see http://mpp.mpg.de/bat
7  */
8 
9 // ---------------------------------------------------------
10 
11 #include "BCModelManager.h"
12 
13 #include "BCDataPoint.h"
14 #include "BCLog.h"
15 
16 #include <TString.h>
17 
18 // ---------------------------------------------------------
20  : fDataSet(NULL)
21 {
22 }
23 
24 // ---------------------------------------------------------
26  : fModels(other.fModels),
27  fAPrioriProbability(other.fAPrioriProbability),
28  fAPosterioriProbability(other.fAPosterioriProbability),
29  fDataSet(other.fDataSet)
30 {
31 }
32 
33 // ---------------------------------------------------------
35 {
36 }
37 
38 // ---------------------------------------------------------
40 {
41  swap(*this, rhs);
42  return *this;
43 }
44 
45 // ---------------------------------------------------------
47 {
48  std::swap(A.fModels, B.fModels);
49  std::swap(A.fAPrioriProbability, B.fAPrioriProbability);
50  std::swap(A.fAPosterioriProbability, B.fAPosterioriProbability);
51  std::swap(A.fDataSet, B.fDataSet);
52 }
53 
54 // ---------------------------------------------------------
56 {
57  // set data set
58  fDataSet = dataset;
59 
60  // set data set of all models in the manager
61  for (unsigned int i = 0; i < GetNModels(); ++i)
62  GetModel(i)->SetDataSet(fDataSet);
63 }
64 
65 // ---------------------------------------------------------
66 void BCModelManager::AddModel(BCModel* model, double probability)
67 {
68  // set data set
69  if (fDataSet)
70  model->SetDataSet(fDataSet);
71 
72  // fill model into container
73  fModels.push_back(model);
74  // set probabilities
75  fAPrioriProbability.push_back(probability);
76  fAPosterioriProbability.push_back(-1);
77 }
78 
79 // ---------------------------------------------------------
81 {
82  for (unsigned i = 0; i < GetNModels(); ++i)
83  GetModel(i)->SetPrecision(precision);
84 }
85 
86 // ---------------------------------------------------------
87 void BCModelManager::SetNIterationsMax(int niterations)
88 {
89  for (unsigned i = 0; i < GetNModels(); ++i)
90  GetModel(i)->SetNIterationsMax(niterations);
91 }
92 
93 // ---------------------------------------------------------
94 void BCModelManager::SetNIterationsMin(int niterations)
95 {
96  for (unsigned i = 0; i < GetNModels(); ++i)
97  GetModel(i)->SetNIterationsMin(niterations);
98 }
99 
100 // ---------------------------------------------------------
102 {
103  for (unsigned i = 0; i < GetNModels(); ++i)
104  GetModel(i)->SetNIterationsPrecisionCheck(niterations);
105 }
106 
107 // ---------------------------------------------------------
109 {
110  for (unsigned i = 0; i < GetNModels(); ++i)
111  GetModel(i)->SetIntegrationMethod(method);
112 }
113 
114 // ---------------------------------------------------------
116 {
117  for (unsigned i = 0; i < GetNModels(); ++i)
119 }
120 
121 // ---------------------------------------------------------
123 {
124  for (unsigned i = 0; i < GetNModels(); ++i)
125  GetModel(i)->SetOptimizationMethod(method);
126 }
127 
128 // ---------------------------------------------------------
129 void BCModelManager::SetRelativePrecision(double relprecision)
130 {
131  for (unsigned i = 0; i < GetNModels(); ++i)
132  GetModel(i)->SetRelativePrecision(relprecision);
133 }
134 
135 // ---------------------------------------------------------
136 void BCModelManager::SetAbsolutePrecision(double absprecision)
137 {
138  for (unsigned i = 0; i < GetNModels(); ++i)
139  GetModel(i)->SetAbsolutePrecision(absprecision);
140 }
141 
142 // ---------------------------------------------------------
143 void BCModelManager::SetNbins(unsigned int n)
144 {
145  for (unsigned i = 0; i < GetNModels(); ++i)
146  GetModel(i)->SetNbins(n);
147 }
148 
149 // ---------------------------------------------------------
150 void BCModelManager::SetNChains(unsigned int n)
151 {
152  for (unsigned i = 0; i < GetNModels(); ++i)
153  GetModel(i)->SetNChains(n);
154 }
155 
156 // ---------------------------------------------------------
158 {
159  // initialize likelihood norm
160  double normalization = 0.0;
161 
162  BCLog::OutSummary("Running normalization of all models.");
163 
164  for (unsigned int i = 0; i < GetNModels(); ++i) {
165  fModels[i]->Integrate();
166 
167  // add to total normalization
168  normalization += fModels[i]->GetIntegral() * fAPrioriProbability[i];
169  }
170 
171  // set model a posteriori probabilities
172  for (unsigned int i = 0; i < GetNModels(); ++i)
173  fAPosterioriProbability[i] = (fModels[i]->GetIntegral() * fAPrioriProbability[i]) / normalization;
174 }
175 
176 // ---------------------------------------------------------
177 double BCModelManager::BayesFactor(unsigned imodel1, unsigned imodel2) const
178 {
179  if (imodel1 >= fModels.size() || imodel2 >= fModels.size())
180  return -1;
181 
182  // Bayes Factors are the likelihoods integrated over the parameters
183  // Is this equal to the posteriors?
184  // NOOOO
185  // But it is equal to normalization factors.
186 
187  // check model 1
188  const double norm1 = fModels[imodel1]->GetIntegral();
189  if (norm1 < 0.) {
190  BCLOG_ERROR(Form(" Model %s (index %d) not normalized. Cannot calculate Bayes factor.", fModels[imodel1]->GetName().data(), imodel1));
191  return -1.;
192  }
193 
194  // check model 2
195  const double norm2 = fModels[imodel2]->GetIntegral();
196  if (norm2 < 0) {
197  BCLOG_ERROR(Form(" Model %s (index %d) not normalized. Cannot calculate Bayes factor.", fModels[imodel2]->GetName().data(), imodel2));
198  return -1.;
199  }
200 
201  // denominator cannot be zero
202  if (norm2 < std::numeric_limits<double>::min() && norm1 >= std::numeric_limits<double>::min()) {
203  BCLOG_ERROR(Form(" Model %s (index %d) has ZERO probability. Bayes factor is infinite.", fModels[imodel2]->GetName().data(), imodel2));
204  return -1.;
205  }
206 
207  // denominator cannot be zero unless also numerator is zero
208  if (norm2 < std::numeric_limits<double>::min() && norm1 < std::numeric_limits<double>::min()) {
209  BCLOG_WARNING(Form("Models %s and %s have ZERO probability. Bayes factor is unknown. Returning 1.", fModels[imodel2]->GetName().data(), fModels[imodel1]->GetName().data()));
210  return 1.;
211  }
212 
213  // now calculate the factor
214  return norm1 / norm2;
215 }
216 
217 // ---------------------------------------------------------
219 {
220  for (unsigned i = 0; i < GetNModels(); ++i)
221  GetModel(i)->FindMode();
222 }
223 
224 // ---------------------------------------------------------
226 {
227  // marginalizes all models registered
228  for (unsigned i = 0; i < GetNModels(); ++i)
229  GetModel(i)->MarginalizeAll();
230 }
231 
232 // ---------------------------------------------------------
234 {
235  for (unsigned i = 0; i < GetNModels(); ++i)
236  GetModel(i)->WriteMarkovChain(flag);
237 }
238 
239 // ---------------------------------------------------------
241 {
242  for (unsigned i = 0; i < GetNModels(); ++i)
243  GetModel(i)->WriteMarkovChainRun(flag);
244 }
245 
246 // ---------------------------------------------------------
248 {
249  for (unsigned i = 0; i < GetNModels(); ++i)
251 }
252 
253 // ---------------------------------------------------------
254 void BCModelManager::WriteMarkovChain(const std::string& prefix, const std::string& option, bool flag_run, bool flag_prerun)
255 {
256  for (unsigned i = 0; i < GetNModels(); ++i)
257  GetModel(i)->WriteMarkovChain(prefix + GetModel(i)->GetSafeName() + ".root", option, flag_run, flag_prerun);
258 }
259 
260 // ---------------------------------------------------------
262 {
263  BCLog::OutSummary("");
264  BCLog::OutSummary("======================================");
265  BCLog::OutSummary(" Summary");
266  BCLog::OutSummary("======================================");
267  BCLog::OutSummary("");
268  BCLog::OutSummary(Form(" Number of models %lu: ", fModels.size()));
269  BCLog::OutSummary("");
270 
271  BCLog::OutSummary(" - Models:");
272  BCLog::OutSummary("");
273  for (unsigned i = 0; i < fModels.size(); ++i)
274  fModels[i]->PrintSummary();
275 
276  BCLog::OutSummary(" - Data:");
277  BCLog::OutSummary("");
278  BCLog::OutSummary(Form(" Number of entries: %u", fDataSet->GetNDataPoints()));
279  BCLog::OutSummary("");
280 
282 }
283 
284 // ---------------------------------------------------------
286 {
287  BCLog::OutSummary("======================================");
288  BCLog::OutSummary(" Model comparison:");
289  BCLog::OutSummary("");
290 
291  BCLog::OutSummary(" - A priori probabilities:");
292  for (unsigned i = 0; i < fModels.size(); ++i)
293  BCLog::OutSummary(Form(" (%u) p(%s) = %f", i, fModels[i]->GetName().data(), fAPrioriProbability[i]));
294 
295  BCLog::OutSummary(" - A posteriori probabilities:");
296  for (unsigned i = 0; i < fModels.size(); ++i)
297  BCLog::OutSummary(Form(" (%u) p(%s | data) = %f", i, fModels[i]->GetName().data(), fAPosterioriProbability[i]));
298 
299  // Bayes factors summary
300  BCLog::OutSummary(" - Bayes factors:");
301  for (unsigned i = 0; i < fModels.size(); ++i)
302  for (unsigned j = i + 1; j < fModels.size(); ++j)
303  BCLog::OutSummary(Form(" K := p(data | %s) / p(data | %s) = %f", fModels[i]->GetName().data(), fModels[j]->GetName().data(),
304  BayesFactor(i, j)));
305  BCLog::OutSummary("===========================================");
306 }
void WriteMarkovChainRun(bool flag)
Turn on/off writing of Markov chain to root file during run for all models.
void FindMode()
Does the mode finding.
void SetAbsolutePrecision(double absprecision)
Set absolute precision of the numerical integation.
void SetRelativePrecision(double relprecision)
void SetOptimizationMethod(BCIntegrate::BCOptimizationMethod method)
void SetMarginalizationMethod(BCIntegrate::BCMarginalizationMethod method)
Definition: BCIntegrate.h:465
void SetNIterationsMin(int niterations)
Definition: BCIntegrate.h:475
void AddModel(BCModel *model, double prior_probability=0.)
Adds a model to the container.
void SetNIterationsPrecisionCheck(int niterations)
Definition: BCIntegrate.h:485
A class representing a set of BCModels.
int MarginalizeAll()
Marginalize all probabilities wrt.
void SetDataSet(BCDataSet *dataset)
Sets the data set.
Definition: BCModel.h:145
void SetIntegrationMethod(BCIntegrate::BCIntegrationMethod method)
The base class for all user-defined models.
Definition: BCModel.h:39
std::vector< double > FindMode(std::vector< double > start=std::vector< double >())
Do the mode finding using a method set via SetOptimizationMethod.
void WriteMarkovChain(bool flag)
Turn on/off writing of Markov chain to root file.
BCModel * GetModel(unsigned index)
Returns the BCModel at a certain index of this BCModelManager.
void SetNChains(unsigned int n)
Sets the number of Markov chains.
A class representing a set of data points.
Definition: BCDataSet.h:39
unsigned GetNDataPoints() const
Definition: BCDataSet.h:75
void PrintSummary() const
Prints a summary to the logs.
void SetAbsolutePrecision(double absprecision)
Set absolute precision of the numerical integation.
Definition: BCIntegrate.h:496
void SetPrecision(BCEngineMCMC::Precision precision)
Set the precision for the MCMC run.
BCOptimizationMethod
An enumerator for the mode finding algorithm.
Definition: BCIntegrate.h:153
BCModelManager()
The default constructor.
void SetIntegrationMethod(BCIntegrate::BCIntegrationMethod method)
void SetNbins(unsigned int nbins)
Set the number of bins for the marginalized distribution of all parameters.
Definition: BCEngineMCMC.h:994
void SetMarginalizationMethod(BCIntegrate::BCMarginalizationMethod method)
void SetNChains(unsigned n)
Sets the number of Markov chains which are run in parallel.
Definition: BCEngineMCMC.h:775
void SetPrecision(BCEngineMCMC::Precision precision)
Set the precision for the MCMC run.
void Integrate()
Calculates the normalization of the likelihood for each model in the container.
void SetNIterationsPrecisionCheck(int niterations)
BCIntegrationMethod
An enumerator for integration algorithms.
Definition: BCIntegrate.h:164
void SetNbins(unsigned int n)
void WriteMarkovChainRun(bool flag)
Turn on/off writing of Markov chain to root file during run.
BCModelManager & operator=(BCModelManager modelmanager)
The defaut assignment operator.
friend void swap(BCModelManager &A, BCModelManager &B)
swap
void SetRelativePrecision(double relprecision)
Definition: BCIntegrate.h:491
unsigned int GetNModels()
void SetNIterationsMax(int niterations)
Sets the maximum number of iterations for the Monte Carlo integration for all BCModels in this BCMode...
void PrintModelComparisonSummary() const
Prints a summary of the model comparison to the log.
void WriteMarkovChainPreRun(bool flag)
Turn on/off writing of Markov chain to root file during prerun.
void WriteMarkovChainPreRun(bool flag)
Turn on/off writing of Markov chain to root file during prerun for all models.
void MarginalizeAll()
Marginalize all probabilities wrt.
void SetDataSet(BCDataSet *dataset)
Sets the data set common to all BCModels in this BCModelManager.
void WriteMarkovChain(bool flag)
Turn on/off writing of Markov chains to root files for all models.
virtual ~BCModelManager()
The default destructor.
void SetNIterationsMin(int niterations)
Sets the minimum number of iterations for the Monte Carlo integration for all BCModels in this BCMode...
Precision
An enumerator for the status of a test.
Definition: BCEngineMCMC.h:65
double BayesFactor(const unsigned int imodel1, const unsigned int imodel2) const
Calculate Bayes factor for two models.
void SetNIterationsMax(int niterations)
Definition: BCIntegrate.h:480
BCMarginalizationMethod
An enumerator for marginalization algorithms.
Definition: BCIntegrate.h:176
void SetOptimizationMethod(BCIntegrate::BCOptimizationMethod method)
Definition: BCIntegrate.h:456