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_POWALG
00038 #define __RVL_POWALG
00039 
00040 #include "alg.hh"
00041 #include "linop.hh"
00042 #include "ioterm.hh";
00043 
00044 namespace RVLUmin {
00045 
00046   using namespace RVL;
00047   using namespace RVLAlg;
00048 
00055   template <class Scalar>
00056   class PowerStep: public Algorithm {
00057 
00058     typedef typename ScalarFieldTraits<Scalar>::AbsType AScalar;
00059 
00060   private:
00061 
00062     Vector<Scalar> & x;         
00063     const LinearOp<Scalar> & A; 
00064     Vector<Scalar> p;           
00065     Vector<Scalar> w;           
00066     AScalar & sig;              
00067     AScalar & err;              
00068     AScalar rq;                 
00069     AScalar sx;                 
00070 
00071     PowerStep();
00072     PowerStep(PowerStep< Vector<Scalar> > const &);
00073 
00074   public:
00075   
00082     PowerStep( RVL::Vector<Scalar> & _x, const LinearOp<Scalar> & _A,
00083          AScalar & _sig, AScalar & _err )
00084       : x(_x), 
00085     A(_A), 
00086     p(A.getDomain()), 
00087     w(A.getRange()),
00088     sig(_sig),
00089     err(_err),
00090     sx(ScalarFieldTraits<AScalar>::One())
00091     {     
00092       AScalar one = ScalarFieldTraits<AScalar>::One();
00093       AScalar sx = one;
00094       if (ProtectedDivision<AScalar>(one,x.norm(),sx)) {
00095     RVLException e;
00096     e<<"Error: RVLUmin::PowerStep::constructor\n";
00097     e<<"zerodivide\n";
00098     throw e;
00099       }
00100       x.scale(sx);
00101     }
00102 
00106     void run() {
00107 
00108       try {
00109     AScalar one = ScalarFieldTraits<AScalar>::One();
00110     A.applyOp(x,w);
00111     rq = w.normsq();
00112     if (rq < ScalarFieldTraits<AScalar>::Zero()) {
00113       RVLException e;
00114       e<<"Error: PowerMethod::run\n";
00115       e<<"computed apparently negative Rayleigh quotient\n";
00116       throw e;
00117     }
00118     sig=sqrt(rq);
00119     if (ProtectedDivision<AScalar>(one,rq,err)) {
00120       sig=ScalarFieldTraits<AScalar>::Zero();
00121       err=ScalarFieldTraits<AScalar>::One();
00122     }
00123     else {
00124       A.applyAdjOp(w,p);
00125       
00126       p.linComb(-rq,x);
00127       
00128       err*=p.norm();
00129       
00130       p.linComb(rq,x);
00131       
00132       if (ProtectedDivision<AScalar>(one,p.norm(),sx)) {
00133         RVLException e;
00134         e<<"Error: RVLUmin::PowerStep::run\n";
00135         e<<"zerodivide\n";
00136         throw e;
00137       }
00138       
00139       x.scale(sx,p);
00140     }
00141       }
00142 
00143       catch (RVLException & e) {
00144     e<<"\ncalled from PowerStep::run\n";
00145     throw e;
00146       }
00147     }
00148   };
00149 
00180   template<typename Scalar>
00181   class PowerMethod: public Algorithm {
00182 
00183     typedef typename ScalarFieldTraits<Scalar>::AbsType AScalar;
00184 
00185   private:
00186 
00187     AScalar err;                        
00188     PowerStep<Scalar> step;             
00189     std::vector<std::string> names;     
00190     std::vector<AScalar *> nums;        
00191     std::vector<AScalar> tols;          
00192     int _nstep;                         
00193     int it;                             
00194     ostream & _str;                     
00195 
00196   public:
00197     
00206     PowerMethod(Vector<Scalar> & x,
00207         AScalar & sig,
00208         LinearOp<Scalar> const & A,
00209         int nstep, AScalar tol, ostream & str) 
00210       : err(ScalarFieldTraits<AScalar>::One()),
00211     step(x,A,sig,err),_nstep(nstep),_str(str),
00212     names(2),nums(2),tols(2), it(0) {
00213       names[0]="Relative Residual"; nums[0]=&err; tols[0]=tol;
00214       names[1]="Est Singular Value"; nums[1]=&sig; tols[1]=ScalarFieldTraits<AScalar>::Zero();
00215     }
00216     
00217     void run() {
00218       try {
00219     VectorCountingThresholdIterationTable<Scalar> term(_nstep,names, nums, tols,_str);
00220     term.init();
00221     LoopAlg l(step,term);
00222     l.run();
00223     it=term.getCount();
00224       }
00225       catch (RVLException & e) {
00226     e<<"\ncalled from PowerMethod::run\n";
00227     throw e;
00228       }
00229     }
00230     
00231     int getCount() { return it; }
00232   };
00233 
00234 }
00235 
00236 #endif