logistic.hh

Go to the documentation of this file.
00001 /*************************************************************************
00002 
00003 Copyright Rice University, 2004 - 2015.
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 
00033 #ifndef __RVL_VLOp
00034 #define __RVL_VLOp
00035 
00036 #include "space.hh"
00037 
00038 namespace RVL {
00039 
00056   template<class Scalar>
00057   class RVLScalarLogistic: public BinaryLocalFunctionObject<Scalar> {
00058   private:
00059     Scalar s;
00060     Scalar m;
00061     RVLScalarLogistic(const RVLScalarLogistic<Scalar> &) {}
00062   public:
00063     RVLScalarLogistic(Scalar fmin=ScalarFieldTraits<Scalar>::Zero(),
00064               Scalar fmax=ScalarFieldTraits<Scalar>::One()) {
00065       try {
00066     testRealOnly<Scalar>();
00067     if (!(fmin<fmax)) {
00068       RVLException e;
00069       e<<"ERROR: RVLScalarLogistic constructor\n";
00070       e<<"fmin="<<fmin<<" not less than fmax="<<fmax<<"\n";
00071       throw e;
00072     }
00073     s = 2.0 /(fmax-fmin);
00074     m = 0.5 *(fmax+fmin);
00075       }
00076       catch (RVLException & e) {
00077     e<<"\ncalled from RVLScalarLogistic constructor\n";
00078     throw e;
00079       }
00080     }
00081     ~RVLScalarLogistic() {}
00082   
00088     using RVL::BinaryLocalEvaluation<Scalar>::operator();
00089     void operator()(LocalDataContainer<Scalar> & x,
00090             LocalDataContainer<Scalar> const & y) {
00091       if (x.getSize() != y.getSize()) {
00092     RVLException e; e<<"ERROR: RVLScalarLogistic\n";
00093     e<<"input size = "<<x.getSize()<<" output size = "<<y.getSize()<<"\n";
00094     e<<"required to be same\n";
00095     throw e;
00096       }
00097       else {
00098     size_t n = x.getSize();
00099     Scalar * px = x.getData();
00100     Scalar const * py = y.getData();
00101     for (size_t i=0;i<n;i++) {
00102       px[i]=m + py[i]/sqrt(1.0 + s*s*py[i]*py[i]);
00103     }
00104       }
00105     }
00106     string getName() const  { return "RVLScalarLogistic"; }
00107   };
00108 
00120   template<class Scalar>
00121   class RVLScalarLogisticInverse: public BinaryLocalFunctionObject<Scalar> {
00122   private:
00123     Scalar s;
00124     Scalar m;
00125     RVLScalarLogisticInverse(const RVLScalarLogisticInverse<Scalar> &) {}
00126   public:
00127     RVLScalarLogisticInverse(Scalar fmin=ScalarFieldTraits<Scalar>::Zero(),
00128                  Scalar fmax=ScalarFieldTraits<Scalar>::One()) {
00129       try {
00130     testRealOnly<Scalar>();
00131     if (!(fmin<fmax)) {
00132       RVLException e;
00133       e<<"ERROR: RVLScalarLogisticInverse constructor\n";
00134       e<<"fmin="<<fmin<<" not less than fmax="<<fmax<<"\n";
00135       throw e;
00136     }
00137     s = 2.0 /(fmax-fmin);
00138     m = 0.5 *(fmax+fmin);
00139       }
00140       catch (RVLException & e) {
00141     e<<"\ncalled from RVLScalarLogisticInverse constructor\n";
00142     throw e;
00143       }
00144     }
00145     ~RVLScalarLogisticInverse() {}
00146   
00152     using RVL::BinaryLocalEvaluation<Scalar>::operator();
00153     void operator()(LocalDataContainer<Scalar> & x,
00154             LocalDataContainer<Scalar> const & y) {
00155       if (x.getSize() != y.getSize()) {
00156     RVLException e; e<<"ERROR: RVLScalarLogisticInverse\n";
00157     e<<"input size = "<<x.getSize()<<" output size = "<<y.getSize()<<"\n";
00158     e<<"required to be same\n";
00159     throw e;
00160       }
00161       else {
00162     size_t n = x.getSize();
00163     Scalar * px = x.getData();
00164     Scalar const * py = y.getData();
00165     for (size_t i=0;i<n;i++) {
00166       if ((py[i] < m-1/s + numeric_limits<Scalar>::epsilon()) || 
00167           (py[i] > m+1/s - numeric_limits<Scalar>::epsilon())) {
00168         RVLException e;
00169         e<<"ERROR: RVLScalarLogisticInverse\n";
00170         e<<"input value = "<<py[i]<<" too close to \n";
00171         e<<"fmin = "<<m-1/s<<" or fmax = "<<m+1/s<<"\n";
00172         throw e;
00173       }
00174       px[i]=(py[i]-m)/sqrt(1.0 - s*s*(py[i]-m)*(py[i]-m));
00175     }
00176       }
00177     }
00178     string getName() const  { return "RVLScalarLogisticInverse"; }
00179   };
00180 
00195   template<class Scalar>
00196   class RVLScalarLogisticDeriv: public TernaryLocalFunctionObject<Scalar> {
00197   private:
00198     Scalar s;
00199     Scalar t;
00200     RVLScalarLogisticDeriv(const RVLScalarLogisticDeriv<Scalar> &) {}
00201   public:
00202     RVLScalarLogisticDeriv(Scalar fmin=ScalarFieldTraits<Scalar>::Zero(),
00203                Scalar fmax=ScalarFieldTraits<Scalar>::One()) {
00204       try {
00205     testRealOnly<Scalar>();
00206     if (!(fmin<fmax)) {
00207       RVLException e;
00208       e<<"ERROR: RVLScalarLogisticDeriv constructor\n";
00209       e<<"fmin="<<fmin<<" not less than fmax="<<fmax<<"\n";
00210       throw e;
00211     }
00212     s = 2.0 /(fmax-fmin);
00213       }
00214       catch (RVLException & e) {
00215     e<<"\ncalled from RVLScalarLogisticDeriv constructor\n";
00216     throw e;
00217       }
00218     }
00219     ~RVLScalarLogisticDeriv() {}
00220   
00226     using RVL::TernaryLocalEvaluation<Scalar>::operator();
00227     void operator()(LocalDataContainer<Scalar> & x,
00228             LocalDataContainer<Scalar> const & y, 
00229             LocalDataContainer<Scalar> const & dy) {
00230       if ((x.getSize() != y.getSize()) ||
00231       (x.getSize() != dy.getSize())) {
00232     RVLException e; e<<"ERROR: RVLScalarLogisticDeriv\n";
00233     e<<"input size = "<<y.getSize()<<"\n";
00234     e<<"input pert size = "<<dy.getSize()<<"\n";
00235     e<<"output size = "<<x.getSize()<<"\n";
00236     e<<"required to be same\n";
00237     throw e;
00238       }
00239       else {
00240     size_t n = x.getSize();
00241     Scalar * px = x.getData();
00242     Scalar const * py = y.getData();
00243     Scalar const * pdy = dy.getData();
00244     for (size_t i=0;i<n;i++) {
00245       t=1.0/sqrt(1.0 + s*s*py[i]*py[i]);
00246       px[i]=pdy[i]*t*t*t;
00247     }
00248       }
00249     }
00250     string getName() const  { return "RVLScalarLogisticDeriv"; }
00251   };
00252 
00271   template<class Scalar>
00272   class RVLVectorLogistic: public QuaternaryLocalFunctionObject<Scalar> {
00273   private:
00274     RVLVectorLogistic(const RVLVectorLogistic<Scalar> &) {}
00275   public:
00276     RVLVectorLogistic() {
00277       try {
00278     testRealOnly<Scalar>();
00279       }
00280       catch (RVLException & e) {
00281     e<<"\ncalled from RVLVectorLogistic constructor\n";
00282     throw e;
00283       }
00284     }
00285     ~RVLVectorLogistic() {}
00286   
00292     using RVL::QuaternaryLocalEvaluation<Scalar>::operator();
00293     void operator()(LocalDataContainer<Scalar> & x,
00294             LocalDataContainer<Scalar> const & y,
00295             LocalDataContainer<Scalar> const & lb,
00296             LocalDataContainer<Scalar> const & ub) {
00297       if ((x.getSize() != y.getSize()) ||
00298       (x.getSize() != lb.getSize()) ||
00299       (x.getSize() != ub.getSize())) {
00300     RVLException e; e<<"ERROR: RVLVectorLogistic\n";
00301     e<<"input size = "<<x.getSize()<<"\n";
00302     e<<"output size = "<<y.getSize()<<"\n";
00303     e<<"lb size = "<<lb.getSize()<<"\n";
00304     e<<"ub size = "<<ub.getSize()<<"\n";
00305     e<<"required to be same\n";
00306     throw e;
00307       }
00308       else {
00309     size_t n = x.getSize();
00310     Scalar * px = x.getData();
00311     Scalar const * py = y.getData();
00312     Scalar const * fmin = lb.getData();
00313     Scalar const * fmax = ub.getData();
00314     for (size_t i=0;i<n;i++) {
00315       if (!(fmin[i]<fmax[i])) {
00316         RVLException e;
00317         e<<"ERROR: RVLVectorLogistic::operator()\n";
00318         e<<"array index = "<<i<<"\n";
00319         e<<"fmin="<<fmin[i]<<" not less than fmax="<<fmax[i]<<"\n";
00320         throw e;
00321       }
00322       Scalar s = 2.0/(fmax[i]-fmin[i]);
00323       Scalar m = 0.5 *(fmax[i]+fmin[i]);
00324       px[i]=m + py[i]/sqrt(1.0 + s*s*py[i]*py[i]);
00325     }
00326       }
00327     }
00328     string getName() const  { return "RVLVectorLogistic"; }
00329   };
00330 
00345   template<class Scalar>
00346   class RVLVectorLogisticDeriv: public LocalFunctionObject<Scalar> {
00347   public:
00348     RVLVectorLogisticDeriv() {}
00349     RVLVectorLogisticDeriv(const RVLVectorLogisticDeriv<Scalar> &) {}
00350     ~RVLVectorLogisticDeriv() {}
00351   
00352     using RVL::LocalEvaluation<Scalar>::operator();
00353     void operator()(LocalDataContainer<Scalar> & x,
00354             std::vector<LocalDataContainer<Scalar> const *> & v) {
00355       if (v.size() != 4) {
00356     RVLException e;
00357     e<<"ERROR: RVLVectorLogisticDeriv::operator()\n";
00358     e<<"  input std::vector must have size = 4\n";
00359     e<<"  layout: v[0]=x, v[1]=dx, v[2]=xmin, v[3]=xmax\n";
00360     throw e;
00361       }
00362       if ((x.getSize() != v[0]->getSize()) ||
00363       (x.getSize() != v[1]->getSize()) ||
00364       (x.getSize() != v[2]->getSize()) ||
00365       (x.getSize() != v[3]->getSize())) {   
00366     RVLException e; e<<"ERROR: RVLVectorLogisticDeriv\n";
00367     e<<"  incompatible array lengths\n";
00368     throw e;
00369       }
00370       else {
00371     size_t n = x.getSize();
00372     Scalar * px = x.getData();
00373     Scalar const * py = v[0]->getData();
00374     Scalar const * pdy = v[1]->getData();
00375     Scalar const * fm = v[2]->getData();
00376     Scalar const * fp = v[3]->getData();
00377     for (size_t i=0;i<n;i++) {
00378       if (!(fm[i]<fp[i])) {
00379         RVLException e;
00380         e<<"ERROR: RVLVectorLogistic::operator()\n";
00381         e<<"array index = "<<i<<"\n";
00382         e<<"fmin="<<fm[i]<<" not less than fmax="<<fp[i]<<"\n";
00383         throw e;
00384       }
00385       Scalar s = 2.0/(fp[i]-fm[i]);
00386       Scalar t=1.0/sqrt(1.0 + s*s*py[i]*py[i]);
00387       px[i]=pdy[i]*t*t*t;
00388     }
00389       }
00390     }
00391     string getName() const  { return "RVLVectorLogisticDeriv"; }
00392   };
00393 
00404   template<class Scalar>
00405   class RVLVectorLogisticInverse: public LocalFunctionObject<Scalar> {
00406   public:
00407     RVLVectorLogisticInverse() {}
00408     RVLVectorLogisticInverse(const RVLVectorLogisticInverse<Scalar> &) {}
00409     ~RVLVectorLogisticInverse() {}
00410   
00411     using RVL::LocalEvaluation<Scalar>::operator();
00412     void operator()(LocalDataContainer<Scalar> & x,
00413             std::vector<LocalDataContainer<Scalar> const *> & v) {
00414       if (v.size() != 3) {
00415     RVLException e;
00416     e<<"ERROR: RVLVectorLogisticInverse::operator()\n";
00417     e<<"  input std::vector must have size = 4\n";
00418     e<<"  layout: v[0]=x, v[1]=xmin, v[2]=xmax\n";
00419     throw e;
00420       }
00421       if ((x.getSize() != v[0]->getSize()) ||
00422       (x.getSize() != v[1]->getSize()) ||
00423       (x.getSize() != v[2]->getSize())) {   
00424     RVLException e; e<<"ERROR: RVLVectorLogisticInverse\n";
00425     e<<"  incompatible array lengths\n";
00426     throw e;
00427       }
00428       else {
00429     size_t n = x.getSize();
00430     Scalar * px = x.getData();
00431     Scalar const * py = v[0]->getData();    
00432     Scalar const * fm = v[1]->getData();
00433     Scalar const * fp = v[2]->getData();
00434     for (size_t i=0;i<n;i++) {
00435       Scalar s = 2.0/(fp[i]-fm[i]);
00436       Scalar m = 0.5*(fp[i]+fm[i]);
00437       if (s*s*(py[i]-m)*(py[i]-m) > 1.0 - numeric_limits<Scalar>::epsilon()) {
00438         //    if ((py[i] < (m-1/s) + 
00439         //        (py[i] > m+1/s - numeric_limits<Scalar>::epsilon())) {
00440         RVLException e;
00441         e<<"ERROR: RVLVectorLogisticInverse\n";
00442         e<<"  input value = "<<py[i]<<" too close to \n";
00443         e<<"  fmin = "<<m-1/s<<" or fmax = "<<m+1/s<<"\n";
00444         e<<"  or exceeds these bounds - cannot invert logistic map\n";
00445         e<<"  supplied function bounds are "<<fm[i]<<" and "<<fp[i]<<"\n";
00446         throw e;
00447       }
00448       px[i]=(py[i]-m)/sqrt(1.0 - s*s*(py[i]-m)*(py[i]-m));    
00449     }
00450       }
00451     }
00452     string getName() const  { return "RVLVectorLogisticInverse"; }
00453   };
00454 
00455   template<typename Scalar>
00456   class VectorLogisticOp: public Operator<Scalar> {
00457 
00458   private:
00459 
00460     // these should be shared_ptr objects - to do
00461     Vector<Scalar> const & lb;
00462     Vector<Scalar> const & ub;
00463 
00464     VectorLogisticOp();
00465     
00466   protected:
00467 
00468     void apply(Vector<float> const & x,
00469            Vector<float> & y) const {
00470       try {
00471     RVLVectorLogistic<Scalar> f;
00472     y.eval(f,x,lb,ub);
00473       }
00474       catch (RVLException & e) {
00475     e<<"\ncalled from VectorLogisticOp::apply\n";
00476     throw e;
00477       }
00478     }
00479       
00480     void applyDeriv(Vector<float> const & x,
00481             Vector<float> const & dx,
00482             Vector<float> & dy) const {
00483       try {
00484     RVLVectorLogisticDeriv<Scalar> f;
00485     std::vector<RVL::Vector<Scalar> const *> v;
00486     v.push_back(&x);
00487     v.push_back(&dx);
00488     v.push_back(&lb);
00489     v.push_back(&ub);
00490     dy.eval(f,v);
00491       }
00492       catch (RVLException & e) {
00493     e<<"\ncalled from VectorLogisticOp::applyDeriv\n";
00494     throw e;
00495       }
00496     }
00497     
00498     void applyAdjDeriv(Vector<float> const & x,
00499                Vector<float> const & dy,
00500                Vector<float> & dx) const {
00501       try {
00502     RVLVectorLogisticDeriv<Scalar> f;
00503     std::vector<RVL::Vector<Scalar> const *> v;
00504     v.push_back(&x);
00505     v.push_back(&dy);
00506     v.push_back(&lb);
00507     v.push_back(&ub);
00508     dx.eval(f,v);
00509       }
00510       catch (RVLException & e) {
00511     e<<"\ncalled from VectorLogisticOp::applyDeriv\n";
00512     throw e;
00513       }
00514     }
00515 
00516     /* note: not implemented yet
00517 
00518     void applyDeriv2(const Vector<float> & x,
00519              const Vector<float> & dx1,
00520              const Vector<float> & dx2,
00521              Vector<float> & dy) const {
00522       RVLException e;
00523       e<<"ERROR: VectorLogisticOp::applyDeriv2 not defined\n";
00524       e<<"  complain to management\n";
00525       throw e;
00526     }
00527     void applyAdjDeriv2(const Vector<float> & x,
00528             const Vector<float> & dy,
00529             const Vector<float> & dx2,
00530             Vector<float> & dx1) const {
00531       RVLException e;
00532       e<<"ERROR: VectorLogisticOp::applyAdjDeriv2 not defined\n";
00533       e<<"  complain to management\n";
00534       throw e;
00535     }
00536     */
00537     
00538     Operator<float> * clone() const { return new VectorLogisticOp<Scalar>(*this); }
00539 
00540   public:
00541 
00542     VectorLogisticOp(Vector<Scalar> const & _lb,
00543              Vector<Scalar> const & _ub)
00544       : lb(_lb), ub(_ub) {}
00545 
00546     VectorLogisticOp(VectorLogisticOp<Scalar> const & op) 
00547       : lb(op.lb), ub(op.ub) {}
00548 
00549     ~VectorLogisticOp() {}
00550 
00551     Space<Scalar> const & getDomain() const { return lb.getSpace(); }
00552     Space<Scalar> const & getRange() const { return lb.getSpace(); }
00553 
00554     ostream & write(ostream & str) const {
00555       str<<"Vector Logistic Operator implementing field box constraints\n";
00556       str<<"*** lower bound vector: \n";
00557       lb.write(str);
00558       str<<"*** upper bound vector: \n";
00559       ub.write(str);
00560       return str;
00561     }
00562   };
00563 
00564 }
00565 
00566 #endif

Generated on 5 Jan 2017 for LocalRVL by  doxygen 1.4.7