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