00001 #ifndef RVL_UMIN_TRALG_
00002 #define RVL_UMIN_TRALG_
00003
00004 #include "table.hh"
00005 #include "op.hh"
00006 #include "alg.hh"
00007 #include "ioterm.hh"
00008 #include "boolterm.hh"
00009
00010 namespace RVLUmin {
00011
00012 using namespace RVL;
00013 using namespace RVLAlg;
00014
00056 template<typename Scalar, typename Policy >
00057 class TRGNStep: public Algorithm {
00058
00059 typedef typename ScalarFieldTraits<Scalar>::AbsType atype;
00060
00061 public:
00062
00082 void run() {
00083
00084
00085
00086 solver->run();
00087 bool active = false;
00088 {
00089 Terminator & tsolver = dynamic_cast<Terminator &>(*solver);
00090 active = tsolver.query();
00091 }
00092 delete solver;
00093 solver=NULL;
00094
00095
00096 if (p.norm()<minstep*pol.Delta) {
00097 nostep=true;
00098 return;
00099 }
00100
00101
00102 atype jvalsave = jval;
00103 predred = jvalsave - 0.5*rnorm*rnorm;
00104 str<<"** predicted reduction = "<<predred<<" active = "<<active<<"\n";
00105 str<<"** length of step = "<<p.norm()<<"\n";
00106
00107
00108
00109 Vector<Scalar> & x = opeval.getPoint();
00110 xsave.copy(x);
00111 x.linComb(-ScalarFieldTraits<Scalar>::One(),p);
00112
00113
00114
00115
00116
00117
00118 jval = 0.5*opeval.getValue().normsq();
00119
00120
00121 actred = jvalsave - jval;
00122
00123 str<<"** actual reduction: old jval = "<<jvalsave<<" new jval = "<<jval<<" actred = "<<actred<<"\n";
00124 if (actred < eta1*predred) {
00125 pol.Delta *= gamma1;
00126 x.copy(xsave);
00127 }
00128
00129
00130 if ((actred > eta2*predred) && active) {
00131 int dcount = 0;
00132 Vector<Scalar> plast(opeval.getDomain());
00133 while (active && dcount<5) {
00134 str<<"active trust region constraint and good step - attempt to increase TR\n";
00135 atype deltalast=pol.Delta;
00136 atype jvallast = jval;
00137
00138
00139 plast.copy(p);
00140
00141 p.scale(gamma2);
00142
00143 pol.Delta *= gamma2;
00144 str<<"last TR = "<<deltalast<<" new TR = "<<pol.Delta<<"\n";
00145
00146 x.copy(xsave);
00147
00148 Vector<Scalar> dp(opeval.getRange());
00149 opeval.getDeriv().applyOp(p,dp);
00150
00151 dp.linComb(-ScalarFieldTraits<Scalar>::One(),opeval.getValue());
00152
00153 predred = jvalsave - 0.5*dp.normsq();
00154 str<<"new predred="<<predred<<"\n";
00155
00156 x.linComb(-ScalarFieldTraits<Scalar>::One(),p);
00157
00158 jval = 0.5*opeval.getValue().normsq();
00159 str<<"last jval = "<<jvalsave<<" new jval = "<<jval<<"\n";
00160
00161 actred = jvalsave - jval;
00162 str<<"new actred = "<<actred<<"\n";
00163
00164 if (actred < eta1*predred || jval > jvallast) {
00165 str<<"G-A failed, revert to previous estimate, unset active flag\n";
00166 pol.Delta = deltalast;
00167 jval=jvallast;
00168 p.copy(plast);
00169 x.copy(xsave);
00170 x.linComb(-ScalarFieldTraits<Scalar>::One(),p);
00171 active=false;
00172 }
00173 else {
00174 str<<"G-A passed";
00175 }
00176 dcount++;
00177 if (dcount==5) {
00178 str<<", max number of TR expansions reached\n";
00179 }
00180 else {
00181 str<<", try it again\n";
00182 }
00183 }
00184 }
00185
00186
00187 solver = pol.build(p,opeval.getDeriv(),opeval.getValue(),rnorm,nrnorm,str);
00188 agnrm=nrnorm;
00189 rgnrm=nrnorm*gnrmrecip;
00190
00191
00192 }
00193
00194 atype getDelta() { return pol.Delta; }
00195
00234 TRGNStep(Policy const & _pol,
00235 OperatorEvaluation<Scalar> & _opeval,
00236 atype _eta1,
00237 atype _eta2,
00238 atype _gamma1,
00239 atype _gamma2,
00240 atype _minstep,
00241 bool & _nostep,
00242 atype & _predred,
00243 atype & _actred,
00244 atype & _jval,
00245 atype & _agnrm,
00246 atype & _rgnrm,
00247 ostream & _str)
00248 : pol(_pol),
00249 opeval(_opeval),
00250 eta1(_eta1),eta2(_eta2),gamma1(_gamma1),gamma2(_gamma2),minstep(_minstep),
00251 nostep(_nostep),predred(_predred), actred(_actred),
00252 jval(_jval), agnrm(_agnrm), rgnrm(_rgnrm),
00253 p(_opeval.getDomain()), xsave(_opeval.getDomain()), solver(NULL), str(_str) {
00254
00255
00256
00257 if ( (gamma1 <= ScalarFieldTraits<atype>::Zero()) ||
00258 (gamma1 > ScalarFieldTraits<atype>::One()) ||
00259 (gamma2 < ScalarFieldTraits<atype>::One()) ||
00260 (gamma1*gamma2 > ScalarFieldTraits<atype>::One()-100.0*numeric_limits<atype>::epsilon()) ||
00261 (eta1 < ScalarFieldTraits<atype>::Zero()) ||
00262 (eta1 > eta2) ) {
00263 RVLException e;
00264 e<<"Error: TRTRGNStep constructor\n";
00265 e<<"insane TR param inputs\n";
00266 e<<"gamma1= "<<gamma1<<"\n";
00267 e<<"gamma2= "<<gamma2<<"\n";
00268 e<<"eta1 = "<<eta1<<"\n";
00269 e<<"eta2 = "<<eta2<<"\n";
00270 throw e;
00271 }
00272
00273
00274 actred = ScalarFieldTraits<atype>::Zero();
00275 predred = ScalarFieldTraits<atype>::Zero();
00276
00277
00278
00279 solver = pol.build(p,opeval.getDeriv(),opeval.getValue(),rnorm,nrnorm,str);
00280
00281
00282
00283
00284 jval = 0.5*rnorm*rnorm;
00285 agnrm = nrnorm;
00286
00287
00288 if (ProtectedDivision<atype>(ScalarFieldTraits<atype>::One(),nrnorm,gnrmrecip)) {
00289
00290 agnrm = ScalarFieldTraits<atype>::Zero();
00291 rgnrm = ScalarFieldTraits<atype>::Zero();
00292 gnrmrecip = ScalarFieldTraits<atype>::Zero();
00293 str<<"NOTE: TRGNStep constructor\n";
00294 str<<" initial value of normal residual norm = "<<nrnorm<<" below division threshold\n";
00295 str<<" set residual norm values to zero, return - this should stop iteration\n";
00296 }
00297 else {
00298 rgnrm = ScalarFieldTraits<atype>::One();
00299 }
00300
00301
00302
00303 }
00304
00305 ~TRGNStep() { if (solver) delete solver; }
00306
00307 private:
00308
00309 Policy const & pol;
00310 OperatorEvaluation<Scalar> & opeval;
00311 atype & predred;
00312 atype & actred;
00313 atype & jval;
00314 atype & agnrm;
00315 atype & rgnrm;
00316 bool & nostep;
00317 atype gnrmrecip;
00318 atype eta1;
00319 atype eta2;
00320 atype gamma1;
00321 atype gamma2;
00322 atype minstep;
00323 atype rnorm;
00324 atype nrnorm;
00325 Vector<Scalar> p;
00326 Vector<Scalar> xsave;
00327
00328 mutable Algorithm * solver;
00329 ostream & str;
00330 };
00331
00468 template<typename Scalar, typename Policy>
00469 class TRGNAlg: public Algorithm, public Policy {
00470
00471 typedef typename ScalarFieldTraits<Scalar>::AbsType atype;
00472
00473 public:
00474
00475 void run() {
00476
00477 try {
00478 bool nostep = false;
00479
00480 TRGNStep<Scalar, Policy> step(*this,opeval,eta1,eta2,gamma1,gamma2,minstep,
00481 nostep,predred,actred,jval,agnrm,rgnrm,str);
00482 BoolTerminator bstop(nostep);
00483 VectorCountingThresholdIterationTable<atype> vstop(maxcount,names,nums,tols,str);
00484 vstop.init();
00485 atype jval0=jval;
00486 atype agnrm0=agnrm;
00487 atype delta0=step.getDelta();
00488 OrTerminator stop(bstop,vstop);
00489
00490 LoopAlg doit(step,stop);
00491 doit.run();
00492 actcount=vstop.getCount();
00493 str<<"\n******************* TRGN Summary *******************\n";
00494 if (nostep && maxcount > 0) {
00495 str<<"TRGN: no update from GN step at TR step "<<actcount<<"\n";
00496 str<<" possibly gradient already below threshhold\n";
00497 }
00498 if (actcount > 0) {
00499 str<<"iteration count = "<<actcount<<"\n";
00500 str<<"initial objective = "<<jval0<<"\n";
00501 str<<"final objective = "<<jval<<"\n";
00502 str<<"objective redn = "<<jval/jval0<<"\n";
00503 str<<"initial gradient norm = "<<agnrm0<<"\n";
00504 str<<"gradient norm = "<<agnrm<<"\n";
00505 str<<"gradient redn = "<<rgnrm<<"\n";
00506 str<<"initial trust radius = "<<delta0<<"\n";
00507 str<<"final trust radius = "<<step.getDelta()<<"\n";
00508 }
00509 else {
00510 if (!nostep) {
00511 str<<"TRGN no initial step due to internal error\n";
00512 }
00513 }
00514 }
00515 catch (RVLException & e) {
00516 e<<"\ncalled from TRGNAlg::run\n";
00517 throw e;
00518 }
00519 }
00520
00522 int getCount() const { return actcount; }
00523
00550 TRGNAlg(Operator<Scalar> const & op,
00551 Vector<Scalar> & x,
00552 int _maxcount,
00553 atype _jtol,
00554 atype _agtol,
00555 atype _rgtol,
00556 atype _eta1,
00557 atype _eta2,
00558 atype _gamma1,
00559 atype _gamma2,
00560 atype _minstep,
00561 ostream & _str)
00562 : Policy(), opeval(op,x),
00563 jtol(_jtol),agtol(_agtol),rgtol(_rgtol),
00564 eta1(_eta1),eta2(_eta2),gamma1(_gamma1),gamma2(_gamma2),
00565 maxcount(_maxcount),minstep(_minstep),
00566 names(6),nums(6),tols(6),actcount(0),
00567 str(_str) { this->inittable(); }
00568
00573 TRGNAlg(Operator<Scalar> const & op,
00574 Vector<Scalar> & x,
00575 Table & t,
00576 ostream & _str)
00577 : opeval(op,x),
00578 jtol(getValueFromTable<atype>(t,"ResidualTol")),
00579 agtol(getValueFromTable<atype>(t,"AbsGradTol")),
00580 rgtol(getValueFromTable<atype>(t,"RelGradTol")),
00581 eta1(getValueFromTable<Scalar>(t,"MinDecrease")),
00582 eta2(getValueFromTable<Scalar>(t,"GoodDecrease")),
00583 gamma1(getValueFromTable<Scalar>(t,"StepDecrFactor")),
00584 gamma2(getValueFromTable<Scalar>(t,"StepIncrFactor")),
00585 maxcount(getValueFromTable<int>(t,"MaxItn")),
00586 minstep(getValueFromTable<int>(t,"MinStepTol")),
00587 names(6),nums(6),tols(6),actcount(0),
00588 str(_str) {
00589 this->inittable(); }
00590
00591 private:
00592 OperatorEvaluation<Scalar> opeval;
00593 mutable atype predred;
00594 mutable atype actred;
00595 mutable atype jval;
00596 atype jtol;
00597 mutable atype agnrm;
00598 mutable atype rgnrm;
00599 atype agtol;
00600 atype rgtol;
00601 atype eta1;
00602 atype eta2;
00603 atype gamma1;
00604 atype gamma2;
00605 int maxcount;
00606 atype minstep;
00607 vector<string> names;
00608 vector<atype *> nums;
00609 vector<atype> tols;
00610 mutable int actcount;
00611 ostream & str;
00612
00613 void inittable() {
00614 names[0]="LS Objective"; nums[0]=&jval; tols[0]=jtol;
00615 names[1]="Gradient Norm"; nums[1]=&agnrm; tols[1]=agtol;
00616 names[2]="Rel Grad Norm"; nums[2]=&rgnrm; tols[2]=rgtol;
00617 names[3]="Actual Redn"; nums[3]=&actred; tols[3]=-numeric_limits<atype>::max();
00618 names[4]="Predicted Redn"; nums[4]=&predred; tols[4]=ScalarFieldTraits<atype>::Zero();
00619 names[5]="Trust Radius"; nums[5]=&(this->Delta); tols[5]=ScalarFieldTraits<atype>::Zero();
00620 }
00621 };
00622 }
00623 #endif