MaCh3  2.4.2
Reference Guide
MCMCBase.cpp
Go to the documentation of this file.
1 #include "Fitters/MCMCBase.h"
2 
3 // *************************
4 // Initialise the Manager and make it an object of mcmc class
5 // Now we can dump Manager settings to the output file
7 // *************************
8  // Beginning step number
9  stepStart = 0;
10 
11  // Starting parameters should be thrown
12  out_of_bounds = false;
13  chainLength = Get<unsigned>(fitMan->raw()["General"]["MCMC"]["NSteps"], __FILE__, __LINE__);
14  if (chainLength < 10){
15  MACH3LOG_ERROR("MCMC chain length must be at least 10 steps, otherwise this will result in a floating point exception.");
16  throw MaCh3Exception(__FILE__, __LINE__);
17  }
18 
19  AnnealTemp = GetFromManager<double>(fitMan->raw()["General"]["MCMC"]["AnnealTemp"], -999);
20  if (AnnealTemp < 0)
21  anneal = false;
22  else
23  {
24  MACH3LOG_INFO("Enabling simulated annealing with T = {}", AnnealTemp);
25  anneal = true;
26  }
27 }
28 
29 
30 // *******************
31 // Run the Markov chain with all the systematic objects added
33 // *******************
34  // Save the settings into the output file
35  SaveSettings();
36 
37  // Prepare the output branches
38  PrepareOutput();
39 
40  // Remove obsolete memory and make other checks before fit starts
42 
43  // Print Progress before Propose Step
44  PrintProgress(false);
45 
46  // Only propose step if we are running fresh chain. If we are running from previous chain then it's not needed and we can use usual pipeline
47  if(stepStart == 0) {
48  // Reconfigure the samples, systematics and oscillation for first weight
49  // ProposeStep sets logLProp
50  ProposeStep();
51  // Set the current logL to the proposed logL for the 0th step
52  // Accept the first step to set logLCurr: this shouldn't affect the MCMC because we ignore the first N steps in burn-in
54  }
55 
56  // Begin MCMC
57  const auto StepEnd = stepStart + chainLength;
58  for (step = stepStart; step < StepEnd; ++step)
59  {
60  DoMCMCStep();
61  }
62  // Save all the MCMC output
63  SaveOutput();
64 
65  // Process MCMC
66  ProcessMCMC();
67 
68  // Save the adaptive MCMC
69  for (const auto &syst : systematics)
70  {
71  if (syst->GetDoAdaption())
72  {
73  auto adaptive_handler = syst->GetAdaptiveHandler();
74  adaptive_handler->SaveAdaptiveToFile(adaptive_handler->GetOutFileName(), syst->GetName(), true);
75  }
76  }
77 }
78 
79 // *******************
81 // *******************
85  DoStep();
88 }
89 
90 // *******************
92 // *******************
93  stepClock->Start();
94  out_of_bounds = false;
95 
96  // Print 10 steps in total
97  if ((step - stepStart) % (chainLength / 10) == 0)
98  {
99  PrintProgress();
100  }
101 }
102 
103 // *************************
105 // *************************
106  //KS: Some version of ROOT keep spamming about accessing already deleted object which is wrong and not helpful...
107  int originalErrorLevel = gErrorIgnoreLevel;
108  gErrorIgnoreLevel = kFatal;
109 
110  stepClock->Stop();
111  stepTime = stepClock->RealTime();
112 
113  // Write step to output tree
114  outTree->Fill();
115 
116  // Do Adaptive MCMC
117  AdaptiveStep();
118 
119  if (step % auto_save == 0){
120  outTree->AutoSave();
121  }
122  gErrorIgnoreLevel = originalErrorLevel;
123 }
124 
125 // *******************
126 // Print the fit output progress
127 void MCMCBase::PrintProgress(bool StepsPrint) {
128 // *******************
129  if(StepsPrint) MACH3LOG_INFO("Step:\t{}/{}, current: {:.2f}, proposed: {:.2f}", step - stepStart, chainLength, logLCurr, logLProp);
130  if(StepsPrint) MACH3LOG_INFO("Accepted/Total steps: {}/{} = {:.2f}", accCount, step - stepStart, static_cast<double>(accCount) / static_cast<double>(step - stepStart));
131 
132  for (size_t i = 0; i < samples.size(); ++i) {
133  samples[i]->PrintRates();
134  }
135 
136  for (ParameterHandlerBase *cov : systematics) {
137  cov->PrintNominalCurrProp();
138  }
139 #ifdef DEBUG
140  if (debug)
141  {
142  debugFile << "\n-------------------------------------------------------" << std::endl;
143  debugFile << "Step:\t" << step + 1 << "/" << chainLength << " | current: " << logLCurr << " proposed: " << logLProp << std::endl;
144  }
145 #endif
146 }
147 
148 // *******************
149 void MCMCBase::StartFromPreviousFit(const std::string &FitName) {
150 // *******************
151  // Use base class
153 
154  // For MCMC we also need to set stepStart
155  TFile *infile = M3::Open(FitName, "READ", __FILE__, __LINE__);
156  TTree *posts = infile->Get<TTree>("posteriors");
157  unsigned int step_val = 0;
158 
159  posts->SetBranchAddress("step", &step_val);
160  posts->GetEntry(posts->GetEntries() - 1);
161 
162  stepStart = step_val;
163  // KS: Also update number of steps if using adaption
164  for (unsigned int i = 0; i < systematics.size(); ++i)
165  {
166  if (systematics[i]->GetDoAdaption())
167  {
168  systematics[i]->SetNumberOfSteps(step_val);
169  }
170  }
171  infile->Close();
172  delete infile;
173 }
174 
175 // *************************
177 // *************************
178  // Save the Adaptive output
179  for (const auto &syst : systematics)
180  {
181  if (syst->GetDoAdaption()){
182  syst->UpdateAdaptiveCovariance();
183  }
184  }
185 }
186 
187 // *************************
188 bool MCMCBase::IsStepAccepted(const double acc_prob) {
189 // *************************
190  // Get the random number
191  const double fRandom = random->Rndm();
192  // Do the accept/reject
193  #ifdef DEBUG
194  debugFile << " logLProp: " << logLProp << " logLCurr: " << logLCurr << " acc_prob: " << acc_prob << " fRandom: " << fRandom << std::endl;
195  #endif
196 
197  if (fRandom > acc_prob)
198  {
199  // Reject
200  return false;
201  }
202  return true;
203 }
204 
205 // *************************
207 // *************************
208  ++accCount;
209  logLCurr = logLProp;
210 
211  // Loop over systematics and accept
212  for (size_t s = 0; s < systematics.size(); ++s)
213  {
214  systematics[s]->AcceptStep();
215  }
216 }
#define MACH3LOG_ERROR
Definition: MaCh3Logger.h:37
#define MACH3LOG_INFO
Definition: MaCh3Logger.h:35
Base class for implementing fitting algorithms.
Definition: FitterBase.h:26
std::unique_ptr< TRandom3 > random
Random number.
Definition: FitterBase.h:144
std::vector< SampleHandlerBase * > samples
Sample holder.
Definition: FitterBase.h:129
double logLProp
proposed likelihood
Definition: FitterBase.h:115
void ProcessMCMC()
Process MCMC output.
Definition: FitterBase.cpp:414
int accCount
counts accepted steps
Definition: FitterBase.h:119
void SaveOutput()
Save output and close files.
Definition: FitterBase.cpp:231
void SaveSettings()
Save the settings that the MCMC was run with.
Definition: FitterBase.cpp:79
unsigned int step
current state
Definition: FitterBase.h:111
void PrepareOutput()
Prepare the output file.
Definition: FitterBase.cpp:153
virtual void StartFromPreviousFit(const std::string &FitName)
Allow to start from previous fit/chain.
Definition: FitterBase.cpp:348
double stepTime
Time of single step.
Definition: FitterBase.h:141
Manager * fitMan
The manager for configuration handling.
Definition: FitterBase.h:108
unsigned int stepStart
step start, by default 0 if we start from previous chain then it will be different
Definition: FitterBase.h:121
std::unique_ptr< TStopwatch > stepClock
tells how long single step/fit iteration took
Definition: FitterBase.h:139
double logLCurr
current likelihood
Definition: FitterBase.h:113
int auto_save
auto save every N steps
Definition: FitterBase.h:155
TTree * outTree
Output tree with posteriors.
Definition: FitterBase.h:153
void SanitiseInputs()
Remove obsolete memory and make other checks before fit starts.
Definition: FitterBase.cpp:223
std::vector< ParameterHandlerBase * > systematics
Systematic holder.
Definition: FitterBase.h:134
void RunMCMC() override
Actual implementation of MCMC fitting algorithm.
Definition: MCMCBase.cpp:32
MCMCBase(Manager *const fitMan)
Constructor.
Definition: MCMCBase.cpp:6
bool anneal
simulated annealing
Definition: MCMCBase.h:69
unsigned int chainLength
number of steps in chain
Definition: MCMCBase.h:66
void AcceptStep()
Accept a step.
Definition: MCMCBase.cpp:206
double AnnealTemp
simulated annealing temperature
Definition: MCMCBase.h:71
void StartFromPreviousFit(const std::string &FitName) override
Allow to start from previous fit/chain.
Definition: MCMCBase.cpp:149
bool out_of_bounds
Do we reject based on hitting boundaries in systs.
Definition: MCMCBase.h:60
bool IsStepAccepted(const double acc_prob)
Is step accepted?
Definition: MCMCBase.cpp:188
void DoMCMCStep()
The full StartStep->DoStep->EndStep chain.
Definition: MCMCBase.cpp:80
void PreStepProcess()
Actions before step proposal [start stopwatch].
Definition: MCMCBase.cpp:91
virtual void ProposeStep()=0
Propose a step.
void PrintProgress(const bool StepsPrint=true)
Print the progress.
Definition: MCMCBase.cpp:127
virtual void DoStep()=0
The MCMC step proposal and acceptance.
void PostStepProcess()
Actions after step proposal [end stopwatch, fill tree].
Definition: MCMCBase.cpp:104
void AdaptiveStep()
Adaptive MCMC step.
Definition: MCMCBase.cpp:176
Custom exception class used throughout MaCh3.
The manager class is responsible for managing configurations and settings.
Definition: Manager.h:16
YAML::Node const & raw() const
Return config.
Definition: Manager.h:41
Base class responsible for handling of systematic error parameters. Capable of using PCA or using ada...
TFile * Open(const std::string &Name, const std::string &Type, const std::string &File, const int Line)
Opens a ROOT file with the given name and mode.