MINT2
Neg2LL.h
Go to the documentation of this file.
1 #ifndef NEG2LL_HH
2 #define NEG2LL_HH
3 // author: Jonas Rademacker (Jonas.Rademacker@bristol.ac.uk)
4 // status: Mon 9 Feb 2009 19:17:56 GMT
5 
6 #include "Mint/Minimisable.h"
7 #include "Mint/IPdf.h"
8 #include "Mint/IEventList.h"
9 #include "Mint/IWeightedEvent.h"
10 #include "Mint/counted_ptr.h"
11 #include "Mint/NamedParameter.h"
12 
13 #include <iostream>
14 
15 //#include <omp.h>
16 #include <iomanip>
17 #include <cstdio>
18 #include <vector>
19 
20 /*
21 
22  this implements:
23  class Neg2LL: public Minimisable
24 
25  in a way that its constructor
26 
27  Neg2LL( pdf, eventlist, MinuitParameterSet* mps=0)
28 
29  swallows any type of pdf or eventlist as long as:
30 
31  o pdf implements IPdf<EVENT_TYPE>
32  o eventlist as the method size() and the operator [unsigned int i]
33  o eventList must return an event type that pdf can digest.
34 
35  This specific setup below with Neg2LLClass (defined first, don't
36  use) and Neg2LL (defined 2nd) is chosen such that you can declare
37  Neg2LL w/o the need to specify template arguments, i.e. like this:
38 
39 
40  Neg2LL fcnP(BpPdf, BpEventList);
41 
42  It will take any PDF and Eventlist, with the restrictions described above.
43  This is a bit friendlier than old MINT Neg2LL, which required that you specify
44  template arguments as in Neg2LL<EVENT_TYPE> fcnP(...)
45 
46  */
47 
48 
49 namespace MINT{
50  class Neg2LL;
51 
52  template<typename PDF_TYPE
53  , typename EVENTLIST_TYPE>
54  class Neg2LLClass : public Minimisable{
55  friend class Neg2LL;
56 
57  int _NCalls;
58  protected:
59  //IPdf<EVENT_TYPE>* _pdf;
60  //IEventList<EVENT_TYPE>* _eventList;
61  PDF_TYPE & _pdf;
62  EVENTLIST_TYPE & _eventList;
64  std::vector<double> _grad;
65 
66  // Putting the constructors into "protected" means that nobody can
67  // use this class except for Neg2LL. That's the idea. Use Neg2LL,
68  // not this, this is just a helper class.
69 
70 
71  Neg2LLClass( PDF_TYPE & pdf // IPdf<EVENT_TYPE>* pdf
72  , EVENTLIST_TYPE & erptr // IEventList<EVENT_TYPE>* erptr
73  , MinuitParameterSet* mps = 0)
74  : Minimisable(mps)
75  , _NCalls(0)
76  , _pdf(pdf)
77  , _eventList(erptr)
79  , _grad()
80  {
81  init();
82  }
84  : Minimisable(other)
85  , _NCalls(other._NCalls)
86  , _pdf(other._pdf)
87  , _eventList(other.erptr)
89  , _grad()
90  {
91  init();
92  }
93 
94  public:
95  /*
96  Neg2LLClass( IPdf<EVENT_TYPE>* pdf
97  , MinuitParameterSet* mps = 0)
98  : Minimisable(mps)
99  , _NCalls(0)
100  , _pdf(pdf)
101  , _eventList(0)
102  {
103  init();
104  }
105  */
106  // Neg2LLClass(const Neg2LLClass<EVENT_TYPE>& other)
107 
108  virtual void beginFit(){
109  _pdf.beginFit();
110  };
111  virtual void parametersChanged(){
112  _pdf.parametersChanged();
113  };
114 
115  virtual void endFit(){
116  _pdf.endFit();
117  };
118 
119  bool init(){
120  // just a place holder
121  bool dbThis=true;
122  if(dbThis){
123  std::cout << "Neg2LLClass: I got initialised with an event list with "
124  << _eventList.size() << " events." << std::endl;
125  std::cout << "Neg2LLClass: with pointer: " << &_eventList << std::endl;
126  //if(_eventList.size() > 0){
127  // std::cout << "The first one is:\n"
128  // << _eventList[0]
129  // << std::endl;
130  //}
131 
132  }
133  //_grad= new Double_t[this->getParSet()->size()];
134  _grad.resize(this->getParSet()->size());
135  for(unsigned int i=0; i < _grad.size(); i++) _grad[i]= 0.;
136  return true;
137  }
138 
139  virtual double getPdf(unsigned int evtNumber){
140  bool dbThis=false;
141  //if(dbThis) {
142  //std::cout << "about to call _pdf.getVal() "
143  //<< "for event:\n " << _eventList[evtNumber]
144  //<< std::endl;
145  //}
146  /*
147  if(_eventList.size() <= evtNumber){
148  std::cout << "getPdf called for non-existing event number "
149  << evtNumber
150  << "while _eventList.size() = " << _eventList.size()
151  << "."
152  << std::endl;
153  throw "rubbish";
154  }
155  */
156  double valPdf = _pdf.getVal(_eventList[evtNumber]);
157  if(dbThis) std::cout << " that worked! the value is "
158  << valPdf << std::endl;
159  if(valPdf <= 0){
160  if(dbThis) std::cout << "ERROR in Neg2LLClass::logPdf()"
161  << " the pdf is " << valPdf
162  << " which is <= 0."
163  << std::endl;
164  return -9999.e20 * (1.0 + fabs(valPdf));
165  }
166  return valPdf;
167  }
168 
169  virtual double logPdf(unsigned int evtNumber){
170  return log(getPdf(evtNumber));
171  }
172 
173  virtual double eventWeight(unsigned int evtNumber){
174  return MINT::getWeight(_eventList[evtNumber]);
175  // trick: this is a template that will return one
176  // for all event types, but evt.getWeight in case
177  // the event inherits from IWeightedEvent.
178  // This template is included in IWeightedEvent.h
179  }
180 
181  void doGradient(unsigned int i, double pdfVal, double weight){
182  if(! _useAnalyticGradient) return;
183 
184  std::vector<double> gradPDF(this->getParSet()->size());
185  _pdf.Gradient(_eventList[i], gradPDF,this->getParSet());
186  for(unsigned int j=0; j < this->getParSet()->size(); j++){
187  _grad.at(j)+= weight*gradPDF.at(j)/pdfVal;
188  }
189  return;
190  }
191 
192  virtual double getVal(){
193  _NCalls ++;
194  bool verbose=false;
195  bool dbThis=false;
196  int printFreq = 100;
197  printFreq = 100;
198  if(_NCalls > 500) printFreq = 1000;
199  if(_NCalls > 10000) printFreq = 5000;
200 
201  bool printout = (0 == _NCalls%printFreq) || _NCalls <= 1;
202  printout |= dbThis;
203  verbose |= dbThis;
204 
205  double sum=0;
206 
207  if(verbose && printout){
208  std::cout << "Neg2LLClass::getVal after " << _NCalls << " calls."
209  << " pdf ptr is non zero - that's a start."
210  << std::endl;
211  }
212  double sumweights=0.0;
213  double sumsquareweights=0.0;
214 
215 
216 
217  for(unsigned int i=0; i < _grad.size(); i++) _grad[i]= 0.;
218 
219  // this little thing takes care of things that
220  // get initialised at the first call
221  // (which we should eliminate, but for now
222  // this it a workable work-around)
223  // (needed for multithreading, only)
224  //if(_eventList.empty()) return 0;
225  //eventWeight(0);
226  //getPdf(0);
227 
228  //#pragma omp parallel for reduction(+:sum, sumweights, sumsquareweights);
229  for(unsigned int i=0; i < _eventList.size(); ++i){
230 
231  //EVENT_TYPE & evt( (*_eventList)[i] );
232  // sum += logPdf((*_eventList)[i]);
233  double weight = _eventList[i].getWeight();//eventWeight(i);
234  double pdfVal = getPdf(i);
235  double logPdfVal = log(pdfVal);
236  if(TMath::IsNaN(weight*logPdfVal))continue;
237  sum += weight*logPdfVal;
238  sumweights += weight;
239  sumsquareweights += weight*weight;
240 
241  /*
242  //std::cout << sum << std::endl;
243  if(TMath::IsNaN(sum)){ std::cout << "ERROR for " << i << std::endl;
244  std::cout << weight << std::endl;
245  std::cout << pdfVal << std::endl;
246  std::cout << weight*logPdfVal << std::endl << std::endl;
247 
248  std::cout << _eventList[i].getValueFromVector(0) << std::endl;
249  std::cout << _eventList[i].getValueFromVector(1) << std::endl;
250  std::cout << _eventList[i].getValueFromVector(2) << std::endl;
251  std::cout << _eventList[i].getValueFromVector(3) << std::endl;
252  std::cout << _eventList[i].getValueFromVector(4) << std::endl;
253  std::cout << _eventList[i].getValueFromVector(5) << std::endl;
254  std::cout << _eventList[i].getValueFromVector(6) << std::endl;
255  throw ""; }
256  */
257 
258  if(_useAnalyticGradient) doGradient(i, pdfVal, weight);
259  /*
260  omp didn't cope with the below:
261  if(_useAnalyticGradient){
262  _pdf.Gradient(_eventList[i],gradPDF,this->getParSet());
263  for(unsigned int j=0; j < this->getParSet()->size(); j++){
264  _grad[j]+= weight*gradPDF[j]/pdfVal;
265  }
266  }
267  */
268 
269  }
270 
271  for(unsigned int i=0; i < _grad.size(); i++) _grad[i]=-2. * _grad[i] * fabs(sumweights/sumsquareweights);
272 
273 
274  if(printout){
275  std::cout << "Neg2LLClass::getVal after " << _NCalls << " calls."
276  << "for " << _eventList.size()
277  << " events, I'm about to return "
278  << -2.0*sum*fabs(sumweights/sumsquareweights) << std::endl;
279  std::cout << "Sum of weights = " << sumweights << std::endl;
280  }
281  return -2.* sum*fabs(sumweights/sumsquareweights);
282  }
283 
284  virtual void Gradient(std::vector<double>& grad){
285  grad=_grad;
286  //for(unsigned int i=0; i < _grad.size(); i++) grad[i]=_grad[i];
287  }
288 
289  virtual bool useAnalyticGradient() {return _useAnalyticGradient;}
291 
292  virtual double getNewVal(){
293  // forces re-calculation after parameter change
295  return getVal();
296  }
297 
298  virtual ~Neg2LLClass(){}//if(0 != _grad) delete[] _grad;}
299 
300  };
301 
302 
303  // ===================================
304 
305  class Neg2LL: public Minimisable{
306  protected:
308 
309  public:
310  template <typename PDF_TYPE, typename EVENTLIST_TYPE>
311  Neg2LL(PDF_TYPE & pdf, EVENTLIST_TYPE & evtList
312  , MinuitParameterSet* mps=0)
313  : _imini(new Neg2LLClass <PDF_TYPE, EVENTLIST_TYPE>(pdf, evtList, mps))
314  {
315  }
316 
317  //Neg2LL(const Neg2LL& other): _imini(other._imini){
318  //}
319 
320  virtual MinuitParameterSet* getParSet(){ return _imini->getParSet();}
321 
322  virtual void beginFit(){_imini->beginFit();}
323  virtual void parametersChanged(){_imini->parametersChanged();}
324  virtual void endFit(){_imini->endFit();}
325 
326  virtual double getVal(){return _imini->getVal();}
327  virtual double getNewVal(){return _imini->getNewVal();}
328 
329  virtual void Gradient(std::vector<double>& grad){_imini->Gradient(grad);}
330  virtual bool useAnalyticGradient() {return _imini->useAnalyticGradient();}
331  virtual void setUseAnalyticGradient(bool useAnalyticGradient) { _imini->setUseAnalyticGradient(useAnalyticGradient); }
332 
333  virtual ~Neg2LL(){}
334 
335  };
336 
337 } // namespace MINT
338 
339 #endif
340 //
virtual void parametersChanged()
Definition: Neg2LL.h:323
virtual MinuitParameterSet * getParSet()
Definition: Neg2LL.h:320
virtual double getNewVal()
Definition: Neg2LL.h:292
virtual double getNewVal()
Definition: Neg2LL.h:327
std::vector< double > _grad
Definition: Neg2LL.h:64
virtual void Gradient(std::vector< double > &grad)
Definition: Neg2LL.h:284
virtual void endFit()
Definition: Neg2LL.h:324
virtual double getVal()
Definition: Neg2LL.h:326
virtual void beginFit()
Definition: Neg2LL.h:108
unsigned int size() const
virtual void setUseAnalyticGradient(bool useAnalyticGradient)
Definition: Neg2LL.h:290
virtual void setUseAnalyticGradient(bool useAnalyticGradient)
Definition: Neg2LL.h:331
bool _useAnalyticGradient
Definition: Neg2LL.h:63
virtual double getPdf(unsigned int evtNumber)
Definition: Neg2LL.h:139
virtual ~Neg2LL()
Definition: Neg2LL.h:333
virtual double eventWeight(unsigned int evtNumber)
Definition: Neg2LL.h:173
PDF_TYPE & _pdf
Definition: Neg2LL.h:61
Neg2LL(PDF_TYPE &pdf, EVENTLIST_TYPE &evtList, MinuitParameterSet *mps=0)
Definition: Neg2LL.h:311
counted_ptr< IMinimisable > _imini
Definition: Neg2LL.h:307
virtual void Gradient(std::vector< double > &grad)
Definition: Neg2LL.h:329
MinuitParameterSet * getParSet()
Definition: Minimisable.cpp:25
virtual bool useAnalyticGradient()
Definition: Neg2LL.h:330
virtual ~Neg2LLClass()
Definition: Neg2LL.h:298
double getWeight(const EVT_TYPE &)
virtual double logPdf(unsigned int evtNumber)
Definition: Neg2LL.h:169
void doGradient(unsigned int i, double pdfVal, double weight)
Definition: Neg2LL.h:181
Neg2LLClass(const Neg2LLClass< PDF_TYPE, EVENTLIST_TYPE > &other)
Definition: Neg2LL.h:83
EVENTLIST_TYPE & _eventList
Definition: Neg2LL.h:62
virtual double getVal()
Definition: Neg2LL.h:192
virtual bool useAnalyticGradient()
Definition: Neg2LL.h:289
Neg2LLClass(PDF_TYPE &pdf, EVENTLIST_TYPE &erptr, MinuitParameterSet *mps=0)
Definition: Neg2LL.h:71
virtual void parametersChanged()
Definition: Neg2LL.h:111
virtual void beginFit()
Definition: Neg2LL.h:322
virtual void endFit()
Definition: Neg2LL.h:115