ls.hh

Go to the documentation of this file.
00001 /*************************************************************************
00002 
00003 Copyright Rice University, 2004, 2005, 2006
00004 All rights reserved.
00005 
00006 Permission is hereby granted, free of charge, to any person obtaining a
00007 copy of this software and associated documentation files (the "Software"),
00008 to deal in the Software without restriction, including without limitation
00009 the rights to use, copy, modify, merge, publish, distribute, and/or sell
00010 copies of the Software, and to permit persons to whom the Software is
00011 furnished to do so, provided that the above copyright notice(s) and this
00012 permission notice appear in all copies of the Software and that both the
00013 above copyright notice(s) and this permission notice appear in supporting
00014 documentation.
00015 
00016 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
00019 RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
00020 NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
00021 DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00022 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00023 ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
00024 THIS SOFTWARE.
00025 
00026 Except as contained in this notice, the name of a copyright holder shall
00027 not be used in advertising or otherwise to promote the sale, use or other
00028 dealings in this Software without prior written authorization of the
00029 copyright holder.
00030 
00031 **************************************************************************/
00032 #ifndef __LS
00033 #define __LS
00034 
00035 #include "op.hh"
00036 #include "functional.hh"
00037 
00038 namespace RVL {
00039 
00040   /*template<class Scalar>
00041   class StdLeastSquaresFcnlGN;
00042   
00043   template<class Scalar>
00044   class RegLeastSquaresFcnlGN;
00045 
00046   template<class Scalar>
00047   class RegPriorLeastSquaresFcnlGN;
00048   */
00049 
00051   template<class Scalar>
00052   class ShiftOperator: public Operator<Scalar> {
00053 
00054   private:
00055 
00056     const Vector<Scalar> & d;
00057     // disabled
00058     ShiftOperator();
00059 
00060   protected:
00061 
00062     void apply(const Vector<Scalar> & x, 
00063            Vector<Scalar> & y) const {
00064       try {
00065     y.copy(x);
00066     y.linComb(-1.0,d);
00067       }
00068       catch (RVLException & e) {
00069     e<<"\ncalled from ShiftOperator::apply\n";
00070     throw e;
00071       }
00072     }
00073   
00074     void applyDeriv(const Vector<Scalar> & x, 
00075             const Vector<Scalar> & dx,
00076             Vector<Scalar> & dy) const {
00077       try {
00078     dy.copy(dx);
00079       }
00080       catch (RVLException & e) {
00081     e<<"\ncalled from ShiftOperator::applyDeriv\n";
00082     throw e;
00083       }
00084     }
00085 
00086     void applyAdjDeriv(const Vector<Scalar> & x, 
00087                const Vector<Scalar> & dy,
00088                Vector<Scalar> & dx) const {
00089       try {
00090     dx.copy(dy);
00091       }
00092       catch (RVLException & e) {
00093     e<<"\ncalled from ShiftOperator::applyAdjDeriv\n";
00094     throw e;
00095       }
00096     }
00097   
00098     // permits override
00099     virtual Operator<Scalar> * clone() const {
00100       return new ShiftOperator<Scalar>(*this);
00101     }
00102   
00103   public:
00105     ShiftOperator(const Vector<Scalar> & dd): d(dd) {}
00106     ShiftOperator(const ShiftOperator<Scalar> & a): d(a.d) {}
00107     ~ShiftOperator() {}
00108 
00110     const Space<Scalar> & getDomain() const { return d.getSpace(); }
00111     const Space<Scalar> & getRange() const { return d.getSpace(); }
00112 
00113     ostream & write(ostream & str) const {
00114       str<<"Shift Operator"<<"\n";
00115       str<<"*** shift vector\n";
00116       d.write(str);
00117       return str;
00118     }
00119   };
00120 
00123   template<class Scalar>
00124   class ResidualOperator: public Operator<Scalar> {
00125 
00126   private:
00127 
00128     Vector<Scalar> const & d;
00129     Operator<Scalar> const & G;
00130     // disabled
00131     ResidualOperator();
00132 
00133   protected:
00134 
00135     void apply(const Vector<Scalar> & x, 
00136            Vector<Scalar> & y) const {
00137       try {
00138     this->export_apply(G,x,y);
00139     y.linComb(-1.0,d);
00140       }
00141       catch (RVLException & e) {
00142     e<<"\ncalled from ResidualOperator::apply\n";
00143     throw e;
00144       }
00145     }
00146   
00147     void applyDeriv(const Vector<Scalar> & x, 
00148             const Vector<Scalar> & dx,
00149             Vector<Scalar> & dy) const {
00150       try {
00151     this->export_applyDeriv(G,x,dx,dy);
00152       }
00153       catch (RVLException & e) {
00154     e<<"\ncalled from ResidualOperator::applyDeriv\n";
00155     throw e;
00156       }
00157     }
00158 
00159     void applyAdjDeriv(const Vector<Scalar> & x, 
00160                const Vector<Scalar> & dy,
00161                Vector<Scalar> & dx) const {
00162       try {
00163     this->export_applyAdjDeriv(G,x,dy,dx);
00164       }
00165       catch (RVLException & e) {
00166     e<<"\ncalled from ResidualOperator::applyAdjDeriv\n";
00167     throw e;
00168       }
00169     }
00170   
00171     // permits override
00172     virtual Operator<Scalar> * clone() const {
00173       return new ResidualOperator<Scalar>(*this);
00174     }
00175   
00176   public:
00178     ResidualOperator(Operator<Scalar> const & GG,
00179              Vector<Scalar> const & dd): d(dd), G(GG) {
00180       if (G.getRange() != d.getSpace()) {
00181     RVLException e;
00182     e<<"Error: ResidualOperator constructor\n";
00183     e<<"input vector not in range of operator\n";
00184     e<<"input vector:\n";
00185     d.write(e);
00186     e<<"operator:\n";
00187     G.write(e);
00188     throw e;
00189       }
00190     }
00191       ResidualOperator(ResidualOperator<Scalar> const & a): d(a.d), G(a.G) {}
00192     ~ResidualOperator() {}
00193 
00195     const Space<Scalar> & getDomain() const { return G.getDomain(); }
00196     const Space<Scalar> & getRange() const { return G.getRange(); }
00197 
00198     Scalar getMaxStep(const Vector<Scalar> & x,
00199               const Vector<Scalar> & dx) const {
00200       return G.getMaxStep(x,dx);
00201     }
00202 
00203     ostream & write(ostream & str) const {
00204       str<<"Residual Operator"<<"\n";
00205       str<<"*** data vector:\n";
00206       d.write(str);
00207       str<<"*** operator:\n";
00208       G.write(str);
00209       return str;
00210     }
00211   };
00212 
00222   template<class Scalar>
00223   class EuclideanForm: public Functional<Scalar> {
00224 
00225   private:
00226 
00227     const Space<Scalar> & sp;
00228     EuclideanForm();
00229 
00230   protected: 
00231 
00232     void apply(const Vector<Scalar> & x,
00233            Scalar & val) const {
00234       try {
00235     if (sp != x.getSpace()) {
00236       RVLException e;
00237       e<<"Error: EuclideanForm::apply\n";
00238       e<<"input vector not in domain\n";
00239       throw e;
00240     }
00241     val = 0.5*x.inner(x);
00242       }
00243       catch(RVLException & e) {
00244     e<<"\ncalled from EuclideanForm::apply\n";
00245     throw e;
00246       }
00247     }
00248 
00249     void applyGradient(const Vector<Scalar> & x,
00250                Vector<Scalar> & g) const {
00251       try {
00252     if (sp != x.getSpace()) {
00253       RVLException e;
00254       e<<"Error: EuclideanForm::applyGradient\n";
00255       e<<"input vector not in domain\n";
00256       throw e;
00257     }
00258     g.copy(x);
00259       }
00260       catch(RVLException & e) {
00261     e<<"\ncalled from EuclideanForm::applyGradient\n";
00262     throw e;
00263       }
00264     }
00265 
00266     void applyHessian(const Vector<Scalar> & x,
00267               const Vector<Scalar> & delx,
00268               Vector<Scalar> & dely) const {
00269       try {
00270     if (sp != delx.getSpace()) {
00271       RVLException e;
00272       e<<"Error: EuclideanForm::applyHessian\n";
00273       e<<"input vector not in domain\n";
00274       throw e;
00275     }
00276     dely.copy(delx);
00277       }
00278       catch (RVLException & e) {
00279     e<<"\ncalled from EuclideanForm::applyGradient\n";
00280     throw e;
00281       }
00282     }
00283 
00284     // permits override
00285     virtual Functional<Scalar> * clone() const { 
00286       return new EuclideanForm<Scalar>(*this); 
00287     }
00288 
00289   public:
00290 
00291     EuclideanForm(const Space<Scalar> & _sp): sp(_sp) { testRealOnly<Scalar>(); }
00292     EuclideanForm(const EuclideanForm<Scalar> & q): sp(q.sp) { testRealOnly<Scalar>(); }
00293     ~EuclideanForm() {}
00294 
00295     // access to domain
00296     const Space<Scalar> & getDomain() const { return sp; }
00297 
00298     ostream & write(ostream & str) const {
00299       str<<"Euclidean quadratic form - length squared\n";
00300       return str;
00301     }
00302   };
00303 
00313   template<class Scalar>
00314   class QuadraticForm: public Functional<Scalar> {
00315 
00316   private:
00317 
00318     const LinearOp<Scalar> & A;
00319     mutable Vector<Scalar> r;
00320     mutable bool applied;
00321 
00322     QuadraticForm();
00323 
00324   protected: 
00325 
00326     void apply(const Vector<Scalar> & x,
00327            Scalar & val) const {
00328       try {
00329     if (!applied) {
00330       A.applyOp(x,r);
00331       applied = true;
00332     }
00333     val =  0.5*r.normsq();;
00334       }
00335       catch(RVLException & e) {
00336     e<<"\ncalled from QuadraticForm::apply\n";
00337     throw e;
00338       }
00339     }
00340 
00341     void applyGradient(const Vector<Scalar> & x,
00342                Vector<Scalar> & g) const {
00343       try {
00344     if (!applied) {
00345       A.applyOp(x,r);
00346       applied = true;
00347     }
00348     A.applyAdjOp(r,g);
00349       }
00350       catch(RVLException & e) {
00351     e<<"\ncalled from QuadraticForm::applyGradient\n";
00352     throw e;
00353       }
00354     }
00355 
00356     void applyHessian(const Vector<Scalar> & x,
00357               const Vector<Scalar> & delx,
00358               Vector<Scalar> & dely) const {
00359       try {
00360     Vector<Scalar> z(A.getRange());
00361     A.applyOp(delx,z);
00362     A.applyAdjOp(z,dely);
00363       }
00364       catch (RVLException & e) {
00365     e<<"\ncalled from QuadraticForm::applyGradient\n";
00366     throw e;
00367       }
00368     }
00369 
00370     // permits override
00371     virtual Functional<Scalar> * clone() const { 
00372       return new QuadraticForm<Scalar>(*this); 
00373     }
00374 
00375   public:
00376 
00377     QuadraticForm(const LinearOp<Scalar> & AA)
00378       : A(AA), r(A.getDomain()), applied(false) { testRealOnly<Scalar>(); }
00379 
00380     QuadraticForm(const QuadraticForm<Scalar> & q)
00381       : A(q.A), r(A.getDomain()), applied(false) { testRealOnly<Scalar>(); }
00382         
00383     ~QuadraticForm() {}
00384 
00385     const Space<Scalar> & getDomain() const { return A.getDomain(); }
00386 
00387     ostream & write(ostream & str) const {
00388       str<<"Quadratic form with operator\n";
00389       A.write(str);
00390       return str;
00391     }
00392   };
00393 
00403   template<class Scalar>
00404   class ShiftedQuadraticForm: public Functional<Scalar> {
00405 
00406   private:
00407 
00408     const LinearOp<Scalar> & A;
00409     const Vector<Scalar> & b;
00410     mutable Vector<Scalar> r;
00411     mutable bool applied;
00412 
00413     ShiftedQuadraticForm();
00414 
00415   protected: 
00416 
00417     void apply(const Vector<Scalar> & x,
00418            Scalar & val) const {
00419       try {
00420     if (!applied) {
00421       A.applyOp(x,r);
00422       r.linComb(-1.0,b);
00423       applied = true;
00424     }
00425     val = 0.5*r.normsq();
00426       }
00427       catch(RVLException & e) {
00428     e<<"\ncalled from QuadraticForm::apply\n";
00429     throw e;
00430       }
00431     }
00432 
00433     void applyGradient(const Vector<Scalar> & x,
00434                Vector<Scalar> & g) const {
00435       try {
00436     if (!applied) {
00437       A.applyOp(x,r);
00438       r.linComb(-1.0,b);
00439       applied = true;
00440     }
00441     A.applyAdjOp(r,g);
00442       }
00443       catch(RVLException & e) {
00444     e<<"\ncalled from QuadraticForm::applyGradient\n";
00445     throw e;
00446       }
00447     }
00448 
00449     void applyHessian(const Vector<Scalar> & x,
00450               const Vector<Scalar> & delx,
00451               Vector<Scalar> & dely) const {
00452       try {
00453     Vector<Scalar> z(A.getRange());
00454     A.applyOp(delx,z);
00455     A.applyAdjOp(z,dely);
00456       }
00457       catch (RVLException & e) {
00458     e<<"\ncalled from QuadraticForm::applyGradient\n";
00459     throw e;
00460       }
00461     }
00462 
00463     // permits override
00464     virtual Functional<Scalar> * clone() const { 
00465       return new ShiftedQuadraticForm<Scalar>(*this); 
00466     }
00467 
00468   public:
00469 
00470     ShiftedQuadraticForm(const LinearOp<Scalar> & AA,
00471              const Vector<Scalar> & bb)
00472       : A(AA), b(bb), r(A.getRange()), applied(false) { testRealOnly<Scalar>(); }
00473 
00474     ShiftedQuadraticForm(const ShiftedQuadraticForm<Scalar> & q)
00475       : A(q.A), b(q.b), r(A.getRange()), applied(false) { testRealOnly<Scalar>(); }
00476         
00477     ~ShiftedQuadraticForm() { }
00478 
00479     const Space<Scalar> & getDomain() const { return A.getDomain(); }
00480 
00481     ostream & write(ostream & str) const {
00482       str<<"ShiftedQuadratic form with linear operator\n";
00483       A.write(str);
00484       str<<"and shift vector\n";
00485       b.write(str);
00486       return str;
00487     }
00488   };
00489 
00507   template<class Scalar>
00508   class LeastSquaresFcnlGN: public Functional<Scalar> {
00509 
00510   private:
00511 
00512     EuclideanForm<Scalar> sql;
00513     FcnlOpComp<Scalar> work;
00514 
00515     // default constructor--disabled
00516     LeastSquaresFcnlGN();
00517 
00518   protected:
00519     
00520     void apply(Vector<Scalar> const & x,
00521            Scalar & val) const {
00522       try {
00523     this->export_apply(work,x,val);
00524       }
00525       catch (RVLException e) {
00526     e<<"\ncalled from LeastSquaresFcnlGN::apply\n";
00527     throw e;
00528       }
00529     }
00530     void applyGradient(Vector<Scalar> const & x,
00531                Vector<Scalar> & g) const {
00532       try {
00533     this->export_applyGradient(work,x,g);
00534       }
00535       catch (RVLException e) {
00536     e<<"\ncalled from LeastSquaresFcnlGN::applyGradient\n";
00537     throw e;
00538       }
00539     }
00540     void applyHessian(Vector<Scalar> const & x,
00541               Vector<Scalar> const & dx,
00542               Vector<Scalar> & dy) const {
00543       try {
00544     this->export_applyHessian(work,x,dx,dy);
00545       }
00546       catch (RVLException e) {
00547     e<<"\ncalled from LeastSquaresFcnlGN::applyHessian\n";
00548     throw e;
00549       }
00550     }
00551 
00552     virtual Functional<Scalar> * clone() const { 
00553       return new LeastSquaresFcnlGN<Scalar>(*this); 
00554     }
00555 
00556   public:  
00557   
00559     LeastSquaresFcnlGN(Operator<Scalar> const & op)
00560       : sql(op.getRange()), work(sql,op) {
00561       testRealOnly<Scalar>(); 
00562     }
00564     LeastSquaresFcnlGN(const LeastSquaresFcnlGN<Scalar> & J)
00565       : sql(J.sql), work(J.work) { testRealOnly<Scalar>(); }
00566   
00567     // Destructor.
00568     virtual ~LeastSquaresFcnlGN() {}
00569 
00570     Space<Scalar> const & getDomain() const { return work.getDomain(); }
00571  
00572     Scalar getMaxStep(const Vector<Scalar> & x,
00573               const Vector<Scalar> & dx) const {
00574       try {
00575     return work.getMaxStep(x,dx);
00576       }
00577       catch (RVLException & e) {
00578     e<<"\ncalled from LeastSquaresFcnlGN::getMaxStep\n";
00579     throw e;
00580       }
00581     }
00582     
00583     ostream & write(ostream & str) const {
00584       str<<"Least-Squares Gauss-Newton functional: expressed as = \n";
00585       work.write(str);
00586       return str;
00587     }
00588   };
00589 
00607   template<class Scalar>
00608   class StdLeastSquaresFcnlGN: public Functional<Scalar> {
00609 
00610   private:
00611 
00612     // Internal variables
00613     EuclideanForm<Scalar> sql;
00614     ResidualOperator<Scalar> res;
00615     FcnlOpComp<Scalar> work;
00616 
00617     // default constructor--disabled
00618     StdLeastSquaresFcnlGN();
00619 
00620   protected:
00621     
00622     void apply(Vector<Scalar> const & x,
00623            Scalar & val) const {
00624       try {
00625     this->export_apply(work,x,val);
00626       }
00627       catch (RVLException e) {
00628     e<<"\ncalled from StdLeastSquaresFcnlGN::apply\n";
00629     throw e;
00630       }
00631     }
00632     void applyGradient(Vector<Scalar> const & x,
00633                Vector<Scalar> & g) const {
00634       try {
00635     this->export_applyGradient(work,x,g);
00636       }
00637       catch (RVLException e) {
00638     e<<"\ncalled from StdLeastSquaresFcnlGN::applyGradient\n";
00639     throw e;
00640       }
00641     }
00642     void applyHessian(Vector<Scalar> const & x,
00643               Vector<Scalar> const & dx,
00644               Vector<Scalar> & dy) const {
00645       try {
00646     this->export_applyHessian(work,x,dx,dy);
00647       }
00648       catch (RVLException e) {
00649     e<<"\ncalled from StdLeastSquaresFcnlGN::applyHessian\n";
00650     throw e;
00651       }
00652     }
00653 
00654     virtual Functional<Scalar> * clone() const { 
00655       return new StdLeastSquaresFcnlGN<Scalar>(*this); 
00656     }
00657   
00658   public:  
00659   
00661     StdLeastSquaresFcnlGN(Operator<Scalar> const & oper, 
00662               Vector<Scalar> const & d)
00663       : sql(oper.getRange()), 
00664     res(oper,d),
00665         work(sql,res) {
00666       testRealOnly<Scalar>(); 
00667     }
00668 
00670     StdLeastSquaresFcnlGN(const StdLeastSquaresFcnlGN<Scalar> & JJ)
00671       : sql(JJ.sql), 
00672     res(JJ.res), 
00673     work(JJ.work) {
00674       testRealOnly<Scalar>();
00675     }
00676   
00677     // Destructor.
00678     virtual ~StdLeastSquaresFcnlGN() {}
00679 
00680     Space<Scalar> const & getDomain() const { return work.getDomain(); }
00681  
00682     Scalar getMaxStep(const Vector<Scalar> & x,
00683               const Vector<Scalar> & dx) const {
00684       try {
00685     return res.getMaxStep(x,dx);
00686       }
00687       catch (RVLException & e) {
00688     e<<"\ncalled from StdLeastSquaresFcnlGN::getMaxStep\n";
00689     throw e;
00690       }
00691     }
00692 
00693     ostream & write(ostream & str) const {
00694       str<<"Standard Least-Squares Gauss-Newton functional\n";
00695       str<<"based on ResidualOperator\n";
00696       res.write(str);
00697       return str;
00698     }
00699   };
00700 
00722   template<class Scalar>
00723   class RegLeastSquaresFcnlGN: public Functional<Scalar> {
00724 
00725   private:
00726 
00727     // default constructor--disabled
00728     RegLeastSquaresFcnlGN();
00729     StdLeastSquaresFcnlGN<Scalar> f1;
00730     ShiftedQuadraticForm<Scalar> f2;
00731     Scalar lambda;
00732     LinCombFunctional<Scalar> work;
00733 
00734   protected:
00735 
00736     void apply(Vector<Scalar> const & x,
00737            Scalar & val) const {
00738       try {
00739     this->export_apply(work,x,val);
00740       }
00741       catch (RVLException e) {
00742     e<<"\ncalled from RegLeastSquaresFcnlGN::apply\n";
00743     throw e;
00744       }
00745     }
00746     void applyGradient(Vector<Scalar> const & x,
00747                Vector<Scalar> & g) const {
00748       try {
00749     this->export_applyGradient(work,x,g);
00750       }
00751       catch (RVLException e) {
00752     e<<"\ncalled from RegLeastSquaresFcnlGN::applyGradient\n";
00753     throw e;
00754       }
00755     }
00756     void applyHessian(Vector<Scalar> const & x,
00757               Vector<Scalar> const & dx,
00758               Vector<Scalar> & dy) const {
00759       try {
00760     this->export_applyHessian(work,x,dx,dy);
00761       }
00762       catch (RVLException e) {
00763     e<<"\ncalled from RegLeastSquaresFcnlGN::applyHessian\n";
00764     throw e;
00765       }
00766     }
00767 
00768     virtual Functional<Scalar> * clone() const { 
00769       return new RegLeastSquaresFcnlGN<Scalar>(*this); 
00770     }
00771 
00772   public:  
00773   
00775     RegLeastSquaresFcnlGN(Operator<Scalar> const & oper, 
00776               LinearOp<Scalar> const & reg,
00777               Vector<Scalar> const & d,
00778               Vector<Scalar> const & r0,
00779               Scalar lam)
00780       : f1(oper,d), f2(reg,r0), lambda(lam), work(1.0,f1,lam,f2) {
00781       try {
00782     testRealOnly<Scalar>(); 
00783       }
00784       catch (RVLException & e) {
00785     e<<"\ncalled from RegLeastSquaresFcnlGN constructor\n";
00786     throw e;
00787       }
00788     }
00789 
00791     RegLeastSquaresFcnlGN(const RegLeastSquaresFcnlGN<Scalar> & rls)
00792       : f1(rls.f1), f2(rls.f2), lambda(rls.lambda), work(rls.work) { 
00793       testRealOnly<Scalar>(); 
00794     }
00795   
00796     // Destructor.
00797     virtual ~RegLeastSquaresFcnlGN() {}
00798 
00799     Space<Scalar> const & getDomain() const { return work.getDomain(); }
00800 
00801     ostream & write(ostream & str) const {
00802       str<<"Regularized Least-Squares Gauss-Newton functional. realized as\n";
00803       work.write(str);
00804       return str;
00805     }
00806   };
00807 
00808     
00809     
00810     
00817   template<typename Scalar>
00818   class FunctionalBd: public Functional<Scalar> {
00819 
00820   private:
00821 
00822     //    Functional<Scalar> const & f;
00823     Functional<Scalar> * f;
00824     RVL::Oracle<Vector<Scalar> > const & b;
00825 
00826   protected:
00827 
00828     void apply(const Vector<Scalar> & x, 
00829            Scalar & val) const {
00830       try {
00831     val=numeric_limits<Scalar>::max();
00832     if (!b.isFeasible(x)) return;
00833     RVL::Functional<Scalar>::export_apply(*f,x,val);
00834       }
00835       catch (RVLException & e) {
00836     val=numeric_limits<Scalar>::max();
00837       }
00838     }
00839 
00840     void applyGradient(const Vector<Scalar> & x, 
00841                Vector<Scalar> & g) const {
00842       try {
00843     if (!b.isFeasible(x)) {
00844       RVLException e;
00845       e<<"Error: FuncionalBd::applyGradient\n";
00846       e<<"infeasible point\n";
00847       throw e;
00848     }
00849     RVL::Functional<Scalar>::export_applyGradient(*f,x,g);
00850       }
00851       catch (RVLException & e) {
00852     e<<"\ncalled from FunctionalBd::applyGradient\n";
00853     throw e;
00854       }
00855     }
00856 
00857     void applyHessian(const Vector<Scalar> & x,
00858               const Vector<Scalar> & dx, 
00859               Vector<Scalar> & dy) const {
00860       try {
00861     if (!b.isFeasible(x)) {
00862       RVLException e;
00863       e<<"Error: FuncionalBd::applyHessian\n";
00864       e<<"infeasible point\n";
00865       throw e;
00866     }
00867     RVL::Functional<Scalar>::export_applyHessian(*f,x,dx,dy);
00868       }
00869       catch (RVLException & e) {
00870     e<<"\ncalled from FunctionalBd::applyHessian\n";
00871     throw e;
00872       }
00873       
00874     }
00875     
00876     // permits override
00877     virtual Functional<Scalar> * clone() const { 
00878       return new FunctionalBd(*this); 
00879     }
00880     
00881   public:
00882     
00883     FunctionalBd(Functional<Scalar> const & _f,
00884          RVL::Oracle<Vector<Scalar> > const & _b) 
00885       : f(NULL), b(_b) { testRealOnly<Scalar>(); this->export_clone(_f,&f); }
00886 
00887     FunctionalBd(FunctionalBd<Scalar> const & a)
00888       : f(NULL), b(a.b) { testRealOnly<Scalar>(); this->export_clone(*(a.f),&f); }
00889 
00890     ~FunctionalBd() { if (f) delete f; }
00891 
00892     Space<Scalar> const & getDomain() const { return f->getDomain(); }
00893     Scalar getMaxStep(Vector<Scalar> const & x, 
00894               Vector<Scalar> const & dx) const { 
00895       return f->getMaxStep(x,dx);
00896     }
00897 
00898     Functional<Scalar> const & getFunctional() const { return *f; }
00899 
00900     ostream & write(ostream & str) const {
00901       str<<"FunctionalBd: functional returning infty at infeasible points\n";
00902       str<<"data member Functional:\n";
00903       f->write(str);
00904       str<<"bounds test:\n";
00905       b.write(str);
00906       return str;
00907     }
00908 
00909   };
00910 
00914   template<typename Scalar>
00915   class ULBoundsTest: public RVL::Oracle<Vector<Scalar> > {
00916     
00917   private: 
00918     Vector<Scalar> const & ub;
00919     Vector<Scalar> const & lb;
00920     FunctionObjectScalarRedn<Scalar> & minfo;
00921 
00922   public:
00923 
00924     ULBoundsTest(Vector<Scalar> const & _lb,
00925          Vector<Scalar> const & _ub,
00926          FunctionObjectScalarRedn<Scalar> & _minfo)
00927       : ub(_ub), lb(_lb), minfo(_minfo) {
00928       testRealOnly<Scalar>(); 
00929       if (lb.getSpace() != ub.getSpace()) {
00930     RVLException e;
00931     e<<"Error: ULBoundsTest constructor\n";
00932     e<<"upper, lower bound Vectors not in same Space\n";
00933     e<<"lower bd vector:\n";
00934     lb.write(e);
00935     e<<"upper bd vector:\n";
00936     ub.write(e);
00937     throw e;
00938       }
00939       minfo.setValue();
00940     }
00941 
00942     ULBoundsTest(ULBoundsTest<Scalar> const & t)
00943       : lb(t.lb), ub(t.ub), minfo(t.minfo) {
00944       testRealOnly<Scalar>(); 
00945       minfo.setValue();
00946     }       
00947 
00948     ~ULBoundsTest() {}
00949 
00950     bool isFeasible(Vector<Scalar> const & x) const {
00951       // this function should be called only once per x, so
00952       // allocate workspace locally
00953       try {
00954     if (x.getSpace() != lb.getSpace()) return false; 
00955     Vector<Scalar> work(x.getSpace());
00956     Components<Scalar> cwork(work);
00957     // test for bound violation, return false if found
00958     float one = ScalarFieldTraits<float>::One();
00959     float zip = ScalarFieldTraits<float>::Zero();
00960     int size = cwork.getSize();
00961     float valmin = zip;
00962     minfo.setValue(zip);
00963     work.copy(x);
00964     work.linComb(one,ub,-one);
00965     for(int i=0; i< size; i++) {
00966       cwork[i].eval(minfo);
00967       // cerr<<"min(ub - x)["<<i<<"] ="<<minfo.getValue()<<endl;
00968       if (minfo.getValue() < valmin)
00969         valmin = minfo.getValue();
00970     }
00971     // cerr<<"min(ub - x) = valmin ="<<valmin<<endl;
00972     work.copy(x);
00973     work.linComb(-one,lb);
00974     for(int i=0; i<size; i++){
00975       cwork[i].eval(minfo);
00976       // cerr<<"min(ub - x, x - lb)["<<i<<"]="<<minfo.getValue()<<endl;
00977       if (minfo.getValue() < valmin)
00978         valmin = minfo.getValue();
00979     }
00980     // cerr<<"min(ub - x, x - lb) = valmin ="<<valmin<<endl;
00981     if (valmin<zip) return false;
00982     // passed all tests
00983     return true;
00984       }
00985       catch (RVLException & e) {
00986     return false;
00987       }
00988     }
00989 
00990     ostream & write(ostream & str) const {
00991       str<<"Standard upper/lower bounds test\n";
00992       str<<"Lower bound vector:\n";
00993       lb.write(str);
00994       str<<"upper bound vector:\n";
00995       ub.write(str);
00996       str<<"min function:\n";
00997       minfo.write(str);
00998       return str;
00999     }
01000   };
01001 }
01002 #endif

Generated on 5 Jan 2017 for RVL by  doxygen 1.4.7