pow.hh

Go to the documentation of this file.
00001 // cgalg.H
00002 // created by ADP
00003 // last modified 06/17/04
00004 
00005 /*************************************************************************
00006 
00007 Copyright Rice University, 2004.
00008 All rights reserved.
00009 
00010 Permission is hereby granted, free of charge, to any person obtaining a
00011 copy of this software and associated documentation files (the "Software"),
00012 to deal in the Software without restriction, including without limitation
00013 the rights to use, copy, modify, merge, publish, distribute, and/or sell
00014 copies of the Software, and to permit persons to whom the Software is
00015 furnished to do so, provided that the above copyright notice(s) and this
00016 permission notice appear in all copies of the Software and that both the
00017 above copyright notice(s) and this permission notice appear in supporting
00018 documentation.
00019 
00020 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00021 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00022 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
00023 RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
00024 NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
00025 DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00026 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00027 ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
00028 THIS SOFTWARE.
00029 
00030 Except as contained in this notice, the name of a copyright holder shall
00031 not be used in advertising or otherwise to promote the sale, use or other
00032 dealings in this Software without prior written authorization of the
00033 copyright holder.
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;         // initial guess at eigenvector on construction, current iterate else
00063     const LinearOp<Scalar> & A; // the linear op 
00064     Vector<Scalar> p;           // workspace for A * x
00065     Vector<Scalar> w;           // workspace for A^T * p
00066     AScalar & sig;              // estimated largest singular value
00067     AScalar & err;              // residual norm
00068     AScalar rq;                 // Rayleigh quotient
00069     AScalar sx;                 // workspace for 1/x.norm
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       // p <- p-rq*x
00126       p.linComb(-rq,x);
00127       // err=|p-rq*x|/|rq| \simeq |\lambda-rq|/|rq| \simeq |\lambda-rq|/|\lambda|
00128       err*=p.norm();
00129       // p <- p+rq*x - restores p = A^TAx, avoids another Vector workspace
00130       p.linComb(rq,x);
00131       // compute normalizing factor
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       // x = A^TAx / |A^TAx|
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;                        // workspace for rel residual calc
00188     PowerStep<Scalar> step;             // step alg, statically allocated
00189     std::vector<std::string> names;     // headings for report cols
00190     std::vector<AScalar *> nums;        // pointers to err, sig
00191     std::vector<AScalar> tols;          // convergence tol for err, zero for sig (inactive)
00192     int _nstep;                         // max permitted steps
00193     int it;                             // convenience store of steps taken, for tests
00194     ostream & _str;                     // output stream
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

Generated on 5 Jan 2017 for RvlUmin by  doxygen 1.4.7