29 #include "Math/Minimizer1D.h" 
   49 MnParabolaPoint MnLineSearch::operator()(
const MnFcn& fcn, 
const MinimumParameters& st, 
const MnAlgebraicVector& step, 
double gdel, 
const MnMachinePrecision& prec, 
bool debug)
 const {
 
   65       std::cout<<
"gdel= "<<gdel<<std::endl;
 
   66       std::cout<<
"step= "<<step<<std::endl;
 
   69    double overal = 1000.;
 
   70    double undral = -100.;
 
   79    for(
unsigned int i = 0; i < step.size(); i++) {
 
   80       if(step(i) == 0 )  
continue;
 
   81       double ratio = fabs(st.Vec()(i)/step(i));
 
   82       if( slamin == 0) slamin = ratio;
 
   83       if(ratio < slamin) slamin = ratio;
 
   85    if(fabs(slamin) < prec.Eps()) slamin = prec.Eps();
 
   86    slamin *= prec.Eps2();
 
   88    double f0 = st.Fval();
 
   89    double f1 = fcn(st.Vec()+step);
 
   91    double fvmin = st.Fval();
 
   98    double toler8 = toler;
 
   99    double slamax = slambg;
 
  103    bool iterate = 
false;
 
  104    MnParabolaPoint p0(0., f0);
 
  105    MnParabolaPoint p1(slam, flast);
 
  115          std::cout<<
"flast, f0= "<<flast<<
", "<<f0<<std::endl;
 
  116          std::cout<<
"flast-f0= "<<flast-f0<<std::endl;
 
  117          std::cout<<
"slam= "<<slam<<std::endl;
 
  126       double denom = 2.*(flast-f0-gdel*slam)/(slam*slam);
 
  127       if (debug)     std::cout<<
"denom= "<<denom<<std::endl;
 
  134       if (debug)     std::cout<<
"new slam= "<<slam<<std::endl;
 
  137 #ifdef TRY_OPPOSIT_DIR 
  139       bool slamIsNeg = 
false;
 
  144          if (debug)     std::cout<<
"slam is negative- set to   " << slamax << std::endl;
 
  145 #ifdef TRY_OPPOSITE_DIR 
  148          if (debug)     std::cout<<
"slam is negative- compare values between  "<< slamNeg << 
" and  " << slamax << std::endl;
 
  155          if (debug) std::cout << 
"slam larger than mac value - set to " << slamax << std::endl;
 
  159          if (debug) std::cout << 
"slam too small  - set to " << toler8 << std::endl;
 
  164          if (debug) std::cout << 
"slam smaller than " << slamin << 
" return " << std::endl;
 
  168          return MnParabolaPoint(xvmin, fvmin);
 
  170       if(fabs(slam - 1.) < toler8 && p1.Y() < p0.Y()) {
 
  174          return MnParabolaPoint(xvmin, fvmin);
 
  176       if(fabs(slam - 1.) < toler8) slam = 1. + toler8;
 
  183       f2 = fcn(st.Vec() + slam*step);
 
  187 #ifdef TRY_OPPOSITE_DIR 
  190          double f2alt = fcn(st.Vec() + slamNeg*step);
 
  203       if (fabs( p0.Y() - fvmin) < fabs(fvmin)*prec.Eps() ) {
 
  208          overal = slam - toler8;
 
  210          p1 = MnParabolaPoint(slam, flast);
 
  213       } 
while(iterate && niter < maxiter);
 
  214    if(niter >= maxiter) {
 
  216       return MnParabolaPoint(xvmin, fvmin);
 
  220       std::cout<<
"after initial 2-point iter: "<<std::endl;
 
  221       std::cout<<
"x0, x1, x2= "<<p0.X()<<
", "<<p1.X()<<
", "<<slam<<std::endl;
 
  222       std::cout<<
"f0, f1, f2= "<<p0.Y()<<
", "<<p1.Y()<<
", "<<f2<<std::endl;
 
  225    MnParabolaPoint p2(slam, f2);
 
  229       slamax = std::max(slamax, alpha*fabs(xvmin));
 
  230       MnParabola pb = MnParabolaFactory()(p0, p1, p2);
 
  232          std::cout << 
"\nLS Iteration " << niter << std::endl;
 
  233          std::cout<<
"x0, x1, x2= "<<p0.X()<<
", "<<p1.X()<<
", "<<p2.X() <<std::endl;
 
  234          std::cout<<
"f0, f1, f2= "<<p0.Y()<<
", "<<p1.Y()<<
", "<<p2.Y() <<std::endl;
 
  235          std::cout << 
"slamax = " << slamax << std::endl;
 
  236          std::cout<<
"p2-p0,p1: "<<p2.Y() - p0.Y()<<
", "<<p2.Y() - p1.Y()<<std::endl;
 
  237          std::cout<<
"a, b, c= "<<pb.A()<<
" "<<pb.B()<<
" "<<pb.C()<<std::endl;
 
  239       if(pb.A() < prec.Eps2()) {
 
  240          double slopem = 2.*pb.A()*xvmin + pb.B();
 
  241          if(slopem < 0.) slam = xvmin + slamax;
 
  242          else slam = xvmin - slamax;
 
  243          if (debug) std::cout << 
"xvmin = " << xvmin << 
" slopem " << slopem << 
" slam " << slam << std::endl;
 
  247          if(slam > xvmin + slamax) slam = xvmin + slamax;
 
  248          if(slam < xvmin - slamax) slam = xvmin - slamax;
 
  251          if(slam > overal) slam = overal;
 
  253          if(slam < undral) slam = undral;
 
  257          std::cout<<
" slam= "<<slam<< 
" undral " << undral << 
" overal " << overal << std::endl;
 
  263          if (debug) std::cout << 
" iterate on f3- slam  " << niter << 
" slam = " << slam << 
" xvmin " << xvmin << std::endl;
 
  266          double toler9 = std::max(toler8, fabs(toler8*slam));
 
  268          if(fabs(p0.X() - slam) < toler9 ||
 
  269             fabs(p1.X() - slam) < toler9 ||
 
  270             fabs(p2.X() - slam) < toler9) {
 
  274             return MnParabolaPoint(xvmin, fvmin);
 
  280          f3 = fcn(st.Vec() + slam*step);
 
  282                std::cout<<
"f3= "<<f3<<std::endl;
 
  283                std::cout<<
"f3-p(2-0).Y()= "<<f3-p2.Y()<<
" "<<f3-p1.Y()<<
" "<<f3-p0.Y()<<std::endl;
 
  286          if(f3 > p0.Y() && f3 > p1.Y() && f3 > p2.Y()) {
 
  288                std::cout<<
"f3 worse than all three previous"<<std::endl;
 
  290             if(slam > xvmin) overal = std::min(overal, slam-toler8);
 
  291             if(slam < xvmin) undral = std::max(undral, slam+toler8);
 
  292             slam = 0.5*(slam + xvmin);
 
  294                std::cout<<
"new slam= "<<slam<<std::endl;
 
  299       } 
while(iterate && niter < maxiter);
 
  300       if(niter >= maxiter) {
 
  302          return MnParabolaPoint(xvmin, fvmin);
 
  306       MnParabolaPoint p3(slam, f3);
 
  307       if(p0.Y() > p1.Y() && p0.Y() > p2.Y()) p0 = p3;
 
  308       else if(p1.Y() > p0.Y() && p1.Y() > p2.Y()) p1 = p3;
 
  310       if (debug) std::cout << 
" f3 " << f3 << 
" fvmin " << fvmin << 
" xvmin " << xvmin << std::endl;
 
  315          if(slam > xvmin) overal = std::min(overal, slam-toler8);
 
  316          if(slam < xvmin) undral = std::max(undral, slam+toler8);
 
  320    } 
while(niter < maxiter);
 
  323       std::cout<<
"f1, f2= "<<p0.Y()<<
", "<<p1.Y()<<std::endl;
 
  324       std::cout<<
"x1, x2= "<<p0.X()<<
", "<<p1.X()<<std::endl;
 
  325       std::cout<<
"x, f= "<<xvmin<<
", "<<fvmin<<std::endl;
 
  327    return MnParabolaPoint(xvmin, fvmin);
 
  337 MnParabolaPoint MnLineSearch::CubicSearch(
const MnFcn& fcn, 
const MinimumParameters& st, 
const MnAlgebraicVector& step, 
double gdel, 
double g2del,  
const MnMachinePrecision& prec, 
bool debug)
 const {
 
  342       std::cout<<
"gdel= "<<gdel<<std::endl;
 
  343       std::cout<<
"g2del= "<<g2del<<std::endl;
 
  344       std::cout<<
"step= "<<step<<std::endl;
 
  348    double overal = 100.;
 
  349    double undral = -100.;
 
  355    for(
unsigned int i = 0; i < step.size(); i++) {
 
  356       if(step(i) == 0 )  
continue;
 
  357       double ratio = fabs(st.Vec()(i)/step(i));
 
  358       if( slamin == 0) slamin = ratio;
 
  359       if(ratio < slamin) slamin = ratio;
 
  361    if(fabs(slamin) < prec.Eps()) slamin = prec.Eps();
 
  362    slamin *= prec.Eps2();
 
  364    double f0 = st.Fval();
 
  365    double f1 = fcn(st.Vec()+step);
 
  366    double fvmin = st.Fval();
 
  368    if (debug) std::cout << 
"f0 " << f0 << 
"  f1 " << f1 << std::endl;
 
  374    double toler8 = toler;
 
  375    double slamax = slambg;
 
  382    ROOT::Math::SMatrix<double, 3> cubicMatrix;
 
  383    ROOT::Math::SVector<double, 3> cubicCoeff;   
 
  384    ROOT::Math::SVector<double, 3> bVec;   
 
  391    cubicMatrix(0,0) = (x0*x0*x0 - x1*x1*x1)/3.;
 
  392    cubicMatrix(0,1) = (x0*x0 - x1*x1)/2.;
 
  393    cubicMatrix(0,2) = (x0 - x1);
 
  394    cubicMatrix(1,0) = x0*x0;
 
  395    cubicMatrix(1,1) = x0;
 
  396    cubicMatrix(1,2) = 1;
 
  397    cubicMatrix(2,0) = 2.*x0;
 
  398    cubicMatrix(2,1) = 1;
 
  399    cubicMatrix(2,2) = 0;
 
  406    if (debug) std::cout << 
"Vec:\n   " << bVec << std::endl;
 
  409    if (!cubicMatrix.Invert() ) {
 
  410       std::cout << 
"Inversion failed - return " << std::endl;
 
  411       return MnParabolaPoint(xvmin, fvmin);
 
  414    cubicCoeff = cubicMatrix * bVec;
 
  415    if (debug) std::cout << 
"Cubic:\n   " << cubicCoeff << std::endl;
 
  418    double ddd = cubicCoeff(1)*cubicCoeff(1)-4*cubicCoeff(0)*cubicCoeff(2);  
 
  419    double slam1, slam2 = 0;
 
  421    if (cubicCoeff(0) > 0) {
 
  422       slam1 = (- cubicCoeff(1) - std::sqrt(ddd) ) / ( 2. * cubicCoeff(0) );
 
  423       slam2 = (- cubicCoeff(1) + std::sqrt(ddd) ) / ( 2. * cubicCoeff(0) );
 
  425    else if (cubicCoeff(0) < 0) {
 
  426       slam1 = (- cubicCoeff(1) + std::sqrt(ddd) ) / ( 2. * cubicCoeff(0) );
 
  427       slam2 = (- cubicCoeff(1) - std::sqrt(ddd) ) / ( 2. * cubicCoeff(0) );
 
  430       slam1 = - gdel/g2del;
 
  434    std::cout << 
"slam1 &  slam 2 " << slam1 << 
"  " << slam2 << std::endl;
 
  438    if (slam2 < undral) slam2 = undral;
 
  439    if (slam2 > overal) slam2 = overal;
 
  443    if (std::fabs(slam2) < toler) slam2 = ( slam2 >=0 ) ? slamax : -slamax;
 
  446    std::cout << 
"try with slam 2 " << slam2 << std::endl;
 
  448    double f2 = fcn(st.Vec()+slam2*step);
 
  450    std::cout << 
"try with slam 2 " << slam2 << 
" f2 " << f2 << std::endl;
 
  463       if (slam1 < undral) slam1 = undral;
 
  464       if (slam1 > overal) slam1 = overal;
 
  467       if (std::fabs(slam1) < toler) slam1 = ( slam1 >=0 ) ? -slamax : slamax;
 
  469       double f3 = fcn(st.Vec()+slam1*step);
 
  471       std::cout << 
"try with slam 1 " << slam1 << 
" f3 " << f3 << std::endl;
 
  490    bool iterate2 = 
false;
 
  498       std::cout << 
"\n iter" << niter << 
" test approx deriv ad second deriv at " << slam << 
" fp " << fp << std::endl;
 
  501       double h = 0.001*slam;
 
  502       double fh = fcn(st.Vec()+(slam+h)*step);
 
  503       double fl = fcn(st.Vec()+(slam-h)*step);
 
  504       double df = (fh-fl)/(2.*h);
 
  505       double df2 = (fh+fl-2.*fp )/(h*h);
 
  507       std::cout << 
"deriv: " << df << 
" , " << df2 << std::endl;
 
  510       if ( std::fabs(df ) < prec.Eps() && std::fabs( df2 ) < prec.Eps() ) {
 
  512          slam = ( slam >=0 ) ? -slamax : slamax;
 
  514          fp = fcn(st.Vec()+slam*step);
 
  516       else if (  std::fabs(df2 ) <= 0) { 
 
  519          return MnParabolaPoint(slam, fp); 
 
  531          return MnParabolaPoint(slam, fp);
 
  534    } 
while (niter < maxiter);
 
  536    return MnParabolaPoint(xvmin, fvmin);
 
  543       class ProjectedFcn : 
public ROOT::Math::IGenFunction {
 
  547          ProjectedFcn(
const MnFcn & fcn, 
const MinimumParameters & pa, 
const MnAlgebraicVector & step) :
 
  554          ROOT::Math::IGenFunction * Clone()
 const { 
return new ProjectedFcn(*
this); }
 
  558          double DoEval(
double x)
 const {
 
  559             return fFcn(fPar.Vec() + x*fStep);
 
  563          const MinimumParameters & fPar;
 
  564          const MnAlgebraicVector & fStep;
 
  568 MnParabolaPoint MnLineSearch::BrentSearch(
const MnFcn& fcn, 
const MinimumParameters& st, 
const MnAlgebraicVector& step, 
double gdel, 
double g2del,  
const MnMachinePrecision& prec, 
bool debug)
 const {
 
  571       std::cout<<
"gdel= "<<gdel<<std::endl;
 
  572       std::cout<<
"g2del= "<<g2del<<std::endl;
 
  573       for (
unsigned int i = 0; i < step.size(); ++i) {
 
  575             std::cout<<
"step(i)= "<<step(i)<<std::endl;
 
  576             std::cout<<
"par(i) "  <<st.Vec()(i) <<std::endl;
 
  582    ProjectedFcn func(fcn, st, step);
 
  587    double f0 = st.Fval();
 
  588    double f1 = fcn(st.Vec()+step);
 
  591    double fvmin = st.Fval();
 
  593    if (debug) std::cout << 
"f0 " << f0 << 
"  f1 " << f1 << std::endl;
 
  604    double undral = -1000;
 
  605    double overal = 1000;
 
  613    ROOT::Math::SMatrix<double, 3> cubicMatrix;
 
  614    ROOT::Math::SVector<double, 3> cubicCoeff;   
 
  615    ROOT::Math::SVector<double, 3> bVec;   
 
  621    cubicMatrix(0,0) = (x0*x0*x0 - x1*x1*x1)/3.;
 
  622    cubicMatrix(0,1) = (x0*x0 - x1*x1)/2.;
 
  623    cubicMatrix(0,2) = (x0 - x1);
 
  624    cubicMatrix(1,0) = x0*x0;
 
  625    cubicMatrix(1,1) = x0;
 
  626    cubicMatrix(1,2) = 1;
 
  627    cubicMatrix(2,0) = 2.*x0;
 
  628    cubicMatrix(2,1) = 1;
 
  629    cubicMatrix(2,2) = 0;
 
  636    if (debug) std::cout << 
"Vec:\n   " << bVec << std::endl;
 
  639    if (!cubicMatrix.Invert() ) {
 
  640       std::cout << 
"Inversion failed - return " << std::endl;
 
  641       return MnParabolaPoint(xvmin, fvmin);
 
  644    cubicCoeff = cubicMatrix * bVec;
 
  645    if (debug) std::cout << 
"Cubic:\n   " << cubicCoeff << std::endl;
 
  648    double ddd = cubicCoeff(1)*cubicCoeff(1)-4*cubicCoeff(0)*cubicCoeff(2);  
 
  649    double slam1, slam2 = 0;
 
  651    if (cubicCoeff(0) > 0) {
 
  652       slam1 = (- cubicCoeff(1) - std::sqrt(ddd) ) / ( 2. * cubicCoeff(0) );
 
  653       slam2 = (- cubicCoeff(1) + std::sqrt(ddd) ) / ( 2. * cubicCoeff(0) );
 
  655    else if (cubicCoeff(0) < 0) {
 
  656       slam1 = (- cubicCoeff(1) + std::sqrt(ddd) ) / ( 2. * cubicCoeff(0) );
 
  657       slam2 = (- cubicCoeff(1) - std::sqrt(ddd) ) / ( 2. * cubicCoeff(0) );
 
  660       slam1 = - gdel/g2del;
 
  664    if (slam1 < undral) slam1 = undral;
 
  665    if (slam1 > overal) slam1 = overal;
 
  667    if (slam2 < undral) slam2 = undral;
 
  668    if (slam2 > overal) slam2 = overal;
 
  671    double fs1 = func(slam1);
 
  672    double fs2 = func(slam2);
 
  673    std::cout << 
"slam1 &  slam 2 " << slam1 << 
"  " << slam2 << std::endl;
 
  674    std::cout << 
"f(slam1) &  f(slam 2) " << fs1 << 
"  " << fs2 << std::endl;
 
  695    double a = x0 -astart;
 
  696    double b = x0 + astart;
 
  700    double relTol = 0.05;
 
  702    ROOT::Math::Minim1D::Type minType = ROOT::Math::Minim1D::BRENT;
 
  704    bool iterate = 
false;
 
  707    std::cout << 
"f(0)" << func(0.) << std::endl;
 
  708    std::cout << 
"f(1)" << func(1.0) << std::endl;
 
  709    std::cout << 
"f(3)" << func(3.0) << std::endl;
 
  710    std::cout << 
"f(5)" << func(5.0) << std::endl;
 
  717    double delta = delta0;
 
  719    bool scanmin = 
false;
 
  726       std::cout << 
" iter " << iter << 
" a , b , x0 " << a << 
"  " << b << 
"  x0 " << x0 << std::endl;
 
  727       std::cout << 
" fa , fb , f0 " << fa << 
"  " << fb << 
"  f0 " << f0 << std::endl;
 
  728       if (fa <= f0 || fb  <= f0) {
 
  741             if ( std::fabs ( (fa -f2 )/(a-x2) ) >  toler ) {  
 
  750                if (nreset == 0) dir = -1;
 
  752                x0 = x0 + dir * delta;
 
  755                if ( std::fabs (( f0 -fa )/(x0 -a) ) <  toler ) {
 
  756                   delta = 10 * delta0/(10.*(nreset+1));  
 
  763                   std::cout << 
" A: Done a reset - scan in opposite direction ! " << std::endl;
 
  766                if (x0 <  b && x0 > a )
 
  783             if ( std::fabs ( (fb -f2 )/(x2-b) ) >  toler ) {  
 
  792                if (nreset == 0) dir = 1;
 
  794                x0 = x0 + dir * delta;
 
  797                if ( std::fabs ( ( f0 -fb )/(x0-b) ) <  toler ) {
 
  798                   delta = 10 * delta0/(10.*(nreset+1));  
 
  805                   std::cout << 
" B: Done a reset - scan in opposite direction ! " << std::endl;
 
  808                if (x0 >  a && x0 < b)
 
  824          std::cout <<  
" new x0 " << x0 << 
"  " << f0 << std::endl;
 
  827          iterate = scanmin || enlarge;
 
  834    } 
while (iterate && iter < maxiter );
 
  836    if ( f0 > fa || f0 > fb)
 
  839       return MnParabolaPoint(xvmin, fvmin);
 
  844    std::cout << 
"1D minimization using " << minType << std::endl;
 
  846    ROOT::Math::Minimizer1D min(minType);
 
  848    min.SetFunction(func,x0, a, b);
 
  849    int ret = min.Minimize(maxiter, absTol, relTol);
 
  851    std::cout << 
"result of GSL 1D minimization: "  << ret << 
" niter " << min.Iterations() << std::endl;
 
  852    std::cout << 
" xmin = " << min.XMinimum() << 
" fmin " << min.FValMinimum() << std::endl;
 
  854    return MnParabolaPoint(min.XMinimum(), min.FValMinimum());