00001 // @(#)root/minuit2:$Id: DavidonErrorUpdator.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/DavidonErrorUpdator.h" 00011 #include "Minuit2/MinimumState.h" 00012 #include "Minuit2/LaSum.h" 00013 #include "Minuit2/LaProd.h" 00014 00015 //#define DEBUG 00016 00017 #if defined(DEBUG) || defined(WARNINGMSG) 00018 #include "Minuit2/MnPrint.h" 00019 #endif 00020 00021 00022 00023 namespace ROOT { 00024 00025 namespace Minuit2 { 00026 00027 00028 double inner_product(const LAVector&, const LAVector&); 00029 double similarity(const LAVector&, const LASymMatrix&); 00030 double sum_of_elements(const LASymMatrix&); 00031 00032 MinimumError DavidonErrorUpdator::Update(const MinimumState& s0, 00033 const MinimumParameters& p1, 00034 const FunctionGradient& g1) const { 00035 00036 // update of the covarianze matrix (Davidon formula, see Tutorial, par. 4.8 pag 26) 00037 // in case of delgam > gvg (PHI > 1) use rank one formula 00038 // see par 4.10 pag 30 00039 00040 const MnAlgebraicSymMatrix& v0 = s0.Error().InvHessian(); 00041 MnAlgebraicVector dx = p1.Vec() - s0.Vec(); 00042 MnAlgebraicVector dg = g1.Vec() - s0.Gradient().Vec(); 00043 00044 double delgam = inner_product(dx, dg); 00045 double gvg = similarity(dg, v0); 00046 00047 00048 #ifdef DEBUG 00049 std::cout << "dx = " << dx << std::endl; 00050 std::cout << "dg = " << dg << std::endl; 00051 std::cout<<"delgam= "<<delgam<<" gvg= "<<gvg<<std::endl; 00052 #endif 00053 00054 if (delgam == 0 ) { 00055 #ifdef WARNINGMSG 00056 MN_INFO_MSG("DavidonErrorUpdator: delgam = 0 : cannot update - return same matrix "); 00057 #endif 00058 return s0.Error(); 00059 } 00060 #ifdef WARNINGMSG 00061 if (delgam < 0) MN_INFO_MSG("DavidonErrorUpdator: delgam < 0 : first derivatives increasing along search line"); 00062 #endif 00063 00064 if (gvg <= 0 ) { 00065 // since v0 is pos def this gvg can be only = 0 if dg = 0 - should never be here 00066 #ifdef WARNINGMSG 00067 MN_INFO_MSG("DavidonErrorUpdator: gvg <= 0 : cannot update - return same matrix "); 00068 #endif 00069 return s0.Error(); 00070 } 00071 00072 00073 MnAlgebraicVector vg = v0*dg; 00074 00075 MnAlgebraicSymMatrix vUpd = Outer_product(dx)/delgam - Outer_product(vg)/gvg; 00076 00077 if(delgam > gvg) { 00078 // use rank 1 formula 00079 vUpd += gvg*Outer_product(MnAlgebraicVector(dx/delgam - vg/gvg)); 00080 } 00081 00082 double sum_upd = sum_of_elements(vUpd); 00083 vUpd += v0; 00084 00085 double dcov = 0.5*(s0.Error().Dcovar() + sum_upd/sum_of_elements(vUpd)); 00086 00087 return MinimumError(vUpd, dcov); 00088 } 00089 00090 /* 00091 MinimumError DavidonErrorUpdator::Update(const MinimumState& s0, 00092 const MinimumParameters& p1, 00093 const FunctionGradient& g1) const { 00094 00095 const MnAlgebraicSymMatrix& v0 = s0.Error().InvHessian(); 00096 MnAlgebraicVector dx = p1.Vec() - s0.Vec(); 00097 MnAlgebraicVector dg = g1.Vec() - s0.Gradient().Vec(); 00098 00099 double delgam = inner_product(dx, dg); 00100 double gvg = similarity(dg, v0); 00101 00102 // std::cout<<"delgam= "<<delgam<<" gvg= "<<gvg<<std::endl; 00103 MnAlgebraicVector vg = v0*dg; 00104 // MnAlgebraicSymMatrix vUpd(v0.Nrow()); 00105 00106 // MnAlgebraicSymMatrix dd = ( 1./delgam )*outer_product(dx); 00107 // dd *= ( 1./delgam ); 00108 // MnAlgebraicSymMatrix VggV = ( 1./gvg )*outer_product(vg); 00109 // VggV *= ( 1./gvg ); 00110 // vUpd = dd - VggV; 00111 // MnAlgebraicSymMatrix vUpd = ( 1./delgam )*outer_product(dx) - ( 1./gvg )*outer_product(vg); 00112 MnAlgebraicSymMatrix vUpd = Outer_product(dx)/delgam - Outer_product(vg)/gvg; 00113 00114 if(delgam > gvg) { 00115 // dx *= ( 1./delgam ); 00116 // vg *= ( 1./gvg ); 00117 // MnAlgebraicVector flnu = dx - vg; 00118 // MnAlgebraicSymMatrix tmp = Outer_product(flnu); 00119 // tmp *= gvg; 00120 // vUpd = vUpd + tmp; 00121 vUpd += gvg*outer_product(dx/delgam - vg/gvg); 00122 } 00123 00124 // 00125 // MnAlgebraicSymMatrix dd = Outer_product(dx); 00126 // dd *= ( 1./delgam ); 00127 // MnAlgebraicSymMatrix VggV = Outer_product(vg); 00128 // VggV *= ( 1./gvg ); 00129 // vUpd = dd - VggV; 00130 // 00131 // 00132 // double phi = delgam/(delgam - gvg); 00133 00134 // MnAlgebraicSymMatrix vUpd(v0.Nrow()); 00135 // if(phi < 0) { 00136 // // rank-2 Update 00137 // MnAlgebraicSymMatrix dd = Outer_product(dx); 00138 // dd *= ( 1./delgam ); 00139 // MnAlgebraicSymMatrix VggV = Outer_product(vg); 00140 // VggV *= ( 1./gvg ); 00141 // vUpd = dd - VggV; 00142 // } 00143 // if(phi > 1) { 00144 // // rank-1 Update 00145 // MnAlgebraicVector tmp = dx - vg; 00146 // vUpd = Outer_product(tmp); 00147 // vUpd *= ( 1./(delgam - gvg) ); 00148 // } 00149 // 00150 00151 // 00152 // if(delgam > gvg) { 00153 // // rank-1 Update 00154 // MnAlgebraicVector tmp = dx - vg; 00155 // vUpd = Outer_product(tmp); 00156 // vUpd *= ( 1./(delgam - gvg) ); 00157 // } else { 00158 // // rank-2 Update 00159 // MnAlgebraicSymMatrix dd = Outer_product(dx); 00160 // dd *= ( 1./delgam ); 00161 // MnAlgebraicSymMatrix VggV = Outer_productn(vg); 00162 // VggV *= ( 1./gvg ); 00163 // vUpd = dd - VggV; 00164 // } 00165 // 00166 00167 double sum_upd = sum_of_elements(vUpd); 00168 vUpd += v0; 00169 00170 // MnAlgebraicSymMatrix V1 = v0 + vUpd; 00171 00172 double dcov = 00173 0.5*(s0.Error().Dcovar() + sum_upd/sum_of_elements(vUpd)); 00174 00175 return MinimumError(vUpd, dcov); 00176 } 00177 */ 00178 00179 } // namespace Minuit2 00180 00181 } // namespace ROOT