FumiliFCNAdapter.h

Go to the documentation of this file.
00001 // @(#)root/minuit2:$Id: FumiliFCNAdapter.h 37067 2010-11-29 14:38:08Z moneta $
00002 // Author: L. Moneta    10/2006  
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2006 ROOT Foundation,  CERN/PH-SFT                   *
00007  *                                                                    *
00008  **********************************************************************/
00009 
00010 #ifndef ROOT_Minuit2_FumiliFCNAdapter
00011 #define ROOT_Minuit2_FumiliFCNAdapter
00012 
00013 #ifndef ROOT_Minuit2_FumiliFCNBase
00014 #include "Minuit2/FumiliFCNBase.h"
00015 #endif
00016 
00017 #ifndef ROOT_Math_FitMethodFunction
00018 #include "Math/FitMethodFunction.h"
00019 #endif
00020 
00021 #ifndef ROOT_Minuit2_MnPrint
00022 #include "Minuit2/MnPrint.h"
00023 #endif
00024 
00025 #ifndef ROOT_Math_Util
00026 #include "Math/Util.h"
00027 #endif
00028 
00029 #include <cmath>
00030 
00031 namespace ROOT {
00032 
00033    namespace Minuit2 {
00034 
00035 /** 
00036 
00037 
00038 template wrapped class for adapting to FumiliFCNBase signature
00039 
00040 @author Lorenzo Moneta
00041 
00042 @ingroup Minuit
00043 
00044 */
00045 
00046 template< class Function> 
00047 class FumiliFCNAdapter : public FumiliFCNBase {
00048 
00049 public:
00050 
00051 //   typedef ROOT::Math::FitMethodFunction Function; 
00052    typedef typename Function::Type_t Type_t; 
00053 
00054    FumiliFCNAdapter(const Function & f, unsigned int ndim, double up = 1.) : 
00055       FumiliFCNBase( ndim ),
00056       fFunc(f) , 
00057       fUp (up)
00058    {}
00059 
00060    ~FumiliFCNAdapter() {}
00061 
00062   
00063    double operator()(const std::vector<double>& v) const { 
00064       return fFunc.operator()(&v[0]); 
00065    }
00066    double operator()(const double *  v) const { 
00067       return fFunc.operator()(v); 
00068    }
00069    double Up() const {return fUp;}
00070 
00071    void SetErrorDef(double up) { fUp = up; } 
00072   
00073    //virtual std::vector<double> Gradient(const std::vector<double>&) const;
00074 
00075    // forward interface
00076    //virtual double operator()(int npar, double* params,int iflag = 4) const;
00077 
00078 
00079  /**
00080      evaluate gradient hessian and function value needed by fumili 
00081    */
00082    void EvaluateAll( const std::vector<double> & v);
00083 
00084 private:
00085    
00086 
00087 //data member
00088 
00089    const Function & fFunc; 
00090    double fUp; 
00091 };
00092 
00093 
00094 template<class Function>
00095 void FumiliFCNAdapter<Function>::EvaluateAll( const std::vector<double> & v) { 
00096 
00097    //typedef FumiliFCNAdapter::Function Function; 
00098 
00099    //evaluate all elements
00100    unsigned int npar = Dimension();
00101    if (npar != v.size() ) std::cout << "npar = " << npar << "  " << v.size() << std::endl;
00102    assert(npar == v.size());
00103    //must distinguish case of likelihood or LS
00104 
00105    std::vector<double> & grad = Gradient(); 
00106    std::vector<double> & hess = Hessian(); 
00107    // reset  
00108    assert(grad.size() == npar);
00109    grad.assign( npar, 0.0); 
00110    hess.assign( hess.size(), 0.0);
00111    
00112    double sum = 0; 
00113    unsigned int ndata = fFunc.NPoints();
00114 
00115    std::vector<double> gf(npar); 
00116  
00117    //loop on the data points
00118 
00119    
00120    // assume for now least-square
00121    if (fFunc.Type() == Function::kLeastSquare) { 
00122 
00123       for (unsigned int i = 0; i < ndata; ++i) { 
00124          // calculate data element and gradient 
00125          double fval = fFunc.DataElement(&v.front(), i, &gf[0]);
00126 
00127          // t.b.d should protect for bad  values of fval
00128          sum += fval*fval;
00129 
00130          for (unsigned int j = 0; j < npar; ++j) { 
00131             grad[j] += 2. * fval * gf[j];
00132             for (unsigned int k = j; k < npar; ++ k) { 
00133                int idx =  j + k*(k+1)/2; 
00134                hess[idx] += 2.0 * gf[j] * gf[k];  
00135             }
00136          }
00137       }
00138    }
00139    else if (fFunc.Type() == Function::kLogLikelihood) {  
00140 
00141 
00142       for (unsigned int i = 0; i < ndata; ++i) { 
00143 
00144          // calculate data element and gradient 
00145          // return value is log of pdf and derivative of the log(Pdf)
00146          double fval = fFunc.DataElement(&v.front(), i, &gf[0]);
00147 
00148          sum -= fval;
00149          
00150          for (unsigned int j = 0; j < npar; ++j) { 
00151             double gfj = gf[j] ; 
00152             grad[j] -= gfj;
00153             for (unsigned int k = j; k < npar; ++ k) { 
00154                int idx =  j + k*(k+1)/2; 
00155                hess[idx] +=  gfj * gf[k] ;  
00156             }
00157          }
00158       }
00159    }
00160    else { 
00161       MN_ERROR_MSG("FumiliFCNAdapter: type of fit method is not supported, it must be chi2 or log-likelihood");
00162    }
00163 }
00164       
00165 
00166    } // end namespace Minuit2
00167 
00168 } // end namespace ROOT
00169 
00170 
00171 
00172 
00173 #endif //ROOT_Minuit2_FCNAdapter

Generated on Tue Jul 5 14:25:41 2011 for ROOT_528-00b_version by  doxygen 1.5.1