45 double inner_product(
const LAVector&,
const LAVector&);
47 FunctionMinimum FumiliBuilder::Minimum(
const MnFcn& fcn,
const GradientCalculator& gc,
const MinimumSeed& seed,
const MnStrategy& strategy,
unsigned int maxfcn,
double edmval)
const {
56 std::cout<<
"FumiliBuilder convergence when edm < "<<edmval<<std::endl;
59 if(seed.Parameters().Vec().size() == 0) {
60 return FunctionMinimum(seed, fcn.Up());
65 double edm = seed.State().Edm();
67 FunctionMinimum min(seed, fcn.Up() );
71 MN_INFO_MSG(
"FumiliBuilder: initial matrix not pos.def.");
76 std::vector<MinimumState> result;
80 result.push_back( seed.State() );
82 int printLevel = PrintLevel();
84 std::cout <<
"Fumili: start iterating until Edm is < " << edmval << std::endl;
85 MnPrint::PrintState(std::cout, seed.State(),
"Fumili: Initial state ");
87 if (TraceIter() ) TraceIteration(result.size()-1, result.back() );
95 int maxfcn_eff = int(0.5*maxfcn);
102 min = Minimum(fcn, gc, seed, result, maxfcn_eff, edmval);
109 MN_INFO_MSG(
"FumiliBuilder: FunctionMinimum is invalid.");
116 edm = result.back().Edm();
119 std::cout <<
"approximate edm is " << edm << std::endl;
120 std::cout <<
"npass is " << ipass << std::endl;
126 std::cout <<
"FumiliBuilder will verify convergence and Error matrix. " << std::endl;
127 std::cout <<
"dcov is = "<< min.Error().Dcovar() << std::endl;
135 MinimumState st = MnHesse(strategy)(fcn, min.State(), min.Seed().Trafo(),maxfcn);
136 result.push_back( st );
138 if (printLevel > 1) {
139 MnPrint::PrintState(std::cout, st,
"Fumili: After Hessian ");
140 if (TraceIter() ) TraceIteration(result.size()-1, result.back() );
147 std::cout <<
"edm after Hesse calculation " << edm << std::endl;
148 std::cout <<
"state after Hessian calculation " << st << std::endl;
152 if (ipass > 0 && edm >= edmprev) {
154 MN_INFO_MSG(
"FumiliBuilder: Exit iterations, no improvements after Hesse ");
155 MN_INFO_VAL2(
"current edm is ", edm);
156 MN_INFO_VAL2(
"previous value ",edmprev);
162 std::cout <<
"FumiliBuilder: Tolerance is not sufficient - edm is " << edm <<
" requested " << edmval
163 <<
" continue the minimization" << std::endl;
169 if (min.IsAboveMaxEdm() ) {
170 min = FunctionMinimum( min.Seed(), min.States(), min.Up() );
182 if (ipass == 0) maxfcn_eff = maxfcn;
186 }
while (edm > edmval );
191 min.Add( result.back() );
197 FunctionMinimum FumiliBuilder::Minimum(
const MnFcn& fcn,
const GradientCalculator& gc,
const MinimumSeed& seed, std::vector<MinimumState>& result,
unsigned int maxfcn,
double edmval)
const {
230 const MnMachinePrecision& prec = seed.Precision();
232 const MinimumState & initialState = result.back();
234 double edm = initialState.Edm();
238 std::cout <<
"\n\nDEBUG FUMILI Builder \nInitial State: "
239 <<
" Parameter " << initialState.Vec()
240 <<
" Gradient " << initialState.Gradient().Vec()
241 <<
" Inv Hessian " << initialState.Error().InvHessian()
242 <<
" edm = " << initialState.Edm()
243 <<
" maxfcn = " << maxfcn
244 <<
" tolerance = " << edmval
250 edm *= (1. + 3.*initialState.Error().Dcovar());
251 MnAlgebraicVector step(initialState.Gradient().Vec().size());
254 double lambda = 0.001;
256 int printLevel = MnPrint::Level();
260 MinimumState s0 = result.back();
262 step = -1.*s0.Error().InvHessian()*s0.Gradient().Vec();
266 std::cout <<
"\n\n---> Iteration - " << result.size()
267 <<
"\nFval = " << s0.Fval() <<
" numOfCall = " << fcn.NumOfCalls()
268 <<
"\nInternal Parameter values " << s0.Vec()
269 <<
" Newton step " << step << std::endl;
272 double gdel = inner_product(step, s0.Gradient().Grad());
275 MN_INFO_MSG(
"FumiliBuilder: matrix not pos.def, gdel > 0");
280 step = -1.*s0.Error().InvHessian()*s0.Gradient().Vec();
281 gdel = inner_product(step, s0.Gradient().Grad());
283 MN_INFO_VAL2(
"After correction ",gdel);
286 result.push_back(s0);
287 return FunctionMinimum(seed, result, fcn.Up());
306 MinimumParameters p(s0.Vec() + step, fcn( s0.Vec() + step ) );
310 if ( p.Fval() >= s0.Fval() ) {
311 MnLineSearch lsearch;
312 MnParabolaPoint pp = lsearch(fcn, s0.Parameters(), step, gdel, prec);
314 if(fabs(pp.Y() - s0.Fval()) < prec.Eps()) {
318 p = MinimumParameters(s0.Vec() + pp.X()*step, pp.Y() );
322 std::cout <<
"Before Gradient " << fcn.NumOfCalls() << std::endl;
325 FunctionGradient g = gc(p, s0.Gradient());
328 std::cout <<
"After Gradient " << fcn.NumOfCalls() << std::endl;
336 MinimumError e = ErrorUpdator().Update(s0, p, gc, lambda);
339 edm = Estimator().Estimate(g, s0.Error());
343 std::cout <<
"Updated new point: \n "
344 <<
" FVAL " << p.Fval()
345 <<
" Parameter " << p.Vec()
346 <<
" Gradient " << g.Vec()
347 <<
" InvHessian " << e.Matrix()
348 <<
" Hessian " << e.Hessian()
349 <<
" edm = " << edm << std::endl << std::endl;
354 MN_INFO_MSG(
"FumiliBuilder: matrix not pos.def., edm < 0");
358 edm = Estimator().Estimate(g, s0.Error());
360 result.push_back(s0);
361 if (TraceIter() ) TraceIteration(result.size()-1, result.back() );
362 return FunctionMinimum(seed, result, fcn.Up());
367 if ( p.Fval() < s0.Fval() )
373 if ( edm < 0.1 )
break;
377 std::cout <<
" finish iteration- " << result.size() <<
" lambda = " << lambda <<
" f1 = " << p.Fval() <<
" f0 = " << s0.Fval() <<
" num of calls = " << fcn.NumOfCalls() <<
" edm " << edm << std::endl;
380 result.push_back(MinimumState(p, e, g, edm, fcn.NumOfCalls()));
381 if (TraceIter() ) TraceIteration(result.size()-1, result.back() );
383 if (printLevel > 1) {
384 MnPrint::PrintState(std::cout, result.back(),
"Fumili: Iteration # ",result.size());
388 edm *= (1. + 3.*e.Dcovar());
391 }
while(edm > edmval && fcn.NumOfCalls() < maxfcn);
395 if(fcn.NumOfCalls() >= maxfcn) {
397 MN_INFO_MSG(
"FumiliBuilder: call limit exceeded.");
399 return FunctionMinimum(seed, result, fcn.Up(), FunctionMinimum::MnReachedCallLimit());
403 if(edm < fabs(prec.Eps2()*result.back().Fval())) {
405 MN_INFO_MSG(
"FumiliBuilder: machine accuracy limits further improvement.");
407 return FunctionMinimum(seed, result, fcn.Up());
408 }
else if(edm < 10.*edmval) {
409 return FunctionMinimum(seed, result, fcn.Up());
412 MN_INFO_MSG(
"FumiliBuilder: finishes without convergence.");
413 MN_INFO_VAL2(
"FumiliBuilder: ",edm);
414 MN_INFO_VAL2(
" requested: ",edmval);
416 return FunctionMinimum(seed, result, fcn.Up(), FunctionMinimum::MnAboveMaxEdm());
422 std::cout <<
"Exiting successfully FumiliBuilder \n"
423 <<
"NFCalls = " << fcn.NumOfCalls()
424 <<
"\nFval = " << result.back().Fval()
425 <<
"\nedm = " << edm <<
" requested = " << edmval << std::endl;
428 return FunctionMinimum(seed, result, fcn.Up());