lnsrchBT.hh

Go to the documentation of this file.
00001 //lnsrhcBT.H
00002 // created by WWS
00003 // last modified 06/09/04
00004 
00005 /*************************************************************************
00006 
00007 Copyright Rice University, 2004.
00008 All rights reserved.
00009 
00010 Permission is hereby granted, free of charge, to any person obtaining a
00011 copy of this software and associated documentation files (the "Software"),
00012 to deal in the Software without restriction, including without limitation
00013 the rights to use, copy, modify, merge, publish, distribute, and/or sell
00014 copies of the Software, and to permit persons to whom the Software is
00015 furnished to do so, provided that the above copyright notice(s) and this
00016 permission notice appear in all copies of the Software and that both the
00017 above copyright notice(s) and this permission notice appear in supporting
00018 documentation.
00019 
00020 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00021 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00022 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
00023 RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
00024 NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
00025 DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00026 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00027 ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
00028 THIS SOFTWARE.
00029 
00030 Except as contained in this notice, the name of a copyright holder shall
00031 not be used in advertising or otherwise to promote the sale, use or other
00032 dealings in this Software without prior written authorization of the
00033 copyright holder.
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     //    Scalar gamma; replaced by gamma1
00066     Scalar gamma1;
00067     //    Scalar con; replaced by eta1
00068     Scalar eta1;
00069     Scalar eta2;
00070     bool DispFlag;
00071     Scalar fudge;
00072     //    Scalar stretch; replaced by gamma2
00073     Scalar gamma2;
00074     int maxsteps;
00075     mutable Scalar step; // may be stretched on return
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     //  cerr<<"fval in lnsrchBT::run"<<endl;
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     //  cout<<"fruit = "<<fruit<<" step = "<<step<<endl;
00203 
00204     // check that step is not too small rel length of direction vector
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     //  cout<<"LS: first step\n";
00231     //  x.write(cout);
00232 
00233     // while not sufficient decrease, shrink step 
00234     while( (fx.getValue() > fval + eta1*step*gfdx) && 
00235            (step*dxnorm > minstep) && 
00236            bt <= maxsteps) {
00237       // if the new value is bigger than the old (esp. if it's much bigger),
00238       // then a more nuanced estimate is sensible - use quadratic interpolation
00239       //      if (fx.getValue() > fval && bt<2) {
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     // if we get to here, we've backtracked the max number of steps without
00296     // satisfying sufficient decrease
00297     // return "true", i.e. stop line search alg
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     // otherwise, line search has succeeded, check if we can do better
00315     else {
00316       // internal doubling: lengthen step if success on first try - 
00317       // requires additional workspace:
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());  // vector in which to save last trial point
00325         y.copy(x); 
00326         Scalar stepsave = step;          // last step
00327         Scalar fvalnext=fx.getValue();   // last function value
00328         bt=0;                            // count reset for internal doubling
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         // Stop doubling. If no improvement, backtrack.
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

Generated on 5 Jan 2017 for RvlUmin by  doxygen 1.4.7