chebalg.hh

Go to the documentation of this file.
00001 // chebalg.hh
00002 // created by Yin 01/11/13
00003 // last modified 01/25/13
00004 
00005 // Much code is shamelessly stolen from the umin Cheb.H
00006 // originally written by WWS, with his permission
00007 
00008 /*************************************************************************
00009 
00010 Copyright Rice University, 2004.
00011 All rights reserved.
00012 
00013 Permission is hereby granted, free of charge, to any person obtaining a
00014 copy of this software and associated documentation files (the "Software"),
00015 to deal in the Software without restriction, including without limitation
00016 the rights to use, copy, modify, merge, publish, distribute, and/or sell
00017 copies of the Software, and to permit persons to whom the Software is
00018 furnished to do so, provided that the above copyright notice(s) and this
00019 permission notice appear in all copies of the Software and that both the
00020 above copyright notice(s) and this permission notice appear in supporting
00021 documentation.
00022 
00023 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00024 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00025 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
00026 RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
00027 NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
00028 DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00029 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00030 ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
00031 THIS SOFTWARE.
00032 
00033 Except as contained in this notice, the name of a copyright holder shall
00034 not be used in advertising or otherwise to promote the sale, use or other
00035 dealings in this Software without prior written authorization of the
00036 copyright holder.
00037 
00038 **************************************************************************/
00039 
00040 
00041 #ifndef __RVLALG_UMIN_Cheb_H
00042 #define __RVLALG_UMIN_Cheb_H
00043 
00044 #include "alg.hh"
00045 #include "terminator.hh"
00046 #include "linop.hh"
00047 #include "table.hh"
00048 
00049 using namespace RVLAlg;
00050 
00051 namespace RVLUmin {
00052 
00053   using namespace RVL;
00054   using namespace RVLAlg;    
00055 
00079   template<typename Scalar>
00080   class ChebStep : public Algorithm {
00081 
00082     typedef typename ScalarFieldTraits<Scalar>::AbsType atype;
00083 
00084   public:
00085 
00086     ChebStep(LinearOp<Scalar> const & _A,
00087          Vector<Scalar> & _x,
00088          Vector<Scalar> const & _b,
00089          atype & _rnorm, 
00090          atype & _nrnorm,
00091          std::vector<atype> &_coeff,
00092          int & _kc,
00093          int & _nrt,
00094          atype _gamma = 0.04,     // inversion level
00095          atype _epsilon = 0.001,  // error reduction
00096          atype _alpha = 1.1,      // 'fudge factor'
00097          atype _lbd_est = 0.0,    // input operator spectrum in case it is know prior
00098          ostream & _str = cout)
00099       : A(_A), x(_x), b(_b), rnorm(_rnorm), nrnorm(_nrnorm), coeff(_coeff), gamma(_gamma), epsilon(_epsilon), alpha(_alpha), lbd_est(_lbd_est),kc(_kc), nrt(_nrt), str(_str), dx(A.getDomain()), r(A.getDomain()), ndx(A.getDomain()), tmp_vector(A.getRange()), x_init(_x),dx_init(A.getDomain()),r_init(A.getDomain()),ndx_init(A.getDomain()){
00100         
00101       atype one = ScalarFieldTraits<atype>::One();
00102       atype tmp = one;
00103       nrt = 0;
00104       // NOTE: set up dx_init, r_init, ndx_int
00105       // The real step of initialization is in the run() method
00106       rnorm = b.norm();
00107       A.applyAdjOp(b,r_init);
00108       dx_init.zero();
00109       nrnorm=r_init.norm();
00110       ndx_init.zero();
00111       A.applyOp(r_init,tmp_vector);
00112       A.applyAdjOp(tmp_vector,ndx_init);
00113       //nrnorm=ndx_init.norm();
00114       
00115       tmp = abs(r_init.inner(ndx_init));
00116       if (ProtectedDivision<atype>(tmp,r_init.normsq(),RQ)) {
00117           RVLException e;
00118           e<<"Error: ChebStep::ChebStep() from ProtectedDivision: RQ\n";
00119           throw e;
00120       }
00121       if(RQ > lbd_est){
00122           lbd_est = alpha * RQ;
00123           nrt = nrt + 1;
00124       }
00125 
00126       ProtectedDivision<atype>(2*one,(one+gamma)*lbd_est,s);
00127     }
00128       
00132     void run() {
00133       try {
00134           atype one = ScalarFieldTraits<atype>::One();
00135           if (kc == 0){
00136               x.copy(x_init);
00137               r.copy(r_init);   
00138               dx.copy(dx_init);
00139               ndx.copy(ndx_init);
00140               str<<"Estimated spectrum bound at iter ["<<nrt<<"] = "<< lbd_est << endl;
00141               str << "NOTE: The  " << nrt << "-th restart\n";
00142           }
00143       
00144           atype tmp;
00145           dx.linComb(s*coeff[kc+1],r,coeff[kc+1]-one); // this = a*x+b*this
00146           
00147           x.linComb(one,dx);
00148           A.applyOp(dx,tmp_vector);
00149           A.applyAdjOp(tmp_vector,ndx);
00150           A.applyOp(x,tmp_vector);
00151           tmp_vector.linComb(-1*one,b);
00152           rnorm = tmp_vector.norm();
00153           
00154           r.linComb(-1*one,ndx);
00155           nrnorm=r.norm();
00156           //nrnorm = ndx.norm();
00157           tmp = abs(dx.inner(ndx));
00158           if (ProtectedDivision<atype>(tmp,dx.normsq(),RQ)) {
00159               RVLException e;
00160               e<<"Error: ChebStep::run() from ProtectedDivision: RQ\n";
00161               throw e;
00162           } 
00163           if(RQ > lbd_est){
00164               lbd_est = alpha * RQ;
00165               ProtectedDivision<atype>(2*one,(one+gamma)*lbd_est,s);
00166               kc = -1;
00167               nrt = nrt + 1;
00168           }
00169           kc = kc + 1;
00170       }
00171       catch (RVLException & e) {
00172     e<<"\ncalled from ChebStep::run()\n";
00173     throw e;
00174       }
00175      
00176     }
00177     
00178     atype getSpectrumBound() const { return lbd_est; }
00179 
00180     ~ChebStep() {}
00181 
00182   private:
00183 
00184     // references to external objects
00185     LinearOp<Scalar> const & A;
00186     Vector<Scalar> & x;
00187     Vector<Scalar> const & b;
00188     atype & rnorm;
00189     atype & nrnorm;
00190     
00191     // added for Chebyshev
00192     std::vector<atype> &coeff;
00193  
00194     atype gamma;           // inversion level
00195     atype epsilon;         // error reduction factor
00196     atype alpha;           // 'fudge factor'
00197     atype beta;
00198     atype RQ;
00199     atype lbd_est;         // estimated spectrum bound
00200     atype s;
00201     int &kc;
00202     int &nrt;
00203     ostream & str;
00204     // end of added
00205     
00206     // need four work vectors and one scalar as persistent object data
00207     Vector<Scalar> dx;
00208     Vector<Scalar> r;
00209     Vector<Scalar> ndx;
00210     Vector<Scalar> tmp_vector;
00211       
00212     // need vectors to store initial values for restarting purpose
00213     Vector<Scalar> x_init;
00214     Vector<Scalar> dx_init;
00215     Vector<Scalar> r_init;
00216     Vector<Scalar> ndx_init;
00217   };
00218   
00219  
00344   template<typename Scalar>
00345   class ChebAlg: public Algorithm {
00346 
00347     typedef typename ScalarFieldTraits<Scalar>::AbsType atype;
00348 
00349   public:
00350 
00389     ChebAlg(RVL::Vector<Scalar> & _x, 
00390         LinearOp<Scalar> const & _inA, 
00391         Vector<Scalar> const & _rhs, 
00392         atype & _rnorm,
00393         atype & _nrnorm,
00394         atype _gamma = 0.04,     // inversion level
00395         atype _epsilon = 0.001,  // error reduction
00396         atype _alpha = 1.1,      // 'fudge factor'
00397             atype _lbd_est=0.0,
00398         int _maxcount = 10,      // upper bound of iterations
00399         ostream & _str = cout)  
00400       : inA(_inA), x(_x), rhs(_rhs), rnorm(_rnorm), nrnorm(_nrnorm), gamma(_gamma),epsilon(_epsilon),alpha(_alpha),lbd_est(_lbd_est),maxcount(_maxcount), kmax(_maxcount), kc(0), ktot(0), str(_str), step(inA,x,rhs,rnorm,nrnorm,coeff,kc,nrt,gamma,epsilon,alpha,lbd_est,str)
00401     // NOTE: reference to coeff has been passed to ChebStep object step, however
00402     // coeff has not been initialized.
00403     { x.zero();
00404       // NOTE: estimating the necessary number of iterations
00405       atype one = ScalarFieldTraits<atype>::One();
00406       atype beta=0;
00407       atype epsest=0;
00408       ProtectedDivision<atype>(sqrt(alpha)*epsilon,one+sqrt(alpha),epsest);
00409       atype epsk;
00410       epsk= epsest + one;
00411       atype tmp = one;
00412       ProtectedDivision<atype>(one - gamma,one + gamma,beta);
00413       atype q=0;
00414       ProtectedDivision<atype>(beta,one + sqrt(one-beta*beta),q);
00415       int k = 1;
00416       while (epsk > epsest && k<=kmax) {
00417     tmp = tmp * q;
00418     ProtectedDivision<atype>(2*tmp,one + tmp*tmp,epsk);
00419       k = k + 1;
00420     }
00421     kmax = k-1;
00422     str << "NOTE: computed number of iterations needed:  " << kmax << "\n";
00423     // NOTE: compute Chebyshev coefficients
00424     atype ckm = one;
00425     atype ck = one / beta;
00426     atype ckp=0;
00427     coeff.reserve(kmax+1);   // allocate memory for coeff
00428     coeff[0] = ScalarFieldTraits<atype>::Zero();
00429     coeff[1] = one;
00430     for (int i=2; i<kmax+1; i++) {
00431       ProtectedDivision<atype>(2*ck,beta,ckp);
00432       ckp = ckp - ckm;
00433       coeff[i] = one + ckm / ckp;
00434       ckm = ck;
00435       ck = ckp;
00436       //str<<"coeff["<<i<<"] = "<< coeff[i] << endl;
00437     }
00438       }
00439   
00440 
00441     ~ChebAlg() {}
00442 
00443     void run() { 
00444       
00445       // terminator for Cheb iteration
00446       vector<string> names(2);
00447       vector<atype *> nums(2);
00448       vector<atype> tols(2);
00449       atype rnorm0=rnorm;
00450       atype nrnorm0=nrnorm;
00451       names[0]="Residual Norm"; nums[0]=&rnorm; tols[0]=ScalarFieldTraits<atype>::Zero();
00452       names[1]="Normal Residual Norm"; nums[1]=&nrnorm; tols[1]=tols[0]=ScalarFieldTraits<atype>::Zero();
00453       str<<"========================== BEGIN Cheb =========================\n";
00454       VectorCountingThresholdIterationTable<atype> stop1(maxcount,names,nums,tols,str);
00455       MaxTerminator<int> stop2(kc,kmax-1);
00456       //MaxTerminator<int> stop3(nrt,maxrt);
00457       stop1.init();
00458       // terminate if either
00459       OrTerminator stop(stop1,stop2);
00460       // loop
00461       LoopAlg doit(step,stop);
00462       doit.run();
00463       ktot = stop1.getCount();
00464 
00465       str<<"=========================== END Cheb ==========================\n";
00466         // display results
00467         str<<"\n ******* summary ********  "<<endl;
00468         str<<"initial residual norm      = "<<rnorm0<<endl;
00469         str<<"residual norm              = "<<rnorm<<endl;
00470         str<<"residual redn              = "<<rnorm/rnorm0<<endl;
00471         str<<"initial gradient norm      = "<<nrnorm0<<endl;
00472         str<<"gradient norm              = "<<nrnorm<<endl;
00473         str<<"gradient redn              = "<<nrnorm/nrnorm0<<endl;
00474     }
00475 
00476     int getCount() const { return kc; }
00477     int getTotalCount() const { return ktot; }
00478     int getRestartCount() const { return nrt+1; }
00479     atype getSpectrumBound() const { return step.getSpectrumBound(); }
00480 
00481 
00482   private:
00483 
00484     LinearOp<Scalar> const & inA;  // operator
00485     Vector<Scalar> & x;            // state - solution vector
00486     Vector<Scalar> const & rhs;    // reference to rhs
00487     atype & rnorm;                 // residual norm
00488     atype & nrnorm;                // gradient norm
00489 
00490     // added for Chebyshev
00491     std::vector<atype> coeff;
00492     atype gamma;           // inversion level
00493     atype epsilon;         // error reduction factor
00494     atype alpha;           // 'fudge factor'
00495     atype lbd_est;         // spectrum bound of op
00496     int maxcount;                  // upper bound for iteration count
00497     int nrt;                       // upper bound for restarting
00498     // end of added 
00499 
00502     int kmax;
00503     int kc;
00504     int ktot;
00505     ostream & str;                 // stream for report output
00506     ChebStep<Scalar> step;         // single step of Cheb
00507 
00508     // disable default, copy constructors
00509     ChebAlg();
00510     ChebAlg(ChebAlg<Scalar> const &);
00511 
00512   };
00513 
00535   template<typename Scalar>
00536   class ChebPolicyData {
00537     
00538     typedef typename ScalarFieldTraits<Scalar>::AbsType atype;
00539     
00540   public:
00541     
00542     int maxcount;
00543     atype gamma;     // inversion level
00544     atype epsilon;   // error reduction
00545     atype alpha;     // 'fudge factor'
00546     atype lbd_est;   // estimated spectrum bound
00547     bool verbose;
00548     
00549     ChebPolicyData(atype _gamma = 0.04,
00550            atype _epsilon = 0.01,
00551            atype _alpha = 1.001,
00552            atype _lbd_est = 0.0,
00553            int _maxcount = 0,
00554            bool _verbose = false)
00555       : maxcount(_maxcount), gamma(_gamma), epsilon(_epsilon), alpha(_alpha),lbd_est(_lbd_est),verbose(_verbose) {}
00556     
00557     ChebPolicyData(ChebPolicyData<Scalar> const & a)
00558       : maxcount(a.maxcount), gamma(a.gamma), epsilon(a.epsilon), alpha(a.alpha), lbd_est(a.lbd_est), verbose(a.verbose) {}
00559       
00560     ostream & write(ostream & str) const {
00561           str<<"\n";
00562           str<<"==============================================\n";
00563           str<<"ChebPolicyData: \n";
00564           str<<"gamma     = "<<gamma<<"\n";
00565           str<<"epsilon   = "<<epsilon<<"\n";
00566           str<<"alpha     = "<<alpha<<"\n";
00567           str<<"lbd_est   = "<<lbd_est<<"\n";
00568           str<<"maxcount  = "<<maxcount<<"\n";
00569           str<<"verbose   = "<<verbose<<"\n";
00570           str<<"==============================================\n";
00571           return str;
00572       }
00573     
00574   };
00575   
00576   template<typename Scalar> 
00577   class ChebPolicy {
00578 
00579     typedef typename ScalarFieldTraits<Scalar>::AbsType atype;
00580 
00581   public:
00601     ChebAlg<Scalar> * build(Vector<Scalar> & x, 
00602                 LinearOp<Scalar> const & A,
00603                 Vector<Scalar> const & d,
00604                 atype & rnorm,
00605                 atype & nrnorm,
00606                 ostream & str) const {
00607         if (verbose)
00608       return new ChebAlg<Scalar>(x, A, d,rnorm,nrnorm,gamma,epsilon,alpha,lbd_est,maxcount,str);
00609         else
00610       return new ChebAlg<Scalar>(x, A, d,rnorm,nrnorm,gamma,epsilon,alpha,lbd_est,maxcount,nullstr);
00611     }
00612 
00618     void assign(atype _rtol, atype _nrtol, atype _gamma, atype _epsilon, atype _alpha, atype _lbd_est, int _maxcount, bool _verbose) {
00619         gamma = _gamma; epsilon=_epsilon; alpha=_alpha; lbd_est=_lbd_est; maxcount=_maxcount; verbose=_verbose;
00620     }
00621 
00623     void assign(Table const & t) {
00624       gamma=getValueFromTable<atype>(t,"Cheb_gamma");
00625       epsilon=getValueFromTable<atype>(t,"Cheb_epsilon");
00626       alpha=getValueFromTable<atype>(t,"Cheb_alpha");
00627       lbd_est=getValueFromTable<atype>(t,"Cheb_lbd_est");
00628       maxcount=getValueFromTable<int>(t,"Cheb_MaxItn");
00629       verbose=getValueFromTable<bool>(t,"Cheb_Verbose");
00630     }
00631 
00633     void assign(ChebPolicyData<Scalar> const & s) {
00634       gamma=s.gamma;
00635       epsilon=s.epsilon;
00636       alpha=s.alpha;
00637       lbd_est=s.lbd_est;
00638       maxcount=s.maxcount;
00639       verbose=s.verbose;
00640     }
00641 
00650     ChebPolicy(atype _gamma = 0.04,
00651                atype _epsilon = 0.01,
00652                atype _alpha = 1.001,
00653                atype _lbd_est = 0.0,
00654            int _maxcount = 0,
00655             bool _verbose = true)
00656       : gamma(_gamma), epsilon(_epsilon), alpha(_alpha), lbd_est(_lbd_est),maxcount(_maxcount), verbose(_verbose), nullstr(0){}
00657       
00658     ChebPolicy(ChebPolicy<Scalar> const & p)
00659       : gamma(p.gamma),
00660     epsilon(p.epsilon),
00661     alpha(p.alpha),
00662     lbd_est(p.lbd_est),
00663     maxcount(p.maxcount),
00664     verbose(p.verbose),
00665     nullstr(0) {}
00666       
00667   private:
00668     mutable atype gamma;
00669     mutable atype epsilon;
00670     mutable atype alpha;
00671     mutable atype lbd_est;
00672     mutable int maxcount;
00673     mutable bool verbose;
00674     mutable std::ostream nullstr;
00675   };
00676 }
00677 
00678 #endif
00679 
00680 
00681 
00682 
00683 
00684 
00685 
00686 
00687 

Generated on 5 Jan 2017 for RvlUmin by  doxygen 1.4.7