TRGNAlg.hh

Go to the documentation of this file.
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       //cerr<<"TRGNStep::run\n";
00084       // run then delete solver - first check whether trust region was
00085       // transgressed
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       // test for nontrivial step - failure is fatal
00096       if (p.norm()<minstep*pol.Delta) {
00097     nostep=true;
00098     return;
00099       }
00100 
00101       // here rnorm is final residual from TRLS solver
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       //cerr<<"TRGNStep: predred="<<predred<<endl;
00107       // provisionally update eval point - save current point in case 
00108       // need to revert
00109       Vector<Scalar> & x = opeval.getPoint();
00110       xsave.copy(x);
00111       x.linComb(-ScalarFieldTraits<Scalar>::One(),p);
00112       // reset (reconstruct) solver
00113       //cerr<<"TRGNStep::run - main callg before call to pol.build Delta="<<pol.Delta<<endl;
00114       //      solver = pol.build(p,opeval.getDeriv(),opeval.getValue(),rnorm,nrnorm,str);   
00115       // by convention this should have recalculated the objective
00116       // function, gradient norm
00117       //      jval = 0.5*rnorm*rnorm;
00118       jval = 0.5*opeval.getValue().normsq();
00119 
00120       // compute actual reduction
00121       actred = jvalsave - jval;
00122       // Case 1: fail to satisfy G-A : rescind eval point update, shrink Delta
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       // Case 2: otherwise keep update
00129       // Case 2.1: only grow Delta if step hit TR boundary
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       // save last update vector
00139       plast.copy(p);
00140       // stretch it
00141       p.scale(gamma2);
00142       // stretch TR
00143       pol.Delta *= gamma2; 
00144       str<<"last TR = "<<deltalast<<" new TR = "<<pol.Delta<<"\n";
00145       // restore x
00146       x.copy(xsave);
00147       // compute DF(x)p - x not updated
00148       Vector<Scalar> dp(opeval.getRange());
00149       opeval.getDeriv().applyOp(p,dp);
00150       // create quadratic residual
00151       dp.linComb(-ScalarFieldTraits<Scalar>::One(),opeval.getValue());
00152       // estimate reduction - note jvalsave is resid at xsave
00153       predred = jvalsave - 0.5*dp.normsq();
00154       str<<"new predred="<<predred<<"\n";
00155       // update x
00156       x.linComb(-ScalarFieldTraits<Scalar>::One(),p);
00157       // create real residual
00158       jval = 0.5*opeval.getValue().normsq();
00159       str<<"last jval = "<<jvalsave<<" new jval = "<<jval<<"\n";
00160       // compute actual reduction
00161       actred = jvalsave - jval;
00162       str<<"new actred = "<<actred<<"\n";
00163       // if G-A fails, back off
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       // rejigger everything for the new point
00187       solver = pol.build(p,opeval.getDeriv(),opeval.getValue(),rnorm,nrnorm,str);         
00188       agnrm=nrnorm;
00189       rgnrm=nrnorm*gnrmrecip;
00190 
00191       //cerr<<"at end of TRGNStep::run - Delta = "<<pol.Delta<<endl;
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       //cerr<<"TRGNStep:: construction\n";
00256       // sanity test params
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       // no step taken yet so set reductions to zero
00274       actred = ScalarFieldTraits<atype>::Zero();
00275       predred = ScalarFieldTraits<atype>::Zero();
00276 
00277       //cerr<<"TRGNStep -> Solver construction via policy\n";
00278       // initial solver assignment
00279       solver = pol.build(p,opeval.getDeriv(),opeval.getValue(),rnorm,nrnorm,str);
00280       //cerr<<"TRGNStep -> return from Solver construction\n";
00281       // solver policy: least squares solution of Ax=b. 
00282       // pass b=opeval.getValue, A=opeval.getDeriv references - cause reinitialization if needed
00283       // on creation, initialize x=0, r=b, rnorm=b.norm, nrnorm=A^Tb.norm 
00284       jval = 0.5*rnorm*rnorm;
00285       agnrm = nrnorm;
00286 
00287       // record initial reciprocal grad norm for future ref
00288       if (ProtectedDivision<atype>(ScalarFieldTraits<atype>::One(),nrnorm,gnrmrecip)) {
00289     // reset grad norms to zero
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       // don't touch initial Delta
00301       //cerr<<"Exit TRGNStep constructor\n";
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     // workspace for solver
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       //cerr<<"TRGNAlg::run\n";
00477       try {
00478     bool nostep = false;
00479     //cerr<<"TRGNAlg->TRGNStep constructor\n";
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     //cerr<<"TRGNAlg->LoopAlg\n";
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

Generated on 5 Jan 2017 for RvlUmin by  doxygen 1.4.7