MnPosDef.cxx

Go to the documentation of this file.
00001 // @(#)root/minuit2:$Id: MnPosDef.cxx 27589 2009-02-24 11:23:44Z moneta $
00002 // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei   2003-2005  
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2005 LCG ROOT Math team,  CERN/PH-SFT                *
00007  *                                                                    *
00008  **********************************************************************/
00009 
00010 #include "Minuit2/MnPosDef.h"
00011 #include "Minuit2/MinimumState.h"
00012 #include "Minuit2/MnMachinePrecision.h"
00013 
00014 #if defined(DEBUG) || defined(WARNINGMSG)
00015 #include "Minuit2/MnPrint.h" 
00016 #endif
00017 
00018 #include <algorithm>
00019 
00020 
00021 namespace ROOT {
00022 
00023    namespace Minuit2 {
00024 
00025 
00026 LAVector eigenvalues(const LASymMatrix&);
00027 
00028 
00029 MinimumState MnPosDef::operator()(const MinimumState& st, const MnMachinePrecision& prec) const {
00030    // interface from minimum state  
00031    MinimumError err = (*this)(st.Error(), prec);
00032    return MinimumState(st.Parameters(), err, st.Gradient(), st.Edm(), st.NFcn());
00033 }
00034 
00035 MinimumError MnPosDef::operator()(const MinimumError& e, const MnMachinePrecision& prec) const {
00036    // make error matrix positive defined returning a new corrected minimum error state
00037 
00038    MnAlgebraicSymMatrix err(e.InvHessian());
00039    if(err.size() == 1 && err(0,0) < prec.Eps()) {
00040       err(0,0) = 1.;
00041       return MinimumError(err, MinimumError::MnMadePosDef());
00042    } 
00043    if(err.size() == 1 && err(0,0) > prec.Eps()) {
00044       return e;
00045    } 
00046    //   std::cout<<"MnPosDef init matrix= "<<err<<std::endl;
00047    
00048    double epspdf = std::max(1.e-6, prec.Eps2());
00049    double dgmin = err(0,0);
00050    
00051    for(unsigned int i = 0; i < err.Nrow(); i++) {
00052 #ifdef WARNINGMSG
00053       if(err(i,i) <= 0 /* prec.Eps2() */ ) 
00054          MN_INFO_VAL2("negative or zero diagonal element in covariance matrix",i);
00055 #endif
00056       if(err(i,i) < dgmin) dgmin = err(i,i);
00057    }
00058    double dg = 0.;
00059    if(dgmin <= 0) {
00060       //dg = 1. + epspdf - dgmin; 
00061       dg = 0.5 + epspdf - dgmin; 
00062       //     dg = 0.5*(1. + epspdf - dgmin); 
00063 #ifdef WARNINGMSG
00064       MN_INFO_VAL2("added to diagonal of Error matrix a value",dg);
00065 #endif
00066       //std::cout << "Error matrix " << err << std::endl;
00067    }
00068    
00069    MnAlgebraicVector s(err.Nrow());
00070    MnAlgebraicSymMatrix p(err.Nrow());
00071    for(unsigned int i = 0; i < err.Nrow(); i++) {
00072       err(i,i) += dg;
00073       if(err(i,i) < 0.) err(i,i) = 1.;
00074       s(i) = 1./sqrt(err(i,i));
00075       for(unsigned int j = 0; j <= i; j++) {
00076          p(i,j) = err(i,j)*s(i)*s(j);
00077       }
00078    }
00079    
00080    //std::cout<<"MnPosDef p: "<<p<<std::endl;
00081    MnAlgebraicVector eval = eigenvalues(p);
00082    double pmin = eval(0);
00083    double pmax = eval(eval.size() - 1);
00084    //std::cout<<"pmin= "<<pmin<<" pmax= "<<pmax<<std::endl;
00085    pmax = std::max(fabs(pmax), 1.);
00086    if(pmin > epspdf*pmax) return MinimumError(err, e.Dcovar());
00087    
00088    double padd = 0.001*pmax - pmin;
00089 #ifdef DEBUG
00090    std::cout<<"eigenvalues: "<<std::endl;
00091 #endif
00092    for(unsigned int i = 0; i < err.Nrow(); i++) {
00093       err(i,i) *= (1. + padd);
00094 #ifdef DEBUG
00095       std::cout<<eval(i)<<std::endl;
00096 #endif
00097    }
00098    //   std::cout<<"MnPosDef final matrix: "<<err<<std::endl;
00099 #ifdef WARNINGMSG
00100    MN_INFO_VAL2("matrix forced pos-def by adding to diagonal",padd);
00101 #endif
00102    return MinimumError(err, MinimumError::MnMadePosDef());
00103 }
00104 
00105    }  // namespace Minuit2
00106 
00107 }  // namespace ROOT

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