40 double inner_product(
const LAVector&, 
const LAVector&);
 
   42 void VariableMetricBuilder::AddResult( std::vector<MinimumState>& result, 
const MinimumState & state)
 const {
 
   46    result.push_back(state);
 
   50    if (TraceIter() ) TraceIteration(result.size()-1, result.back() );
 
   52       if (PrintLevel() > 1) {
 
   53          MnPrint::PrintState(std::cout, result.back(), 
"VariableMetric: Iteration # ",result.size()-1);
 
   59 FunctionMinimum VariableMetricBuilder::Minimum(
const MnFcn& fcn, 
const GradientCalculator& gc, 
const MinimumSeed& seed, 
const MnStrategy& strategy, 
unsigned int maxfcn, 
double edmval)
 const {
 
   69    int printLevel = PrintLevel();
 
   73    std::cout<<
"VariableMetricBuilder convergence when edm < "<<edmval<<std::endl;
 
   76    if(seed.Parameters().Vec().size() == 0) {
 
   77       return FunctionMinimum(seed, fcn.Up());
 
   82    double edm = seed.State().Edm();
 
   84    FunctionMinimum min(seed, fcn.Up() );
 
   88       MN_INFO_MSG(
"VariableMetricBuilder: initial matrix not pos.def.");
 
   94    std::vector<MinimumState> result;
 
   95    if (StorageLevel() > 0)
 
  103       std::cout << 
"VariableMetric: start iterating until Edm is < " << edmval << std::endl;
 
  104       MnPrint::PrintState(std::cout, seed.State(), 
"VariableMetric: Initial state  ");
 
  107    AddResult( result, seed.State());
 
  111    int maxfcn_eff = maxfcn;
 
  113    bool iterate = 
false;
 
  120       std::cout << 
"start iterating... " << std::endl;
 
  121       if (ipass > 0)  std::cout << 
"continue iterating... " << std::endl;
 
  124       min = Minimum(fcn, gc, seed, result, maxfcn_eff, edmval);
 
  127       if ( min.HasReachedCallLimit() ) {
 
  129          MN_INFO_MSG(
"VariableMetricBuilder: FunctionMinimum is invalid, reached the function call limit");
 
  138             MN_INFO_MSG(
"VariableMetricBuilder: FunctionMinimum is invalid after second try");
 
  145       edm = result.back().Edm();
 
  148       if( (strategy.Strategy() == 2) ||
 
  149           (strategy.Strategy() == 1 && min.Error().Dcovar() > 0.05) ) {
 
  152          std::cout<<
"MnMigrad will verify convergence and Error matrix. "<< std::endl;
 
  153          std::cout<<
"dcov is =  "<<  min.Error().Dcovar() << std::endl;
 
  156          MinimumState st = MnHesse(strategy)(fcn, min.State(), min.Seed().Trafo(),maxfcn);
 
  158          if (printLevel > 1) {
 
  159             MnPrint::PrintState(std::cout, st, 
"VariableMetric: After Hessian  ");
 
  161          AddResult( result, st);
 
  166          std::cout << 
"edm after Hesse calculation " << edm << 
" requested " << edmval << std::endl;
 
  170             double machineLimit = fabs(seed.Precision().Eps2()*result.back().Fval());
 
  171             if (edm >= machineLimit)   {
 
  174                MN_INFO_MSG(
"VariableMetricBuilder: Tolerance is not sufficient, continue the minimization");
 
  175                MN_INFO_VAL2(
"Current  Edm is",edm);
 
  176                MN_INFO_VAL2(
"Required Edm is",edmval);
 
  181                MN_INFO_MSG(
"VariableMetricBuilder: Stop the minimization - reached machine accuracy limit");
 
  182                MN_INFO_VAL2(
"Edm is smaller than machine accuracy",machineLimit);
 
  183                MN_INFO_VAL2(
"Current  Edm is",edm);
 
  184                MN_INFO_VAL2(
"Required Edm is",edmval);
 
  198       if (ipass == 0) maxfcn_eff = int(maxfcn*1.3);
 
  205    if (edm > 10*edmval) {
 
  206       min.Add( result.back(), FunctionMinimum::MnAboveMaxEdm() );
 
  208       MN_INFO_VAL2(
"VariableMetricBuilder: INVALID function minimum - edm is above tolerance,",edm);
 
  209       MN_INFO_VAL2(
"VariableMetricBuilder: Required tolerance  is 10 x edmval ",edmval);
 
  215       if ( min.IsAboveMaxEdm() ) {
 
  216          MN_INFO_MSG(
"VariableMetricBuilder: Edm has been re-computed after Hesse");
 
  217          MN_INFO_VAL2(
"new value is now smaller than the required tolerance,",edm);
 
  220       min.Add( result.back()  );
 
  224    std::cout << 
"Obtained function minimum " << min << std::endl;
 
  230 FunctionMinimum VariableMetricBuilder::Minimum(
const MnFcn& fcn, 
const GradientCalculator& gc, 
const MinimumSeed& seed, std::vector<MinimumState>& result, 
unsigned int maxfcn, 
double edmval)
 const {
 
  240    const MnMachinePrecision& prec = seed.Precision();
 
  244    const MinimumState & initialState = result.back();
 
  246    double edm = initialState.Edm();
 
  250    std::cout << 
"\n\nDEBUG Variable Metric Builder  \nInitial State: " 
  251              << 
" Parameter " << initialState.Vec()
 
  252              << 
" Gradient " << initialState.Gradient().Vec()
 
  253              << 
" Inv Hessian " << initialState.Error().InvHessian()
 
  254              << 
" edm = " << initialState.Edm() << std::endl;
 
  260    edm *= (1. + 3.*initialState.Error().Dcovar());
 
  261    MnLineSearch lsearch;
 
  262    MnAlgebraicVector step(initialState.Gradient().Vec().size());
 
  264    MnAlgebraicVector prevStep(initialState.Gradient().Vec().size());
 
  266    MinimumState s0 = result.back();
 
  267    assert(s0.IsValid() ); 
 
  273       step = -1.*s0.Error().InvHessian()*s0.Gradient().Vec();
 
  276       std::cout << 
"\n\n---> Iteration - " << result.size()
 
  277                 << 
"\nFval = " << s0.Fval() << 
" numOfCall = " << fcn.NumOfCalls()
 
  278                 << 
"\nInternal Parameter values " << s0.Vec()
 
  279                 << 
" Newton step " << step << std::endl;
 
  283       if ( inner_product(s0.Gradient().Vec(),s0.Gradient().Vec() )  <= 0 )  {
 
  285          std::cout << 
"VariableMetricBuilder: all derivatives are zero - return current status" << std::endl;
 
  291       double gdel = inner_product(step, s0.Gradient().Grad());
 
  294       std::cout << 
" gdel = " << gdel << std::endl;
 
  300          MN_INFO_MSG(
"VariableMetricBuilder: matrix not pos.def, gdel > 0");
 
  305          step = -1.*s0.Error().InvHessian()*s0.Gradient().Vec();
 
  309          gdel = inner_product(step, s0.Gradient().Grad());
 
  314             AddResult(result, s0);
 
  316             return FunctionMinimum(seed, result, fcn.Up());
 
  320       MnParabolaPoint pp = lsearch(fcn, s0.Parameters(), step, gdel, prec);
 
  323       if(fabs(pp.Y() - s0.Fval()) <=  fabs(s0.Fval())*prec.Eps() ) {
 
  325          MN_INFO_MSG(
"VariableMetricBuilder: no improvement in line search");
 
  329          if (result.size() <= 1 ) 
 
  330             AddResult(result, MinimumState(s0.Parameters(), s0.Error(), s0.Gradient(), s0.Edm(), fcn.NumOfCalls()));
 
  333             AddResult(result, MinimumState(pp.Y(), s0.Edm(), fcn.NumOfCalls()));
 
  341       std::cout << 
"Result after line search : \nx = " << pp.X()
 
  342                 << 
"\nOld Fval = " << s0.Fval()
 
  343                 << 
"\nNew Fval = " << pp.Y()
 
  344                 << 
"\nNFcalls = " << fcn.NumOfCalls() << std::endl;
 
  347       MinimumParameters p(s0.Vec() + pp.X()*step, pp.Y());
 
  350       FunctionGradient g = gc(p, s0.Gradient());
 
  353       edm = Estimator().Estimate(g, s0.Error());
 
  358          MN_INFO_MSG(
"VariableMetricBuilder: matrix not pos.def. : edm is < 0. Make pos def...");
 
  362          edm = Estimator().Estimate(g, s0.Error());
 
  365             MN_INFO_MSG(
"VariableMetricBuilder: matrix still not pos.def. : exit iterations ");
 
  367             AddResult(result, s0);
 
  369             return FunctionMinimum(seed, result, fcn.Up());
 
  372       MinimumError e = ErrorUpdator().Update(s0, p, g);
 
  375       std::cout << 
"Updated new point: \n " 
  376                 << 
" Parameter " << p.Vec()
 
  377                 << 
" Gradient " << g.Vec()
 
  378                 << 
" InvHessian " << e.Matrix()
 
  379                 << 
" Hessian " << e.Hessian()
 
  380                 << 
" edm = " << edm << std::endl << std::endl;
 
  384       s0 =  MinimumState(p, e, g, edm, fcn.NumOfCalls());
 
  385       if (StorageLevel() || result.size() <= 1) 
 
  386          AddResult(result, s0);
 
  389          AddResult(result, MinimumState(p.Fval(), edm, fcn.NumOfCalls()));
 
  392       edm *= (1. + 3.*e.Dcovar());
 
  395       std::cout << 
"Dcovar = " << e.Dcovar() << 
"\tCorrected edm = " << edm << std::endl;
 
  400    } 
while(edm > edmval && fcn.NumOfCalls() < maxfcn);  
 
  403    if ( ! result.back().IsValid() )
 
  407    if(fcn.NumOfCalls() >= maxfcn) {
 
  409       MN_INFO_MSG(
"VariableMetricBuilder: call limit exceeded.");
 
  411       return FunctionMinimum(seed, result, fcn.Up(), FunctionMinimum::MnReachedCallLimit());
 
  415       if(edm < fabs(prec.Eps2()*result.back().Fval())) {
 
  417          MN_INFO_MSG(
"VariableMetricBuilder: machine accuracy limits further improvement.");
 
  419          return FunctionMinimum(seed, result, fcn.Up());
 
  420       } 
else if(edm < 10*edmval) {
 
  421          return FunctionMinimum(seed, result, fcn.Up());
 
  424          MN_INFO_MSG(
"VariableMetricBuilder: iterations finish without convergence.");
 
  425          MN_INFO_VAL2(
"VariableMetricBuilder",edm);
 
  426          MN_INFO_VAL2(
"            requested",edmval);
 
  428          return FunctionMinimum(seed, result, fcn.Up(), FunctionMinimum::MnAboveMaxEdm());
 
  434    std::cout << 
"Exiting successfully Variable Metric Builder \n" 
  435              << 
"NFCalls = " << fcn.NumOfCalls()
 
  436              << 
"\nFval = " <<  result.back().Fval()
 
  437              << 
"\nedm = " << edm << 
" requested = " << edmval << std::endl;
 
  440    return FunctionMinimum(seed, result, fcn.Up());