ROOTPWA
hamMCpwa.cc
Go to the documentation of this file.
1 
2 //
3 // Copyright 2009 Sebastian Neubert
4 //
5 // This file is part of rootpwa
6 //
7 // rootpwa is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // rootpwa is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with rootpwa. If not, see <http://www.gnu.org/licenses/>.
19 //
21 // Hamiltonian Markov Chain Monte Carlo Simlation of PWALikelihood
22 //
23 // Copyright Sebastian Neubert, 2009
24 //
25 // This file is part of rootpwa
26 //
27 // Foobar is free software: you can redistribute it and/or modify
28 // it under the terms of the GNU General Public License as published by
29 // the Free Software Foundation, either version 3 of the License, or
30 // (at your option) any later version.
31 //
32 // Foobar is distributed in the hope that it will be useful,
33 // but WITHOUT ANY WARRANTY; without even the implied warranty of
34 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 // GNU General Public License for more details.
36 //
37 // You should have received a copy of the GNU General Public License
38 // along with Foobar. If not, see <http://www.gnu.org/licenses/>.
39 //
40 
41 #include <iostream>
42 #include <list>
43 #include <vector>
44 #include <string>
45 #include <map>
46 #include <complex>
47 #include <assert.h>
48 #include <time.h>
49 #include "TBranch.h"
50 #include "TTree.h"
51 #include "TFile.h"
52 #include "TClonesArray.h"
53 #include "TString.h"
54 #include "TComplex.h"
55 #include "TRandom3.h"
56 #include "TFitBin.h"
57 #include "TStopwatch.h"
58 #include "TPWALikelihood.h"
59 #include "TLogMultiGaus.h"
60 #include "TMCMCMeta.h"
61 
62 //#include "TMinuitMinimizer.h"
63 #include "Minuit2/Minuit2Minimizer.h"
64 using namespace std;
65 using namespace ROOT::Minuit2;
66 
67 int lineno = 1; // global variables needed for lex (not understood)
68 char *progname;
69 
70 
71 int main(int argc, char** argv){
72 
73  gRandom->SetSeed(time(NULL));
74 
75  //if(argc<2)return 1;
76  char* progname=argv[0];
77 
78  // set options
79  unsigned int Nit=5000; // number of iterations
80  double low_mass=0;
81  double high_mass=0;
82  string wavefile_name; // wavelist filename
83  TString ofile_name="MCMCresult.root"; // output filename
84  TString start_file_name; // file with starting values
85  double step=0.1;
86  string norm_file_name; // file with normalization integrals
87  bool quiet=false;
88  unsigned int rank=1; // rank
89  double Ttotal=14000; // max runtime <4 hours
90 
91 
92  extern char *optarg;
93  // extern int optind;
94  int c;
95  while ((c = getopt(argc, argv, "l:u:i:w:o:s:S:n:r:qh")) != -1)
96  switch (c) {
97  case 'i':
98  Nit = atoi(optarg);
99  break;
100  case 'l':
101  low_mass = atof(optarg);
102  break;
103  case 'u':
104  high_mass = atof(optarg);
105  break;
106  case 'o':
107  ofile_name = optarg;
108  break;
109  case 's':
110  step = atof(optarg);
111  break;
112  case 'S':
113  start_file_name= optarg;
114  break;
115  case 'n':
116  norm_file_name = optarg;
117  break;
118  case 'w':
119  wavefile_name = optarg;
120  break;
121  case 'r':
122  rank = atoi(optarg);
123  break;
124 
125  case 'q':
126  quiet = true;
127  break;
128  case 'h':
129  cerr << "usage:" << endl;
130  cerr << progname << " -l # -u # [-i -h -q] [-n normfile -s start values -r rank] -w wavelist -o outfile " << endl;
131  cerr << " where:" << endl;
132  cerr << " -i #: iterations" << endl;
133  cerr << " -t #: maximal runtime in sec (default: 14000)" << endl;
134  cerr << " -l #: lower edge of bin" << endl;
135  cerr << " -u #: upper edge of bin" << endl;
136  cerr << " -w file: set wavelist file" << endl;
137  cerr << " -o file: set output file" << endl;
138  cerr << " -n file: set normalization file" << endl;
139  cerr << " -s #: set stepsize" <<endl;
140  cerr << " -r #: set rank" <<endl;
141  cerr << " -q: run quietly" << endl;
142  cerr << " -h: print help" << endl;
143  exit(0);
144  break;
145  }
146 
147 
148  if(norm_file_name.length()<=1)norm_file_name="norm.int";
149  if(wavefile_name.length()<=1){
150  cerr << "No wavelist specified! Aborting!" << endl;
151  return 1;
152  }
153 
154 
156  if(quiet)L.SetQuiet();
157  L.SetWavelist(wavefile_name);
158  L.SetRank(rank);
159  cout<<L.NDim()<<endl;
160  L.LoadAmplitudes();
161  L.LoadIntegrals(norm_file_name,norm_file_name);
162 
163 
164 
165 
166  // TLogMultiGaus L;
167  //vector<double> prec(2);
168  //prec[1]=0.5;
169  //prec[0]=1;
170  //L.Set(prec);
171 
172  cout << "Installing parameters:" << endl;
173  unsigned int ndim=L.NDim();
174  double dL[ndim]; // gradient of loglikelihood
175  double dLlast[ndim];
176  double E; // likelihood-value
177  double H; // Hamiltonian
178  double X[ndim]; // position in phasespace
179  double Xlast[ndim]; // position in PS for last MCMC step
180  double R[ndim]; // vector of velocities in PS
181  double Rlast[ndim];
182 
183  bool hasstart=false;
184  if(start_file_name.Length()>2){
185  TFile* file=TFile::Open(start_file_name,"READ");
186  TFitBin* start=new TFitBin();
187  // check if tree exists
188  TTree* tree=(TTree*)file->Get("pwa");
189  if(tree==NULL){
190  cout << "pwa Tree not found for starting values." << endl;
191  }
192  else {
193  tree->SetBranchAddress("fitbin",&start);
194  // search for entry with same mass bin
195  for(int i=0;i<tree->GetEntriesFast();++i){
196  tree->GetEntry(i);
197  if(start->mass()<=high_mass && start->mass()>=low_mass){
198  cout << "Start values: found suiting mass bin: " << start->mass() <<endl;
199  break;
200  }
201  }
202  // if no suiting mass bin is found use last one
203  start->getParameters(X);
204  hasstart=true;
205  }
206  file->Close();
207  } // endif (start_file_name.Length()>2)
208 
209  for(unsigned int i=0;i<L.NDim();++i){
210  if(!hasstart)X[i]=0.1; // set default values
211  cout << L.parname(i) << " " << X[i] << endl;
212  R[i]=gRandom->Gaus(0,1); // starting values of velocities
213  }
214 
215 
216 
217  // Output tree with Markov Chain samples
218  TFile* file=TFile::Open(ofile_name,"RECREATE");
219 
220 
221 
222  TTree* tree=new TTree("MarkovChain","MarkovChain");
223  tree->Branch("N",&ndim,"N/I");
224  tree->Branch("dL",&dL,"dL[N]/D");
225  tree->Branch("X",&X,"X[N]/D");
226  tree->Branch("L",&E,"L/D");
227  tree->Branch("H",&H,"H/D");
228  tree->Branch("R",&R,"R[N]/D");
229  tree->Branch("Rlast",&Rlast,"Rlast[N]/D");
230 
231 
232 
233  unsigned int Nacc=0;
234  unsigned int Nleap=5; // max number of leap frog steps per iteration
235  double eps=step; // time step
236  double eps2=0.5*eps;
237  double m=0.1; // virtual mass
238 
239  // write meta info ***********************************
240  TMCMCMeta* meta=new TMCMCMeta();
241  for(unsigned int i=0;i<L.NDim();++i){
242  meta->parnames.push_back(L.parname(i));
243  }
244  meta->stepsize=eps;
245  meta->virtmass=m;
246  meta->Nleap=Nleap;
247  meta->low_mass=low_mass;
248  meta->high_mass=high_mass;
249  meta->NEvents=L.nevents();
250  L.getIntCMatrix(meta->Norm,meta->Norm); // BE CAREFULL HERE!!!
251  meta->Write("MetaInfo");
252 
253 
254  TStopwatch watch;
255  watch.Start();
256  double Tmean=0; // mean time for one simulation step;
257  double Tacc=0; // accumulated time
258 
259  // Start itertions
260  for(unsigned it=0;it<Nit;++it){ // iteration loop
261  double tstart=watch.CpuTime();watch.Continue();
262  cout << "Iteration" << it << endl;
263 
264  // decide which way to go:
265  //double sign= gRandom->Uniform()>0.5 ? +1 : -1;
266  //eps*=sign;
267  //eps2*=sign;
268 
269  // Calculate gradient at starting point
270  L.FdF(X,E,dL);
271  // Save Starting values;
272  if(it==0)tree->Fill();
273 
274  double Hlast=0; // Hamilton Function at last step
275  // calculate Hamiltonian:
276  // add kinetical term
277  for(unsigned int ip=0; ip<ndim;++ip){ // loop over velocities
278  Hlast+=R[ip]*R[ip];
279  } // end loop over velocities
280  Hlast*=0.5/m;
281  Hlast+=E;
282 
283 
284  // Shift velocity update by eps/2:
285  for(unsigned int ip=0; ip<ndim;++ip){ // loop over parameters
286  // store previous
287  Xlast[ip]=X[ip];
288  dLlast[ip]=dL[ip];
289  Rlast[ip]=R[ip];
290  R[ip]=R[ip]-eps2*dL[ip]; // update velocities at middle of step
291  }// end loop over parameters
292 
293  unsigned int nl=gRandom->Integer(Nleap);
294  for(unsigned il=0; il<nl;++il){ // leap frog loop
295  for(unsigned int ip=0; ip<ndim;++ip){ // loop over postions
296  X[ip]=X[ip]+eps/m*R[ip]; // update position
297  }// end loop over positions
298  // Calculate Likelihood update with gradient
299 
300  L.FdF(X,E,dL);
301  // check for last step which has to be a half step again!
302  if(il<nl-1){
303  for(unsigned int ip=0; ip<ndim;++ip){ // loop over velocities
304  R[ip]=R[ip]-eps*dL[ip];
305  } // end loop over velocities
306  }
307  else {
308  for(unsigned int ip=0; ip<ndim;++ip){ // loop over velocities
309  R[ip]=R[ip]-eps2*dL[ip];
310  } // end loop over velocities
311  }
312  } // end Hamilton integration through Nleap steps
313  // Do Metropolis Hastings Step
314  // calculate Hamiltonian:
315  H=0;
316  // add kinetical term (and perturb velocities):
317  double P=0;
318  for(unsigned int ip=0; ip<ndim;++ip){ // loop over velocities
319  H+=R[ip]*R[ip];
320  R[ip]=gRandom->Gaus(0,1); // Gibbs step for velocity
321  P+=R[ip]*R[ip];
322  } // end loop over velocities
323  // Normalize Updated Velocity vector
324  double plength=gRandom->Gaus(0,1);
325  plength/=sqrt(P);
326  for(unsigned int ip=0; ip<ndim;++ip)R[ip]*=plength;
327 
328 
329  H*=0.5/m;
330  H+=E;
331  // in principle H should be constant! Appart from numerical errors
332  cout << ">>>> (Hlast-H)/H = " << (Hlast-H)/H << endl;
333  if(H>Hlast){
334  tree->Fill();
335  ++Nacc;
336  }
337  else{
338  if(gRandom->Uniform()<TMath::Exp(H-Hlast)){
339  tree->Fill();
340  ++Nacc;
341  }
342  else {
343  // Restore old values
344  //for(unsigned int ip=0; ip<ndim;++ip){ // loop over postions
345  // // store previous
346  // X[ip]=Xlast[ip];
347  // dL[ip]=dLlast[ip];
348  //}// end loop over positions
349  //tree->Fill();
350  }
351  }
352 
353  cout << "Acceptance Rate: " << (double)Nacc/(double)(it+1) << endl;
354  double tend=watch.CpuTime();watch.Continue();
355 
356  // recalculate mean tiem for step;
357  Tacc+=tend-tstart;
358  Tmean=Tacc/(double)(it+1);
359 
360  if(it%10==0){
361  cout << "Mean time per iteration: "<< Tmean << "sec"<<endl;
362  cout << "Max time left for this job: "
363  << Ttotal-Tacc << "sec ("<< Tacc/Ttotal*100 << "%)" << endl;
364  }
365 
366  // Stop if we are close to time running out
367  if(Tacc+5*Tmean>Ttotal)break;
368  } // end iteration loop
369 
370 
371  tree->Write();
372  file->Close();
373  cout << "Acceptance Rate: " << (double)Nacc/(double)Nit << endl;
374 
375 
376  return 0;
377 /*
378  // write out result ------------------------------------------------------
379  // ----------------------------------------------------------
380  TFile* outfile=new TFile(ofile_name,"RECREATE");
381  TFitBin* result=new TFitBin();
382 
383 
384  double mass=0.5*(low_mass+high_mass);
385  vector<TString> wavenames;
386  const vector<string>& wnames=L.wavenames();
387  for(int i=0;i<wnames.size();++i){
388  wavenames.push_back(TString(wnames[i].c_str()));
389  }
390 
391  double logli=mini.MinValue();
392  vector<TComplex> amps;
393  vector<complex<double> > V;
394  L.buildCAmps(mini.X(),V,true);
395  // convert to TComplex;
396  for(int i=0;i<V.size();++i)amps.push_back(TComplex(V[i].real(),V[i].imag()));
397 
398 
399  // error matrix;
400  int npar=L.NDim();
401  TMatrixD errm(npar,npar);
402  for(int i=0;i<npar;++i){
403  for(int j=0;j<npar;++j){
404  errm[i][j]=mini.CovMatrix(i,j);
405  }
406  }
407 
408  int n=wavenames.size();
409  // indices of real and imag part of parameter in error matrix;
410  int parcount=0;
411  vector<pair<int,int> > indices(npar);
412  for(int ir=0;ir<rank;++ir){
413  for(int ia=ir;ia<2*n;++ia){
414  if(ia==ir){
415  indices[parcount]=pair<int,int>(parcount,-1);
416  ++parcount;
417  }
418  else {
419  indices[parcount]=pair<int,int>(parcount,parcount+1);
420  parcount+=2;
421  }
422  }
423  }
424  assert(parcount=n+1);
425 
426  // get normalization integral
427  integral norm=L.normInt();
428  TCMatrix integr;
429  integr.ResizeTo(n,n);
430  for(int i=0;i<n;++i){// begin outer loop
431  TString w1=wavenames[i];
432  for(int j=0;j<n;++j){
433  TString w2=wavenames[j];
434  if(w1=="flat" || w2=="flat"){
435  if(w1==w2)integr.set(i,j,complex<double>(1,0));
436  else integr.set(i,j,complex<double>(0,0));
437  }
438  else integr.set(i,j,norm.val(w1.Data(),w2.Data()));
439  }// end inner loop
440  } // end outere loop over parameters;
441 
442  cout << "filling TFitBin" << endl;
443 
444  result->fill(amps,
445  indices,
446  wavenames,
447  L.nevents(),
448  mass,
449  integr,
450  errm,
451  logli,
452  rank);
453 
454  TString binname="fitbin";binname+=low_mass;binname+="_";binname+=high_mass;
455  binname.ReplaceAll(" ","");
456  result->Write(binname);
457  */
458  return 0;
459 }
460 
461 // dummy function needed since we link to but do not use minuit.o
462 int mnparm(int, string, double, double, double, double) {
463  cerr << "this is impossible" << endl;
464  throw "aFit";
465  return 0;
466 }