00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "Minuit2/NegativeG2LineSearch.h"
00011 #include "Minuit2/MnFcn.h"
00012 #include "Minuit2/MinimumState.h"
00013 #include "Minuit2/GradientCalculator.h"
00014 #include "Minuit2/MnMachinePrecision.h"
00015 #include "Minuit2/MnLineSearch.h"
00016 #include "Minuit2/MnParabolaPoint.h"
00017 #include "Minuit2/VariableMetricEDMEstimator.h"
00018
00019 #include <cmath>
00020
00021 #ifdef DEBUG
00022 #include <iostream>
00023 #endif
00024
00025 namespace ROOT {
00026
00027 namespace Minuit2 {
00028
00029
00030
00031
00032 MinimumState NegativeG2LineSearch::operator()(const MnFcn& fcn, const MinimumState& st, const GradientCalculator& gc, const MnMachinePrecision& prec) const {
00033
00034
00035
00036
00037
00038
00039
00040 bool negG2 = HasNegativeG2(st.Gradient(), prec);
00041 if(!negG2) return st;
00042
00043 unsigned int n = st.Parameters().Vec().size();
00044 FunctionGradient dgrad = st.Gradient();
00045 MinimumParameters pa = st.Parameters();
00046 bool iterate = false;
00047 unsigned int iter = 0;
00048 do {
00049 iterate = false;
00050 for(unsigned int i = 0; i < n; i++) {
00051
00052 #ifdef DEBUG
00053 std::cout << "negative G2 - iter " << iter << " param " << i << " " << pa.Vec()(i) << " grad2 " << dgrad.G2()(i) << " grad " << dgrad.Vec()(i)
00054 << " grad step " << dgrad.Gstep()(i) << " step size " << pa.Dirin()(i) << std::endl;
00055 #endif
00056 if(dgrad.G2()(i) <= 0) {
00057
00058
00059
00060 if ( std::fabs(dgrad.Vec()(i) ) < prec.Eps() && std::fabs(dgrad.G2()(i) ) < prec.Eps() ) continue;
00061
00062
00063 MnAlgebraicVector step(n);
00064 MnLineSearch lsearch;
00065
00066 if ( dgrad.Vec()(i) < 0)
00067 step(i) = dgrad.Gstep()(i);
00068 else
00069 step(i) = - dgrad.Gstep()(i);
00070
00071 double gdel = step(i)*dgrad.Vec()(i);
00072
00073
00074
00075 bool debugLS = false;
00076
00077 #ifdef DEBUG
00078 std::cout << "step(i) " << step(i) << " gdel " << gdel << std::endl;
00079
00080 debugLS = true;
00081 #endif
00082 MnParabolaPoint pp = lsearch(fcn, pa, step, gdel, prec,debugLS);
00083
00084
00085
00086 #ifdef DEBUG
00087 std::cout << "\nLine search result " << pp.X() << " f(0) " << pa.Fval() << " f(1) " << pp.Y() << std::endl;
00088 #endif
00089
00090 step *= pp.X();
00091 pa = MinimumParameters(pa.Vec() + step, pp.Y());
00092
00093 dgrad = gc(pa, dgrad);
00094
00095 #ifdef DEBUG
00096 std::cout << "Line search - iter" << iter << " param " << i << " " << pa.Vec()(i) << " step " << step(i) << " new grad2 " << dgrad.G2()(i) << " new grad " << dgrad.Vec()(i) << " grad step " << dgrad.Gstep()(i) << std::endl;
00097 #endif
00098
00099 iterate = true;
00100 break;
00101 }
00102 }
00103 } while(iter++ < 2*n && iterate);
00104
00105 MnAlgebraicSymMatrix mat(n);
00106 for(unsigned int i = 0; i < n; i++)
00107 mat(i,i) = (fabs(dgrad.G2()(i)) > prec.Eps2() ? 1./dgrad.G2()(i) : 1.);
00108
00109 MinimumError err(mat, 1.);
00110 double edm = VariableMetricEDMEstimator().Estimate(dgrad, err);
00111
00112 return MinimumState(pa, err, dgrad, edm, fcn.NumOfCalls());
00113 }
00114
00115 bool NegativeG2LineSearch::HasNegativeG2(const FunctionGradient& grad, const MnMachinePrecision& ) const {
00116
00117
00118 for(unsigned int i = 0; i < grad.Vec().size(); i++)
00119
00120 if(grad.G2()(i) <= 0 ) {
00121
00122 return true;
00123 }
00124
00125 return false;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134 }
00135
00136 }