00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 #ifndef __RVL_ALG_LINE_SEARCH_BT
00038 #define __RVL_ALG_LINE_SEARCH_BT
00039 
00040 #include "table.hh"
00041 #include "lnsrch.hh"
00042 
00043 namespace RVLUmin {
00044   using namespace RVLAlg;
00045   using namespace RVL;
00046 
00060   template <class Scalar>
00061   class BacktrackingLineSearchAlgBase: public LineSearchAlgBase<Scalar> {
00062 
00063   private:
00064 
00065     
00066     Scalar gamma1;
00067     
00068     Scalar eta1;
00069     Scalar eta2;
00070     bool DispFlag;
00071     Scalar fudge;
00072     
00073     Scalar gamma2;
00074     int maxsteps;
00075     mutable Scalar step; 
00076     bool ans;
00077 
00078     BacktrackingLineSearchAlgBase();
00079 
00080     ostream & str;
00081 
00082   protected:
00083 
00084     LineSearchAlgBase<Scalar> * clone() const {
00085       return new BacktrackingLineSearchAlgBase(*this);
00086     }
00087 
00088   public:
00089 
00105     BacktrackingLineSearchAlgBase
00106     (LineSearchAlg<Scalar> const & lsalg,
00107      FunctionalEvaluation<Scalar> & fx,
00108      Vector<Scalar> const & dx,
00109      Scalar _step,
00110      Scalar _eta1,
00111      Scalar _eta2,
00112      Scalar _gamma1,
00113      Scalar _gamma2,
00114      bool _DispFlag,
00115      Scalar _fudge,
00116      int _maxsteps,
00117      ostream & _str
00118      )
00119       : LineSearchAlgBase<Scalar>(lsalg,fx,dx),
00120     gamma1(_gamma1),    
00121     eta1(_eta1),
00122     eta2(_eta2),
00123     DispFlag(_DispFlag),
00124     fudge(_fudge),
00125     gamma2(_gamma2),
00126     maxsteps(_maxsteps),
00127     step(_step),
00128     ans(false),
00129     str(_str) {}
00130 
00131     BacktrackingLineSearchAlgBase
00132     (const BacktrackingLineSearchAlgBase<Scalar> & ls)
00133       : LineSearchAlgBase<Scalar>(ls),
00134         gamma1(ls.gamma1),
00135         eta1(ls.eta1),
00136         eta2(ls.eta2),
00137     DispFlag(ls.DispFlag),
00138     fudge(ls.fudge),
00139     gamma2(ls.gamma2),
00140     maxsteps(ls.maxsteps),
00141     step(ls.step),
00142     ans(ls.ans),
00143     str(ls.str) {}
00144 
00145     virtual ~BacktrackingLineSearchAlgBase() {}
00146     
00147     ostream & write(ostream & str) const {
00148       str<<"bt\n";
00149       return str;
00150     }
00151 
00152     bool query() { return ans; }
00153 
00154     Scalar getStep() const { return step; }
00155     
00160     void run() {
00161 
00162       try {
00163 
00164     const Vector<Scalar> & x0 = this->getBasePoint();
00165     Vector<Scalar> const & dx = this->getSearchDirection();
00166     FunctionalEvaluation<Scalar> & fx = this->LineSearchAlgBase<Scalar>::getFunctionalEvaluation();
00167     Vector<Scalar> & x = fx.getPoint();
00168     Scalar minstep = this->getMinStep();
00169 
00170     
00171 
00172     Scalar fval = fx.getValue();
00173     Scalar gfdx = dx.inner(fx.getGradient());
00174     Scalar dxnorm = dx.norm();
00175     Scalar rate = gfdx/dxnorm;
00176     Scalar maxstp = fx.getMaxStep(dx);
00177 
00178     Scalar fruit = fudge*maxstp;
00179     step = (step < fruit)?step:fruit;
00180 
00181     if (DispFlag) {
00182       str<<"BacktrackingLineSearchAlg::run:\n";
00183       str<<"  initial function value = "<<fval<<"\n";
00184       str<<"  initial descent rate   = "<<rate<<"\n";
00185       str<<"  estimated step         = "<<step<<"\n";
00186       str<<"  step vector norm       = "<<dxnorm<<"\n";
00187       str<<"  comparison G-A value   = "<<fval+eta1*step*gfdx<<"\n";
00188       str<<"  max feasible step      = "<<maxstp<<"\n";
00189       str.flush();
00190     }
00191 
00192     if (rate > 0.0) {
00193       if (DispFlag) {
00194         str<<"BacktrackingLineSearchAlg::run:\n";
00195         str<<"  SEARCH DIRECTION IS NOT A DESCENT DIRECTION\n";
00196         str.flush();
00197       }
00198       ans=true;
00199       return;
00200     }
00201 
00202     
00203 
00204     
00205         if (step<minstep*dxnorm) {
00206       if (DispFlag) {
00207         str<<"BacktrackingLineSearchAlg::run:\n";
00208         str<<"  proposed step is too small rel search vector length\n";
00209         str<<"  line search aborted\n";
00210         str.flush();
00211       }
00212       ans=true;
00213       return;
00214     }
00215 
00216     x.copy(x0);
00217     x.linComb(step, dx);
00218     
00219     int bt = 0;
00220     if (DispFlag) {
00221       bt++;
00222       str<<"BacktrackingLineSearchAlg::run:\n";
00223       str<<"  backtrack iter "<<bt<<"\n";
00224       str<<"  trial function value = "<<fx.getValue()<<"\n";
00225       str<<"  trial step           = "<<step<<"\n";
00226       str<<"  Min G-A overestimate = "<<fval+eta1*step*gfdx<<"\n";
00227       str.flush();
00228     }        
00229 
00230     
00231     
00232 
00233     
00234     while( (fx.getValue() > fval + eta1*step*gfdx) && 
00235            (step*dxnorm > minstep) && 
00236            bt <= maxsteps) {
00237       
00238       
00239       
00240       if (bt<2) {
00241         Scalar tmpstep = -(gfdx*step*step)/(2.0*(fx.getValue()-fval-step*gfdx));
00242         str<<"  trial quadr. bt step = "<<tmpstep<<"\n";
00243         if (tmpstep < minstep*dxnorm) {
00244           step = step * gamma1;
00245           if (DispFlag) {
00246         str<<"  quadratic bt step    = "<<tmpstep<<" smaller than min step\n";
00247         str<<"  use linear bt step   = "<<step<<"\n";
00248         str.flush();
00249           }
00250         }
00251         else if (tmpstep > step) {
00252           step = step * gamma1;
00253           if (DispFlag) {
00254         str<<"  quadratic bt step    = "<<tmpstep<<" larger than current step\n";
00255         str<<"  use linear bt step   = "<<step<<"\n";
00256         str.flush();
00257           }
00258         }         
00259         else {
00260           step = tmpstep;
00261           if (DispFlag) {
00262         str<<"  quadratic bt step    = "<<step<<" accepted\n";
00263         str.flush();
00264           }
00265         }
00266       }
00267       else {
00268         step = step * gamma1;
00269       }
00270       x.copy(x0);
00271       if (step*dxnorm < minstep) {
00272         if (DispFlag) {
00273           str<<"BacktrackingLineSearchAlg::run:\n";
00274           str<<"  proposed step length = "<<step*dxnorm<<" is smaller than\n";
00275           str<<"  minimum permitted = "<<minstep<<"\n";
00276           str<<"  --- line search aborted\n";
00277           str.flush();
00278         }
00279         ans=true;
00280         return;
00281       }     
00282       x.linComb(step, dx);
00283 
00284       if (DispFlag) {
00285         bt++;
00286         str<<"BacktrackingLineSearchAlg::run:\n";
00287         str<<"  backtrack iter "<<bt<<"\n";
00288         str<<"  trial function value = "<<fx.getValue()<<"\n";
00289         str<<"  Min G-A overestimate = "<<fval+eta1*step*gfdx<<"\n";
00290         str<<"  trial step           = "<<step<<"\n";
00291         str.flush();
00292       }
00293     }
00294 
00295     
00296     
00297     
00298     if (fx.getValue() > fval + eta1*step*gfdx && 
00299         (step*dxnorm > minstep)) {
00300       if (DispFlag) {
00301         str<<"BacktrackingLineSearchAlg::run:\n";
00302         str<<"  G-A criterion not satisfied, step not accepted\n";
00303         str.flush();
00304       }
00305       if ( bt > maxsteps+1 ) { 
00306         if (DispFlag) {
00307           str<<"  Termination: maximum step count exceeded\n";
00308           str.flush();
00309         }
00310       }
00311       x.copy(x0);
00312       ans=true;
00313     }
00314     
00315     else {
00316       
00317       
00318       if( bt<2 ) {
00319         if (DispFlag) {
00320           str<<"BacktrackingLineSearchAlg::run:\n";
00321           str<<"  Successful step\n";
00322           str.flush();
00323         }
00324         Vector<Scalar> y(x.getSpace());  
00325         y.copy(x); 
00326         Scalar stepsave = step;          
00327         Scalar fvalnext=fx.getValue();   
00328         bt=0;                            
00329         while( (fx.getValue() <= fval+eta2*step*gfdx) &&
00330            (fx.getValue() <= fvalnext) &&
00331            bt <= maxsteps) {
00332           str<<"  successful internal doubling - try another\n";
00333           stepsave=step;
00334           y.copy(x);
00335           step=step*gamma2;
00336           fvalnext=fx.getValue();
00337           x.copy(x0);
00338           x.linComb(step, dx);
00339           bt++;
00340           if (DispFlag) {
00341         str<<"  internal doubling step "<<bt<<"\n";
00342         str<<"  trial function value = "<<fx.getValue()<<"\n";
00343         str<<"  Max G-A overestimate = "<<fval+eta2*step*gfdx<<"\n";      
00344         str<<"  trial step           = "<<step<<"\n";
00345         str.flush();
00346           }
00347         }
00348         
00349         if  ((fx.getValue() > fvalnext) && bt > 0) { 
00350           step=stepsave;
00351           x.copy(y);
00352           if (DispFlag) {
00353         str<<"  last internal doubling step "<<bt<<" failed - backtrack\n";
00354           }
00355         }
00356         else {
00357           if (DispFlag) {
00358         str<<"  internal doubling terminated at step "<<bt<<"\n";
00359           }     
00360         }
00361         if (DispFlag) {
00362           str<<"  final function value = "<<fx.getValue()<<"\n";
00363           str<<"  final step           = "<<step<<"\n";
00364           str<<"  *** end line search ***\n";
00365           str.flush();
00366         }
00367       }
00368       ans=false;
00369     }
00370       }
00371       catch (RVLException & e) {
00372     e<<"\ncalled from BacktrackingLineSearchAlg::run\n";
00373     throw e;
00374       }
00375     }
00376 
00377   };
00378 
00421   template<typename Scalar>
00422   class BacktrackingLineSearchAlg: public LineSearchAlg<Scalar> {
00423 
00424   private:
00425 
00426     Scalar eta1;
00427     Scalar eta2;
00428     Scalar gamma1;
00429     Scalar gamma2;
00430     Scalar fudge;
00431     bool DispFlag;
00432     int maxsteps;
00433     ostream & str;
00434 
00435   protected:
00436 
00437     virtual LineSearchAlgBase<Scalar> * 
00438     build(FunctionalEvaluation<Scalar> & fx,
00439       Vector<Scalar> const & dx,
00440       Scalar firststep) {
00441 
00442       return new BacktrackingLineSearchAlgBase<Scalar>(*this,
00443                                fx,dx,firststep,
00444                                eta1,eta2,gamma1,gamma2,DispFlag,
00445                                fudge,maxsteps,str);
00446     }
00447     
00448   public:
00449 
00463     BacktrackingLineSearchAlg(int _maxsteps=10,
00464                   bool _DispFlag = false,
00465                   Scalar firststep=1.0,
00466                   Scalar minsteptol=numeric_limits<Scalar>::epsilon(),
00467                   Scalar _eta1=0.01,
00468                   Scalar _eta2=0.5,
00469                   Scalar _gamma1=0.5,
00470                   Scalar _gamma2=1.8,
00471                   Scalar _fudge=0.9,
00472                   ostream & _str = cout)
00473       : LineSearchAlg<Scalar>(firststep,minsteptol),
00474     eta1(_eta1),
00475     eta2(_eta2),
00476     gamma1(_gamma1),
00477     gamma2(_gamma2),
00478     fudge(_fudge),
00479     DispFlag(_DispFlag),
00480     maxsteps(_maxsteps),
00481         str(_str) {}
00482 
00484     BacktrackingLineSearchAlg(BacktrackingLineSearchAlg<Scalar> const & bt)
00485       : LineSearchAlg<Scalar>(bt),
00486     DispFlag(bt.DispFlag),
00487     eta1(bt.eta1),
00488     eta2(bt.eta2),
00489     gamma1(bt.gamma1),
00490     gamma2(bt.gamma2),
00491     fudge(bt.fudge),
00492     maxsteps(bt.maxsteps),
00493         str(bt.str) {}
00494 
00495     ~BacktrackingLineSearchAlg() {}
00496 
00497   };
00498 }
00499 
00500 #endif