ROOTPWA
hamMCtest.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 Test Program
22 //#include <fitlog.h>
23 //#include <integral.h>
24 #include <iostream>
25 #include <list>
26 #include <vector>
27 #include <string>
28 #include <map>
29 #include <complex>
30 #include <assert.h>
31 #include "TBranch.h"
32 #include "TTree.h"
33 #include "TFile.h"
34 #include "TString.h"
35 #include "TComplex.h"
36 #include "TMatrixT.h"
37 #include "TRandom3.h"
38 #include "TFitBin.h"
39 #include "TPWALikelihood.h"
40 #include "TLogMultiGaus.h"
41 
42 //#include "TMinuitMinimizer.h"
43 #include "Minuit2/Minuit2Minimizer.h"
44 using namespace std;
45 using namespace ROOT::Minuit2;
46 
47 int lineno = 1; // global variables needed for lex (not understood)
48 char *progname;
49 
50 
51 int main(int argc, char** argv){
52  //if(argc<2)return 1;
53  char* progname=argv[0];
54 
55  // set options
56  bool interactive=false;
57  double low_mass=0;
58  double high_mass=0;
59  TString wavefile_name; // wavelist filename
60  TString ofile_name="fitresult.root"; // output filename
61  TString sfile_name; // file with starting values
62  TString norm_file_name; // file with normalization integrals
63  bool quiet=false;
64  bool starting=false; // are there starting values?
65  unsigned int rank=1; // rank
66 
67  extern char *optarg;
68  // extern int optind;
69  int c;
70  while ((c = getopt(argc, argv, "l:u:iw:o:s:n:r:qh")) != -1)
71  switch (c) {
72  case 'i':
73  interactive = 1;
74  break;
75  case 'l':
76  low_mass = atof(optarg);
77  break;
78  case 'u':
79  high_mass = atof(optarg);
80  break;
81  case 'o':
82  ofile_name = optarg;
83  break;
84  case 's':
85  sfile_name = optarg;
86  starting = 1;
87  break;
88  case 'n':
89  norm_file_name = optarg;
90  break;
91  case 'w':
92  wavefile_name = optarg;
93  break;
94  case 'r':
95  rank = atoi(optarg);
96  break;
97 
98  case 'q':
99  quiet = true;
100  break;
101  case 'h':
102  cerr << "usage:" << endl;
103  cerr << progname << " -l # -u # [-i -h -q] [-n normfile -s start values -r rank] -w wavelist -o outfile " << endl;
104  cerr << " where:" << endl;
105  cerr << " -i: interactive minuit session" << endl;
106  cerr << " -l #: lower edge of bin" << endl;
107  cerr << " -u #: upper edge of bin" << endl;
108  cerr << " -w file: set wavelist file" << endl;
109  cerr << " -o file: set output file" << endl;
110  cerr << " -n file: set normalization file" << endl;
111  cerr << " -s file: set starting values file" <<endl;
112  cerr << " -r #: set rank" <<endl;
113  cerr << " -q: run quietly" << endl;
114  cerr << " -h: print help" << endl;
115  exit(0);
116  break;
117  }
118 
119 
120 
121  TLogMultiGaus L;
122  TMatrixT<double> cov(2,2);
123  cov[0][0]=1;
124  cov[0][1]=2;
125  cov[1][0]=2;
126  cov[1][1]=5;
127  TMatrixT<double> prec(2,2);
128  prec=cov.Invert();
129  prec.Print();
130  L.Set(prec);
131 
132 
133  cout << "Installing parameters:" << endl;
134  unsigned int ndim=L.NDim();
135  double dL[ndim]; // gradient of loglikelihood
136  double dLlast[ndim];
137  double E; // likelihood-value
138  double X[ndim]; // position in phasespace
139  double Xlast[ndim]; // position in PS for last MCMC step
140  double R[ndim]; // vector of velocities in PS
141  double Rlast[ndim];
142 
143 
144  // Output tree with Markov Chain samples
145  TFile* file=TFile::Open("hamMCtest.root","RECREATE");
146  TTree* tree=new TTree("MarkovChain","MarkovChain");
147  tree->Branch("N",&ndim,"N/I");
148  tree->Branch("dL",&dL,"dL[N]/D");
149  tree->Branch("X",&X,"X[N]/D");
150 
151  TTree* tree2=new TTree("Steps","Steps");
152  tree2->Branch("N",&ndim,"N/I");
153  tree2->Branch("dL",&dL,"dL[N]/D");
154  tree2->Branch("X",&X,"X[N]/D");
155 
156  // TODO: read in starting values!
157  for(unsigned int i=0;i<L.NDim();++i){
158  //cout << L.parname(i) << endl;
159  X[i]=0.1;
160  R[i]=gRandom->Gaus(0,1); // starting values of velocities
161  }
162 
163 
164  unsigned int Nacc=0;
165  unsigned int Nit=5000; // number of iterations
166  unsigned int Nleap=5; // max number of leap frog steps per iteration
167  double eps=0.25; // time step
168  double eps2=0.5*eps;
169  double m=0.5; // virtual mass
170 
171 
172 
173  // Start iterations
174  for(unsigned it=0;it<Nit;++it){ // iteration loop
175  cout << "Iteration" << it << endl;
176  // decide which way to go:
177  //double sign= gRandom->Uniform()>0.5 ? +1 : -1;
178  //eps*=sign;
179  //eps2*=sign;
180 
181  // Calculate gradient at starting point
182  L.FdF(X,E,dL);
183  double Hlast=0; // Hamilton Function at last step
184  // calculate Hamiltonian:
185  // add kinetical term
186  for(unsigned int ip=0; ip<ndim;++ip){ // loop over velocities
187  Hlast+=R[ip]*R[ip];
188  } // end loop over velocities
189  Hlast*=0.5/m;
190  Hlast+=E;
191 
192 
193  // Shift velocity update by eps/2:
194  for(unsigned int ip=0; ip<ndim;++ip){ // loop over parameters
195  Rlast[ip]=R[ip];
196  Xlast[ip]=X[ip];
197  dLlast[ip]=dL[ip];
198  R[ip]=R[ip]-eps2*dL[ip]; // update velocities at middle of step
199  }// end loop over parameters
200 
201  unsigned int nl=Nleap;
202  for(unsigned il=0; il<nl;++il){ // leap frog loop
203  for(unsigned int ip=0; ip<ndim;++ip){ // loop over postions
204  // store previous
205  X[ip]=X[ip]+eps/m*R[ip]; // update position
206  }// end loop over positions
207  // Calculate Likelihood update with gradient
208 
209  L.FdF(X,E,dL);
210  // check for last step which has to be a half step again!
211  if(il<nl-1){
212  for(unsigned int ip=0; ip<ndim;++ip){ // loop over velocities
213  R[ip]=R[ip]-eps*dL[ip];
214  } // end loop over velocities
215  }
216  else {
217  for(unsigned int ip=0; ip<ndim;++ip){ // loop over velocities
218  R[ip]=R[ip]-eps2*dL[ip];
219  } // end loop over velocities
220  }
221  tree2->Fill();
222  } // end Hamilton integration through Nleap steps
223  // Do Metropolis Hastings Step
224  // calculate Hamiltonian:
225  double H=0;
226  // add kinetical term (and perturb velocities):
227  double P=0;
228  for(unsigned int ip=0; ip<ndim;++ip){ // loop over velocities
229  H+=R[ip]*R[ip];
230  R[ip]=gRandom->Gaus(0,1); // Gibbs step for velocity
231  P+=R[ip]*R[ip];
232  } // end loop over velocities
233  // Normalize Updated Velocity vector
234  double plength=gRandom->Gaus(0,1);
235  plength/=sqrt(P);
236  for(unsigned int ip=0; ip<ndim;++ip)R[ip]*=plength;
237 
238 
239  H*=0.5/m;
240  H+=E;
241  // in principle H should be constant! Appart from numerical errors
242  cout << ">>>> (Hlast-H)/H = " << (Hlast-H)/H << endl;
243  if(H>Hlast){
244  tree->Fill();
245  ++Nacc;
246  }
247  else{
248  if(gRandom->Uniform()<TMath::Exp(H-Hlast)){
249  tree->Fill();
250  ++Nacc;
251  }
252  else {
253  // Restore old values
254  //for(unsigned int ip=0; ip<ndim;++ip){ // loop over postions
255  // store previous
256  // X[ip]=Xlast[ip];
257  // dL[ip]=dLlast[ip];
258  //}// end loop over positions
259  //tree->Fill();
260  }
261  }
262 
263  cout << "Acceptance Rate: " << (double)Nacc/(double)(it+1) << endl;
264  } // end iteration loop
265 
266 
267  tree->Write();
268  tree2->Write();
269  file->Close();
270  cout << "Acceptance Rate: " << (double)Nacc/(double)Nit << endl;
271 
272 
273  return 0;
274 /*
275  // write out result ------------------------------------------------------
276  // ----------------------------------------------------------
277  TFile* outfile=new TFile(ofile_name,"RECREATE");
278  TFitBin* result=new TFitBin();
279 
280 
281  double mass=0.5*(low_mass+high_mass);
282  vector<TString> wavenames;
283  const vector<string>& wnames=L.wavenames();
284  for(int i=0;i<wnames.size();++i){
285  wavenames.push_back(TString(wnames[i].c_str()));
286  }
287 
288  double logli=mini.MinValue();
289  vector<TComplex> amps;
290  vector<complex<double> > V;
291  L.buildCAmps(mini.X(),V,true);
292  // convert to TComplex;
293  for(int i=0;i<V.size();++i)amps.push_back(TComplex(V[i].real(),V[i].imag()));
294 
295 
296  // error matrix;
297  int npar=L.NDim();
298  TMatrixD errm(npar,npar);
299  for(int i=0;i<npar;++i){
300  for(int j=0;j<npar;++j){
301  errm[i][j]=mini.CovMatrix(i,j);
302  }
303  }
304 
305  int n=wavenames.size();
306  // indices of real and imag part of parameter in error matrix;
307  int parcount=0;
308  vector<pair<int,int> > indices(npar);
309  for(int ir=0;ir<rank;++ir){
310  for(int ia=ir;ia<2*n;++ia){
311  if(ia==ir){
312  indices[parcount]=pair<int,int>(parcount,-1);
313  ++parcount;
314  }
315  else {
316  indices[parcount]=pair<int,int>(parcount,parcount+1);
317  parcount+=2;
318  }
319  }
320  }
321  assert(parcount=n+1);
322 
323  // get normalization integral
324  integral norm=L.normInt();
325  TCMatrix integr;
326  integr.ResizeTo(n,n);
327  for(int i=0;i<n;++i){// begin outer loop
328  TString w1=wavenames[i];
329  for(int j=0;j<n;++j){
330  TString w2=wavenames[j];
331  if(w1=="flat" || w2=="flat"){
332  if(w1==w2)integr.set(i,j,complex<double>(1,0));
333  else integr.set(i,j,complex<double>(0,0));
334  }
335  else integr.set(i,j,norm.val(w1.Data(),w2.Data()));
336  }// end inner loop
337  } // end outere loop over parameters;
338 
339  cout << "filling TFitBin" << endl;
340 
341  result->fill(amps,
342  indices,
343  wavenames,
344  L.nevents(),
345  mass,
346  integr,
347  errm,
348  logli,
349  rank);
350 
351  TString binname="fitbin";binname+=low_mass;binname+="_";binname+=high_mass;
352  binname.ReplaceAll(" ","");
353  result->Write(binname);
354  */
355  return 0;
356 }
357 
358 // dummy function needed since we link to but do not use minuit.o
359 int mnparm(int, string, double, double, double, double) {
360  cerr << "this is impossible" << endl;
361  throw "aFit";
362  return 0;
363 }