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 
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,     
00095          atype _epsilon = 0.001,  
00096          atype _alpha = 1.1,      
00097          atype _lbd_est = 0.0,    
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       
00105       
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       
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); 
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           
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     
00185     LinearOp<Scalar> const & A;
00186     Vector<Scalar> & x;
00187     Vector<Scalar> const & b;
00188     atype & rnorm;
00189     atype & nrnorm;
00190     
00191     
00192     std::vector<atype> &coeff;
00193  
00194     atype gamma;           
00195     atype epsilon;         
00196     atype alpha;           
00197     atype beta;
00198     atype RQ;
00199     atype lbd_est;         
00200     atype s;
00201     int &kc;
00202     int &nrt;
00203     ostream & str;
00204     
00205     
00206     
00207     Vector<Scalar> dx;
00208     Vector<Scalar> r;
00209     Vector<Scalar> ndx;
00210     Vector<Scalar> tmp_vector;
00211       
00212     
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,     
00395         atype _epsilon = 0.001,  
00396         atype _alpha = 1.1,      
00397             atype _lbd_est=0.0,
00398         int _maxcount = 10,      
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     
00402     
00403     { x.zero();
00404       
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     
00424     atype ckm = one;
00425     atype ck = one / beta;
00426     atype ckp=0;
00427     coeff.reserve(kmax+1);   
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       
00437     }
00438       }
00439   
00440 
00441     ~ChebAlg() {}
00442 
00443     void run() { 
00444       
00445       
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       
00457       stop1.init();
00458       
00459       OrTerminator stop(stop1,stop2);
00460       
00461       LoopAlg doit(step,stop);
00462       doit.run();
00463       ktot = stop1.getCount();
00464 
00465       str<<"=========================== END Cheb ==========================\n";
00466         
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;  
00485     Vector<Scalar> & x;            
00486     Vector<Scalar> const & rhs;    
00487     atype & rnorm;                 
00488     atype & nrnorm;                
00489 
00490     
00491     std::vector<atype> coeff;
00492     atype gamma;           
00493     atype epsilon;         
00494     atype alpha;           
00495     atype lbd_est;         
00496     int maxcount;                  
00497     int nrt;                       
00498     
00499 
00502     int kmax;
00503     int kc;
00504     int ktot;
00505     ostream & str;                 
00506     ChebStep<Scalar> step;         
00507 
00508     
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;     
00544     atype epsilon;   
00545     atype alpha;     
00546     atype lbd_est;   
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