24 #if defined(DEBUG) || defined(WARNINGMSG)
27 #if defined(DEBUG) && !defined(WARNINGMSG)
38 MnUserParameterState MnHesse::operator()(
const FCNBase& fcn,
const std::vector<double>& par,
const std::vector<double>& err,
unsigned int maxcalls)
const {
40 return (*
this)(fcn, MnUserParameterState(par, err), maxcalls);
43 MnUserParameterState MnHesse::operator()(
const FCNBase& fcn,
const std::vector<double>& par,
unsigned int nrow,
const std::vector<double>& cov,
unsigned int maxcalls)
const {
45 return (*
this)(fcn, MnUserParameterState(par, cov, nrow), maxcalls);
48 MnUserParameterState MnHesse::operator()(
const FCNBase& fcn,
const std::vector<double>& par,
const MnUserCovariance& cov,
unsigned int maxcalls)
const {
50 return (*
this)(fcn, MnUserParameterState(par, cov), maxcalls);
53 MnUserParameterState MnHesse::operator()(
const FCNBase& fcn,
const MnUserParameters& par,
unsigned int maxcalls)
const {
55 return (*
this)(fcn, MnUserParameterState(par), maxcalls);
58 MnUserParameterState MnHesse::operator()(
const FCNBase& fcn,
const MnUserParameters& par,
const MnUserCovariance& cov,
unsigned int maxcalls)
const {
60 return (*
this)(fcn, MnUserParameterState(par, cov), maxcalls);
63 MnUserParameterState MnHesse::operator()(
const FCNBase& fcn,
const MnUserParameterState& state,
unsigned int maxcalls)
const {
66 unsigned int n = state.VariableParameters();
67 MnUserFcn mfcn(fcn, state.Trafo(),state.NFcn());
68 MnAlgebraicVector x(n);
69 for(
unsigned int i = 0; i < n; i++) x(i) = state.IntParameters()[i];
70 double amin = mfcn(x);
71 Numerical2PGradientCalculator gc(mfcn, state.Trafo(), fStrategy);
72 MinimumParameters par(x, amin);
73 FunctionGradient gra = gc(par);
74 MinimumState tmp = (*this)(mfcn, MinimumState(par, MinimumError(MnAlgebraicSymMatrix(n), 1.), gra, state.Edm(), state.NFcn()), state.Trafo(), maxcalls);
76 return MnUserParameterState(tmp, fcn.Up(), state.Trafo());
79 void MnHesse::operator()(
const FCNBase& fcn, FunctionMinimum& min,
unsigned int maxcalls)
const {
83 MnUserFcn mfcn(fcn, min.UserState().Trafo(),min.NFcn());
84 MinimumState st = (*this)( mfcn, min.State(), min.UserState().Trafo(), maxcalls);
88 MinimumState MnHesse::operator()(
const MnFcn& mfcn,
const MinimumState& st,
const MnUserTransformation& trafo,
unsigned int maxcalls)
const {
92 const MnMachinePrecision& prec = trafo.Precision();
94 double amin = mfcn(st.Vec());
95 double aimsag = sqrt(prec.Eps2())*(fabs(amin)+mfcn.Up());
99 unsigned int n = st.Parameters().Vec().size();
100 if(maxcalls == 0) maxcalls = 200 + 100*n + 5*n*n;
102 MnAlgebraicSymMatrix vhmat(n);
103 MnAlgebraicVector g2 = st.Gradient().G2();
104 MnAlgebraicVector gst = st.Gradient().Gstep();
105 MnAlgebraicVector grd = st.Gradient().Grad();
106 MnAlgebraicVector dirin = st.Gradient().Gstep();
107 MnAlgebraicVector yy(n);
112 if(st.Gradient().IsAnalytical() ) {
113 Numerical2PGradientCalculator igc(mfcn, trafo, fStrategy);
114 FunctionGradient tmp = igc(st.Parameters());
120 MnAlgebraicVector x = st.Parameters().Vec();
123 std::cout <<
"\nMnHesse " << std::endl;
124 std::cout <<
" x " << x << std::endl;
125 std::cout <<
" amin " << amin <<
" " << st.Fval() << std::endl;
126 std::cout <<
" grd " << grd << std::endl;
127 std::cout <<
" gst " << gst << std::endl;
128 std::cout <<
" g2 " << g2 << std::endl;
129 std::cout <<
" Gradient is analytical " << st.Gradient().IsAnalytical() << std::endl;
133 for(
unsigned int i = 0; i < n; i++) {
136 double dmin = 8.*prec.Eps2()*(fabs(xtf) + prec.Eps2());
137 double d = fabs(gst(i));
138 if(d < dmin) d = dmin;
141 std::cout <<
"\nDerivative parameter " << i <<
" d = " << d <<
" dmin = " << dmin << std::endl;
145 for(
unsigned int icyc = 0; icyc < Ncycles(); icyc++) {
149 for(
unsigned int multpy = 0; multpy < 5; multpy++) {
155 sag = 0.5*(fs1+fs2-2.*amin);
158 std::cout <<
"cycle " << icyc <<
" mul " << multpy <<
"\t sag = " << sag <<
" d = " << d << std::endl;
161 if (sag != 0)
goto L30;
162 if(trafo.Parameter(i).HasLimits()) {
163 if(d > 0.5)
goto L26;
165 if(d > 0.5) d = 0.51;
177 const char * name = trafo.Name( trafo.ExtOfInt(i));
178 MN_INFO_VAL2(
"MnHesse: 2nd derivative zero for Parameter ", name);
179 MN_INFO_MSG(
"MnHesse fails and will return diagonal matrix ");
183 for(
unsigned int j = 0; j < n; j++) {
184 double tmp = g2(j) < prec.Eps2() ? 1. : 1./g2(j);
185 vhmat(j,j) = tmp < prec.Eps2() ? 1. : tmp;
188 return MinimumState(st.Parameters(), MinimumError(vhmat, MinimumError::MnHesseFailed()), st.Gradient(), st.Edm(), mfcn.NumOfCalls());
191 double g2bfor = g2(i);
192 g2(i) = 2.*sag/(d*d);
193 grd(i) = (fs1-fs2)/(2.*d);
198 d = sqrt(2.*aimsag/fabs(g2(i)));
199 if(trafo.Parameter(i).HasLimits()) d = std::min(0.5, d);
200 if(d < dmin) d = dmin;
203 std::cout <<
"\t g1 = " << grd(i) <<
" g2 = " << g2(i) <<
" step = " << gst(i) <<
" d = " << d
204 <<
" diffd = " << fabs(d-dlast)/d <<
" diffg2 = " << fabs(g2(i)-g2bfor)/g2(i) << std::endl;
209 if(fabs((d-dlast)/d) < Tolerstp())
break;
210 if(fabs((g2(i)-g2bfor)/g2(i)) < TolerG2())
break;
211 d = std::min(d, 10.*dlast);
212 d = std::max(d, 0.1*dlast);
215 if(mfcn.NumOfCalls() > maxcalls) {
219 MN_INFO_MSG(
"MnHesse: maximum number of allowed function calls exhausted.");
220 MN_INFO_MSG(
"MnHesse fails and will return diagonal matrix ");
223 for(
unsigned int j = 0; j < n; j++) {
224 double tmp = g2(j) < prec.Eps2() ? 1. : 1./g2(j);
225 vhmat(j,j) = tmp < prec.Eps2() ? 1. : tmp;
228 return MinimumState(st.Parameters(), MinimumError(vhmat, MinimumError::MnHesseFailed()), st.Gradient(), st.Edm(), mfcn.NumOfCalls());
234 std::cout <<
"\n Second derivatives " << g2 << std::endl;
237 if(fStrategy.Strategy() > 0) {
239 HessianGradientCalculator hgc(mfcn, trafo, fStrategy);
240 FunctionGradient gr = hgc(st.Parameters(), FunctionGradient(grd, g2, gst));
249 MPIProcess mpiprocOffDiagonal(n*(n-1)/2,0);
250 unsigned int startParIndexOffDiagonal = mpiprocOffDiagonal.StartElementIndex();
251 unsigned int endParIndexOffDiagonal = mpiprocOffDiagonal.EndElementIndex();
253 unsigned int offsetVect = 0;
254 for (
unsigned int in = 0; in<startParIndexOffDiagonal; in++)
255 if ((in+offsetVect)%(n-1)==0) offsetVect += (in+offsetVect)/(n-1);
257 for (
unsigned int in = startParIndexOffDiagonal;
258 in<endParIndexOffDiagonal; in++) {
260 int i = (in+offsetVect)/(n-1);
261 if ((in+offsetVect)%(n-1)==0) offsetVect += i;
262 int j = (in+offsetVect)%(n-1)+1;
264 if ((i+1)==j || in==startParIndexOffDiagonal)
269 double fs1 = mfcn(x);
270 double elem = (fs1 + amin - yy(i) - yy(j))/(dirin(i)*dirin(j));
275 if (j%(n-1)==0 || in==endParIndexOffDiagonal-1)
280 mpiprocOffDiagonal.SyncSymMatrixOffDiagonal(vhmat);
286 std::cout <<
"Original error matrix " << vhmat << std::endl;
289 MinimumError tmpErr = MnPosDef()(MinimumError(vhmat,1.), prec);
292 std::cout <<
"Original error matrix " << vhmat << std::endl;
295 vhmat = tmpErr.InvHessian();
298 std::cout <<
"PosDef error matrix " << vhmat << std::endl;
302 int ifail = Invert(vhmat);
306 MN_INFO_MSG(
"MnHesse: matrix inversion fails!");
307 MN_INFO_MSG(
"MnHesse fails and will return diagonal matrix.");
310 MnAlgebraicSymMatrix tmpsym(vhmat.Nrow());
311 for(
unsigned int j = 0; j < n; j++) {
312 double tmp = g2(j) < prec.Eps2() ? 1. : 1./g2(j);
313 tmpsym(j,j) = tmp < prec.Eps2() ? 1. : tmp;
316 return MinimumState(st.Parameters(), MinimumError(tmpsym, MinimumError::MnInvertFailed()), st.Gradient(), st.Edm(), mfcn.NumOfCalls());
319 FunctionGradient gr(grd, g2, gst);
320 VariableMetricEDMEstimator estim;
323 if(tmpErr.IsMadePosDef()) {
324 MinimumError err(vhmat, MinimumError::MnMadePosDef() );
325 double edm = estim.Estimate(gr, err);
327 MN_INFO_MSG(
"MnHesse: matrix was forced pos. def. ");
329 return MinimumState(st.Parameters(), err, gr, edm, mfcn.NumOfCalls());
333 MinimumError err(vhmat, 0.);
334 double edm = estim.Estimate(gr, err);
337 std::cout <<
"\nHesse is ACCURATE. New state from MnHesse " << std::endl;
338 std::cout <<
"Gradient " << grd << std::endl;
339 std::cout <<
"Second Deriv " << g2 << std::endl;
340 std::cout <<
"Gradient step " << gst << std::endl;
341 std::cout <<
"Error " << vhmat << std::endl;
342 std::cout <<
"edm " << edm << std::endl;
346 return MinimumState(st.Parameters(), err, gr, edm, mfcn.NumOfCalls());