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());