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_CGNE_H
00042 #define __RVLALG_UMIN_CGNE_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
00056
00057 template<typename Scalar>
00058 class CGNEAlg;
00059
00083 template<typename Scalar>
00084 class CGNEStep : public Algorithm {
00085
00086 friend class CGNEAlg<Scalar>;
00087
00088 typedef typename ScalarFieldTraits<Scalar>::AbsType atype;
00089
00090 public:
00091
00092 CGNEStep(LinearOp<Scalar> const & _A,
00093 Vector<Scalar> & _x,
00094 Vector<Scalar> const & _b,
00095 atype & _rnorm,
00096 atype & _nrnorm)
00097 : A(_A), x(_x), b(_b), rnorm(_rnorm), nrnorm(_nrnorm), r(A.getRange()), g(A.getDomain()),
00098 q(A.getRange()), p(A.getDomain()) {
00099
00100
00101 r.copy(b);
00102 rnorm=r.norm();
00103 A.applyAdjOp(r,g);
00104 p.copy(g);
00105 nrnorm=g.norm();
00106 gamma = nrnorm*nrnorm;
00107 }
00108
00112 void run() {
00113 try {
00114
00115 A.applyOp(p,q);
00116
00117 atype qtq = q.normsq();
00118 atype absalpha;
00119 if (ProtectedDivision<atype>(gamma,qtq,absalpha)) {
00120 RVLException e;
00121 e<<"Error: CGNEStep::run() from ProtectedDivision: alpha\n";
00122 throw e;
00123 }
00124
00125
00126
00127
00128 Scalar alpha=absalpha;
00129 x.linComb(alpha,p);
00130 r.linComb(-alpha,q);
00131
00132
00133 A.applyAdjOp(r,g);
00134
00135
00136 atype newgamma = g.normsq();
00137 atype absbeta;
00138 if (ProtectedDivision<atype>(newgamma,gamma,absbeta)) {
00139 RVLException e;
00140 e<<"Error: CGNEStep::run() from ProtectedDivision: beta\n";
00141 throw e;
00142 }
00143
00144
00145 Scalar beta = absbeta;
00146 p.linComb(ScalarFieldTraits<Scalar>::One(),g,beta);
00147 gamma=newgamma;
00148 rnorm=r.norm();
00149 nrnorm=sqrt(gamma);
00150
00151
00152 }
00153 catch (RVLException & e) {
00154 e<<"\ncalled from CGNEStep::run()\n";
00155 throw e;
00156 }
00157
00158 }
00159
00160 ~CGNEStep() {}
00161
00162 protected:
00163
00164
00165 LinearOp<Scalar> const & A;
00166 Vector<Scalar> & x;
00167 Vector<Scalar> const & b;
00168 atype & rnorm;
00169 atype & nrnorm;
00170
00171 private:
00172
00173
00174 Vector<Scalar> r;
00175 Vector<Scalar> g;
00176 Vector<Scalar> q;
00177 Vector<Scalar> p;
00178 atype gamma;
00179 };
00180
00204 template<typename Scalar>
00205 class PCGNEStep : public Algorithm {
00206
00207 friend class CGNEAlg<Scalar>;
00208
00209 typedef typename ScalarFieldTraits<Scalar>::AbsType atype;
00210
00211 public:
00212
00213 PCGNEStep(LinearOp<Scalar> const & _A,
00214 LinearOp<Scalar> const & _M,
00215 Vector<Scalar> & _x,
00216 Vector<Scalar> const & _b,
00217 atype & _rnorm,
00218 atype & _nrnorm)
00219 : A(_A), M(_M), x(_x), b(_b), rnorm(_rnorm), nrnorm(_nrnorm),
00220 r(A.getRange()), ng(A.getDomain()), g(A.getDomain()),
00221 q(A.getRange()), p(A.getDomain()) {
00222
00223
00224 if ((M.getDomain() != A.getDomain()) ||
00225 (M.getRange() != A.getDomain())) {
00226 RVLException e;
00227 e<<"Error PCGNEStep constructor\n";
00228 e<<" preconditioning operator does not have domain, range\n";
00229 e<<" same as domain of system operator\n";
00230 e<<" preconditioning operator:\n";
00231 M.write(e);
00232 e<<" system operator:\n";
00233 A.write(e);
00234 throw e;
00235 }
00236
00237 r.copy(b);
00238 rnorm=r.norm();
00239 A.applyAdjOp(r,ng);
00240 M.applyOp(ng,g);
00241 p.copy(g);
00242 gamma = abs(g.inner(ng));
00243 nrnorm=sqrt(gamma);
00244 }
00245
00249 void run() {
00250 try {
00251 A.applyOp(p,q);
00252 atype qtq = q.normsq();
00253 atype absalpha;
00254 if (ProtectedDivision<atype>(gamma,qtq,absalpha)) {
00255 RVLException e;
00256 e<<"Error: PCGNEStep::run() from ProtectedDivision: alpha\n";
00257 throw e;
00258 }
00259
00260
00261
00262 Scalar alpha=absalpha;
00263 x.linComb(alpha,p);
00264 r.linComb(-alpha,q);
00265
00266 A.applyAdjOp(r,ng);
00267 M.applyOp(ng,g);
00268
00269 atype newgamma = abs(g.inner(ng));
00270 atype absbeta;
00271 if (ProtectedDivision<atype>(newgamma,gamma,absbeta)) {
00272 RVLException e;
00273 e<<"Error: PCGNEStep::run() from ProtectedDivision: beta\n";
00274 throw e;
00275 }
00276
00277 Scalar beta = absbeta;
00278 p.linComb(ScalarFieldTraits<Scalar>::One(),g,beta);
00279 gamma=newgamma;
00280 rnorm=r.norm();
00281 nrnorm=sqrt(gamma);
00282 }
00283 catch (RVLException & e) {
00284 e<<"\ncalled from PCGNEStep::run()\n";
00285 throw e;
00286 }
00287
00288 }
00289
00290 ~PCGNEStep() {}
00291
00292 protected:
00293
00294
00295 LinearOp<Scalar> const & A;
00296 LinearOp<Scalar> const & M;
00297 Vector<Scalar> & x;
00298 Vector<Scalar> const & b;
00299 atype & rnorm;
00300 atype & nrnorm;
00301
00302 private:
00303
00304
00305 Vector<Scalar> r;
00306 Vector<Scalar> ng;
00307 Vector<Scalar> g;
00308 Vector<Scalar> q;
00309 Vector<Scalar> p;
00310 atype gamma;
00311 };
00312
00377 template<typename Scalar>
00378 class CGNEAlg: public Algorithm, public Terminator {
00379
00380 typedef typename ScalarFieldTraits<Scalar>::AbsType atype;
00381
00382 public:
00383
00423 CGNEAlg(RVL::Vector<Scalar> & x,
00424 RVL::LinearOp<Scalar> const & A,
00425 RVL::Vector<Scalar> const & rhs,
00426 atype & _rnorm,
00427 atype & _nrnorm,
00428 atype _rtol = 100.0*numeric_limits<atype>::epsilon(),
00429 atype _nrtol = 100.0*numeric_limits<atype>::epsilon(),
00430 int _maxcount = 10,
00431 atype _maxstep = numeric_limits<atype>::max(),
00432 ostream & _str = cout)
00433 : rnorm(_rnorm),
00434 nrnorm(_nrnorm),
00435 rtol(_rtol),
00436 nrtol(_nrtol),
00437 maxstep(_maxstep),
00438 maxcount(_maxcount),
00439 count(0),
00440 proj(false),
00441 str(_str)
00442 {
00443 try {
00444 x.zero();
00445 step = new CGNEStep<Scalar>(A,x,rhs,rnorm,nrnorm);
00446 }
00447 catch (RVLException & e) {
00448 e<<"\ncalled from CGNEAlg constructor (not preconditioned)\n";
00449 throw e;
00450 }
00451 }
00452
00497 CGNEAlg(RVL::Vector<Scalar> & x,
00498 LinearOp<Scalar> const & A,
00499 LinearOp<Scalar> const & M,
00500 Vector<Scalar> const & rhs,
00501 atype & _rnorm,
00502 atype & _nrnorm,
00503 atype _rtol = 100.0*numeric_limits<atype>::epsilon(),
00504 atype _nrtol = 100.0*numeric_limits<atype>::epsilon(),
00505 int _maxcount = 10,
00506 atype _maxstep = numeric_limits<atype>::max(),
00507 ostream & _str = cout)
00508 : rnorm(_rnorm),
00509 nrnorm(_nrnorm),
00510 rtol(_rtol),
00511 nrtol(_nrtol),
00512 maxstep(_maxstep),
00513 maxcount(_maxcount),
00514 count(0),
00515 proj(false),
00516 str(_str)
00517 {
00518 try {
00519 x.zero();
00520 step = new PCGNEStep<Scalar>(A,M,x,rhs,rnorm,nrnorm);
00521 }
00522 catch (RVLException & e) {
00523 e<<"\ncalled from CGNEAlg constructor (preconditioned)\n";
00524 throw e;
00525 }
00526 }
00527
00528 ~CGNEAlg() {
00529 delete step;
00530 }
00531
00532 bool query() { return proj; }
00533
00534 void run() {
00535 try {
00536
00537
00538 CGNEStep<Scalar> * cg = dynamic_cast<CGNEStep<Scalar> *>(step);
00539 PCGNEStep<Scalar> * pcg = dynamic_cast<PCGNEStep<Scalar> *>(step);
00540 if ((!cg && !pcg) || (cg && pcg)) {
00541 RVLException e;
00542 e<<"Error: CGNEAlg::run\n";
00543 e<<" unable to determine whether step data member\n";
00544 e<<" is preconditioned or not. PANIC!\n";
00545 throw e;
00546 }
00547
00548
00549 vector<string> names(2);
00550 vector<atype *> nums(2);
00551 vector<atype> tols(2);
00552 atype rnorm0=rnorm;
00553 atype nrnorm0=nrnorm;
00554
00555 names[0]="Residual Norm"; nums[0]=&rnorm; tols[0]=rtol*rnorm0;
00556 names[1]="Gradient Norm"; nums[1]=&nrnorm; tols[1]=nrtol*nrnorm0;
00557 if (pcg) str<<"========================== BEGIN PCGNE =========================\n";
00558 else str<<"========================== BEGIN CGNE =========================\n";
00559 VectorCountingThresholdIterationTable<atype> stop1(maxcount,names,nums,tols,str);
00560 stop1.init();
00561
00562
00563
00564 Terminator * stop2 = NULL;
00565 if (cg) stop2 = new BallProjTerminator<Scalar>( cg->x,maxstep,str);
00566 if (pcg) stop2 = new BallProjTerminator<Scalar>(pcg->x,maxstep,str);
00567
00568 OrTerminator stop(stop1,*stop2);
00569
00570 LoopAlg doit(*step,stop);
00571
00572
00573 doit.run();
00574
00575
00576 proj = stop2->query();
00577 if (proj) {
00578 if (cg) {
00579
00580 Vector<Scalar> temp((cg->A).getRange());
00581 (cg->A).applyOp((cg->x),temp);
00582 temp.linComb(-1.0,(cg->b));
00583 rnorm=temp.norm();
00584 Vector<Scalar> temp1((cg->A).getDomain());
00585 (cg->A).applyAdjOp(temp,temp1);
00586 nrnorm=temp1.norm();
00587 }
00588 if (pcg) {
00589 Vector<Scalar> temp((pcg->A).getRange());
00590 (pcg->A).applyOp((pcg->x),temp);
00591 temp.linComb(-1.0,(pcg->b));
00592 rnorm=temp.norm();
00593 Vector<Scalar> temp1((pcg->A).getDomain());
00594 Vector<Scalar> temp2((pcg->A).getDomain());
00595 (pcg->A).applyAdjOp(temp,temp1);
00596 (pcg->M).applyOp(temp1,temp2);
00597 atype tmpgamma = abs(temp1.inner(temp2));
00598 nrnorm=sqrt(tmpgamma);
00599 }
00600 }
00601
00602 count = stop1.getCount();
00603 if (pcg) str<<"=========================== END PCGNE ==========================\n";
00604 else str<<"=========================== END CGNE ==========================\n";
00605
00606 str<<"\n ****************** CGNE summary ***************** "<<endl;
00607 str<<"initial residual norm = "<<rnorm0<<endl;
00608 str<<"residual norm = "<<rnorm<<endl;
00609 str<<"residual redn = "<<rnorm/rnorm0<<endl;
00610 str<<"initial gradient norm = "<<nrnorm0<<endl;
00611 str<<"gradient norm = "<<nrnorm<<endl;
00612 str<<"gradient redn = "<<nrnorm/nrnorm0<<endl;
00613 }
00614 catch (RVLException & e) {
00615 e<<"\ncalled from CGNEAlg::run\n";
00616 throw e;
00617 }
00618 }
00619
00620 int getCount() const { return count; }
00621
00622 private:
00623
00624 atype & rnorm;
00625 atype & nrnorm;
00626 atype rtol;
00627 atype nrtol;
00628 atype maxstep;
00629 int maxcount;
00630 int count;
00631 mutable bool proj;
00632 ostream & str;
00633 Algorithm * step;
00634
00635
00636 CGNEAlg();
00637 CGNEAlg(CGNEAlg<Scalar> const &);
00638
00639 };
00640
00643 template<typename Scalar>
00644 class CGNEPolicyData {
00645
00646 typedef typename ScalarFieldTraits<Scalar>::AbsType atype;
00647
00648 public:
00649
00650 atype rtol;
00651 atype nrtol;
00652 atype Delta;
00653 int maxcount;
00654 bool verbose;
00655
00656 CGNEPolicyData(atype _rtol = numeric_limits<atype>::max(),
00657 atype _nrtol = numeric_limits<atype>::max(),
00658 atype _Delta = numeric_limits<atype>::max(),
00659 int _maxcount = 0,
00660 bool _verbose = false)
00661 : rtol(_rtol), nrtol(_nrtol), Delta(_Delta), maxcount(_maxcount), verbose(_verbose) {}
00662
00663 CGNEPolicyData(CGNEPolicyData<Scalar> const & a)
00664 : rtol(a.rtol), nrtol(a.nrtol), Delta(a.Delta), maxcount(a.maxcount), verbose(a.verbose) {}
00665
00666 ostream & write(ostream & str) const {
00667 str<<"\n";
00668 str<<"==============================================\n";
00669 str<<"CGNEPolicyData: \n";
00670 str<<"rtol = "<<rtol<<"\n";
00671 str<<"nrtol = "<<nrtol<<"\n";
00672 str<<"Delta = "<<Delta<<"\n";
00673 str<<"maxcount = "<<maxcount<<"\n";
00674 str<<"verbose = "<<verbose<<"\n";
00675 str<<"==============================================\n";
00676 return str;
00677 }
00678 };
00679
00702 template<typename Scalar>
00703 class CGNEPolicy {
00704
00705 typedef typename ScalarFieldTraits<Scalar>::AbsType atype;
00706
00707 public:
00727 CGNEAlg<Scalar> * build(Vector<Scalar> & x,
00728 LinearOp<Scalar> const & A,
00729 Vector<Scalar> const & d,
00730 atype & rnorm,
00731 atype & nrnorm,
00732 ostream & str) const {
00733 try {
00734 if (verbose)
00735 return new CGNEAlg<Scalar>(x,A,d,rnorm,nrnorm,rtol,nrtol,maxcount,Delta,str);
00736 else
00737 return new CGNEAlg<Scalar>(x,A,d,rnorm,nrnorm,rtol,nrtol,maxcount,Delta,nullstr);
00738 }
00739 catch (RVLException & e) {
00740 e<<"\ncalled from CGNEPolicy::build\n";
00741 e<<"inputs: \n";
00742 e<<"**** x:\n";
00743 x.write(e);
00744 e<<"**** A:\n";
00745 A.write(e);
00746 e<<"**** d:\n";
00747 d.write(e);
00748 throw e;
00749 }
00750 }
00751
00752
00753 CGNEAlg<Scalar> * build(Vector<Scalar> & x,
00754 LinearOp<Scalar> const & A,
00755 LinearOp<Scalar> const & M,
00756 Vector<Scalar> const & d,
00757 atype & rnorm,
00758 atype & nrnorm,
00759 ostream & str) const {
00760 try {
00761 if (verbose)
00762 return new CGNEAlg<Scalar>(x,A,M,d,rnorm,nrnorm,rtol,nrtol,maxcount,Delta,str);
00763 else
00764 return new CGNEAlg<Scalar>(x,A,M,d,rnorm,nrnorm,rtol,nrtol,maxcount,Delta,nullstr);
00765 }
00766 catch (RVLException & e) {
00767 e<<"\ncalled from CGNEPolicy::build\n";
00768 e<<"inputs: \n";
00769 e<<"**** x:\n";
00770 x.write(e);
00771 e<<"**** A:\n";
00772 A.write(e);
00773 e<<"**** d:\n";
00774 d.write(e);
00775 throw e;
00776 }
00777 }
00778
00784 void assign(atype _rtol, atype _nrtol, atype _Delta, int _maxcount, bool _verbose) {
00785 rtol=_rtol; nrtol=_nrtol; Delta=_Delta; maxcount=_maxcount; verbose=_verbose;
00786 }
00787
00789 void assign(Table const & t) {
00790 rtol=getValueFromTable<atype>(t,"CGNE_ResTol");
00791 nrtol=getValueFromTable<atype>(t,"CGNE_GradTol");
00792 Delta=getValueFromTable<atype>(t,"TR_Delta");
00793 maxcount=getValueFromTable<int>(t,"CGNE_MaxItn");
00794 verbose=getValueFromTable<bool>(t,"CGNE_Verbose");
00795 }
00796
00798 void assign(CGNEPolicyData<Scalar> const & s) {
00799 rtol=s.rtol;
00800 nrtol=s.nrtol;
00801 Delta=s.Delta;
00802 maxcount=s.maxcount;
00803 verbose=s.verbose;
00804 }
00805
00810 mutable atype Delta;
00811
00820 CGNEPolicy(atype _rtol = numeric_limits<atype>::max(),
00821 atype _nrtol = numeric_limits<atype>::max(),
00822 atype _Delta = numeric_limits<atype>::max(),
00823 int _maxcount = 0,
00824 bool _verbose = true)
00825 : Delta(_Delta), rtol(_rtol), nrtol(_nrtol), maxcount(_maxcount), verbose(_verbose), nullstr(0) {}
00826
00827 CGNEPolicy(CGNEPolicy<Scalar> const & p)
00828 : Delta(p.Delta),
00829 rtol(p.rtol),
00830 nrtol(p.nrtol),
00831 maxcount(p.maxcount),
00832 verbose(p.verbose),
00833 nullstr(0) {}
00834
00835 private:
00836 mutable atype rtol;
00837 mutable atype nrtol;
00838 mutable int maxcount;
00839 mutable bool verbose;
00840 mutable std::ostream nullstr;
00841 };
00842 }
00843
00844 #endif
00845
00846
00847
00848
00849
00850
00851
00852
00853