# eoRealBounds.h

    00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
    00002
    00003 //-----------------------------------------------------------------------------
    00004 // eoRealBounds.h
    00005 // (c) Marc Schoenauer 2001, Maarten Keijzer 2000, GeNeura Team, 1998
    00006 /*
    00007     This library is free software; you can redistribute it and/or
    00008     modify it under the terms of the GNU Lesser General Public
    00009     License as published by the Free Software Foundation; either
    00010     version 2 of the License, or (at your option) any later version.
    00011
    00012     This library is distributed in the hope that it will be useful,
    00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00015     Lesser General Public License for more details.
    00016
    00017     You should have received a copy of the GNU Lesser General Public
    00018     License along with this library; if not, write to the Free Software
    00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00020
    00021     Contact: todos@geneura.ugr.es, http://geneura.ugr.es
    00022              Marc.Schoenauer@polytechnique.fr
    00023              mak@dhi.dk
    00024  */
    00025 //-----------------------------------------------------------------------------
    00026
    00027 #ifndef _eoRealBounds_h
    00028 #define _eoRealBounds_h
    00029
    00030 #include <stdexcept>               // std::exceptions!
    00031 #include <utils/eoRNG.h>
    00032
    00075 class eoRealBounds : public eoPersistent
    00076 {
    00077 public:
    00078   virtual ~eoRealBounds(){}
    00079
    00082   virtual bool isBounded(void) const  = 0;
    00083
    00087   virtual bool hasNoBoundAtAll(void) const  = 0;
    00088
    00091   virtual bool isMinBounded(void) const = 0;
    00092
    00095   virtual bool isMaxBounded(void) const = 0;
    00096
    00099   virtual bool isInBounds(double)  const = 0;
    00100
    00103   virtual void foldsInBounds(double &)  const = 0;
    00104
    00107   virtual void truncate(double &)  const = 0;
    00108
    00112   virtual double minimum()  const = 0 ;
    00116   virtual double maximum()  const = 0 ;
    00120   virtual double range()  const = 0;
    00121
    00125   virtual double uniform(eoRng & _rng = eo::rng)  const = 0;
    00126
    00128   virtual eoRealBounds * dup()  const = 0;
    00129 };
    00130
    00133 class eoRealNoBounds : public eoRealBounds
    00134 {
    00135 public:
    00136   virtual ~eoRealNoBounds(){}
    00137
    00138   virtual bool isBounded(void)  const {return false;}
    00139   virtual bool hasNoBoundAtAll(void) const  {return true;}
    00140   virtual bool isMinBounded(void)  const {return false;}
    00141   virtual bool isMaxBounded(void)  const {return false;}
    00142   virtual void foldsInBounds(double &)  const {return;}
    00143   virtual void truncate(double &)  const {return;}
    00144   virtual bool isInBounds(double)  const {return true;}
    00145
    00146   virtual double minimum() const
    00147   {
    00148     throw std::logic_error("Trying to get minimum of unbounded eoRealBounds");
    00149   }
    00150   virtual double maximum() const
    00151   {
    00152     throw std::logic_error("Trying to get maximum of unbounded eoRealBounds");
    00153   }
    00154   virtual double range() const
    00155   {
    00156     throw std::logic_error("Trying to get range of unbounded eoRealBounds");
    00157   }
    00158
    00159   virtual double uniform(eoRng & _rng = eo::rng) const
    00160   {
    00161     throw std::logic_error("Trying to generate uniform values in unbounded eoRealBounds");
    00162   }
    00163
    00164   // methods from eoPersistent
    00171   virtual void readFrom(std::istream& _is)
    00172   {
    00173     throw std::runtime_error("Should not use eoRealBounds::readFrom");
    00174   }
    00175
    00180   virtual void printOn(std::ostream& _os) const
    00181   {
    00182     _os << "[-inf,+inf]";
    00183   }
    00184
    00186   virtual eoRealBounds * dup() const
    00187   {
    00188     return new eoRealNoBounds(*this);
    00189   }
    00190
    00191 };
    00192
    00193 // one object for all - see eoRealBounds.cpp
    00194 extern eoRealNoBounds eoDummyRealNoBounds;
    00195
    00199 class eoRealInterval : public eoRealBounds
    00200 {
    00201 public :
    00202   virtual ~eoRealInterval(){}
    00203
    00207   eoRealInterval(double _min=0, double _max=1) :
    00208     repMinimum(_min), repMaximum(_max), repRange(_max-_min)
    00209   {
    00210     if (repRange<=0)
    00211       throw std::logic_error("Void range in eoRealBounds");
    00212   }
    00213
    00214   // accessors
    00215   virtual double minimum() const { return repMinimum; }
    00216   virtual double maximum() const { return repMaximum; }
    00217   virtual double range()  const { return repRange; }
    00218
    00219   // description
    00220   virtual bool isBounded(void)  const {return true;}
    00221   virtual bool hasNoBoundAtAll(void)  const {return false;}
    00222   virtual bool isMinBounded(void)  const {return true;}
    00223   virtual bool isMaxBounded(void)  const {return true;}
    00224
    00225   virtual double uniform(eoRng & _rng = eo::rng) const
    00226   {
    00227     return repMinimum + _rng.uniform(repRange);
    00228   }
    00229
    00230   // says if a given double is within the bounds
    00231   virtual bool isInBounds(double _r) const
    00232   {
    00233     if (_r < repMinimum)
    00234       return false;
    00235     if (_r > repMaximum)
    00236       return false;
    00237     return true;
    00238   }
    00239
    00240   // folds a value into bounds
    00241   virtual void foldsInBounds(double &  _r) const
    00242   {
    00243     long iloc;
    00244     double dlargloc = 2 * range() ;
    00245
    00246     if (fabs(_r) > 1.0E9)               // iloc too large!
    00247       {
    00248         _r = uniform();
    00249         return;
    00250       }
    00251
    00252     if ( (_r > maximum()) )
    00253       {
    00254         iloc = (long) ( (_r-minimum()) / dlargloc ) ;
    00255         _r -= dlargloc * iloc ;
    00256         if ( _r > maximum() )
    00257           _r = 2*maximum() - _r ;
    00258       }
    00259
    00260     if (_r < minimum())
    00261       {
    00262         iloc = (long) ( (maximum()-_r) / dlargloc ) ;
    00263         _r += dlargloc * iloc ;
    00264         if (_r < minimum())
    00265           _r = 2*minimum() - _r ;
    00266       }
    00267   }
    00268
    00269   // truncates to the bounds
    00270   virtual void truncate(double & _r) const
    00271   {
    00272     if (_r < repMinimum)
    00273       _r = repMinimum;
    00274     else if (_r > repMaximum)
    00275       _r = repMaximum;
    00276     return;
    00277   }
    00278
    00279   // methods from eoPersistent
    00286   virtual void readFrom(std::istream& _is)
    00287   {
    00288     throw std::runtime_error("Should not use eoRealInterval::readFrom");
    00289   }
    00290
    00295   virtual void printOn(std::ostream& _os) const
    00296   {
    00297     _os << "[" << repMinimum << "," << repMaximum << "]";
    00298   }
    00299
    00301   virtual eoRealBounds * dup() const
    00302   {
    00303     return new eoRealInterval(*this);
    00304   }
    00305
    00306 private :
    00307   double repMinimum;
    00308   double repMaximum;
    00309   double repRange;                         // to minimize operations ???
    00310 };
    00311
    00315 class eoRealBelowBound : public eoRealBounds
    00316 {
    00317 public :
    00318   virtual ~eoRealBelowBound(){}
    00322   eoRealBelowBound(double _min=0) :
    00323     repMinimum(_min)
    00324   {}
    00325
    00326   // accessors
    00327   virtual double minimum() const { return repMinimum; }
    00328
    00329   virtual double maximum() const
    00330   {
    00331     throw std::logic_error("Trying to get maximum of eoRealBelowBound");
    00332   }
    00333   virtual double range() const
    00334   {
    00335     throw std::logic_error("Trying to get range of eoRealBelowBound");
    00336   }
    00337
    00338   // random generators
    00339   virtual double uniform(eoRng & _rng = eo::rng) const
    00340   {
    00341     throw std::logic_error("Trying to generate uniform values in eoRealBelowBound");
    00342   }
    00343
    00344   // description
    00345   virtual bool isBounded(void)  const {return false;}
    00346   virtual bool hasNoBoundAtAll(void)  const {return false;}
    00347   virtual bool isMinBounded(void)  const {return true;}
    00348   virtual bool isMaxBounded(void) const  {return false;}
    00349
    00350   // says if a given double is within the bounds
    00351   virtual bool isInBounds(double _r) const
    00352   {
    00353     if (_r < repMinimum)
    00354       return false;
    00355     return true;
    00356   }
    00357
    00358   // folds a value into bounds
    00359   virtual void foldsInBounds(double &  _r) const
    00360   {
    00361     // easy as a pie: symmetry w.r.t. minimum
    00362     if (_r < repMinimum)           // nothing to do otherwise
    00363       _r = 2*repMinimum - _r;
    00364     return ;
    00365   }
    00366
    00367   // truncates to the bounds
    00368   virtual void truncate(double & _r) const
    00369   {
    00370     if (_r < repMinimum)
    00371       _r = repMinimum;
    00372     return;
    00373   }
    00374
    00375   // methods from eoPersistent
    00382   virtual void readFrom(std::istream& _is)
    00383   {
    00384     throw std::runtime_error("Should not use eoRealBelowBound::readFrom");
    00385   }
    00386
    00391   virtual void printOn(std::ostream& _os) const
    00392   {
    00393     _os << "[" << repMinimum << ",+inf]";
    00394   }
    00395
    00397   virtual eoRealBounds * dup() const
    00398   {
    00399     return new eoRealBelowBound(*this);
    00400   }
    00401
    00402 private :
    00403   double repMinimum;
    00404 };
    00405
    00409 class eoRealAboveBound : public eoRealBounds
    00410 {
    00411 public :
    00412   virtual ~eoRealAboveBound(){}
    00413
    00417   eoRealAboveBound(double _max=0) :
    00418     repMaximum(_max)
    00419   {}
    00420
    00421   // accessors
    00422   virtual double maximum() const  { return repMaximum; }
    00423
    00424   virtual double minimum() const
    00425   {
    00426     throw std::logic_error("Trying to get minimum of eoRealAboveBound");
    00427   }
    00428   virtual double range() const
    00429   {
    00430     throw std::logic_error("Trying to get range of eoRealAboveBound");
    00431   }
    00432
    00433   // random generators
    00434   virtual double uniform(eoRng & _rng = eo::rng) const
    00435   {
    00436     throw std::logic_error("Trying to generate uniform values in eoRealAboveBound");
    00437   }
    00438
    00439   // description
    00440   virtual bool isBounded(void)  const {return false;}
    00441   virtual bool hasNoBoundAtAll(void)  const {return false;}
    00442   virtual bool isMinBounded(void)  const {return false;}
    00443   virtual bool isMaxBounded(void)  const {return true;}
    00444
    00445   // says if a given double is within the bounds
    00446   virtual bool isInBounds(double _r) const
    00447   {
    00448     if (_r > repMaximum)
    00449       return false;
    00450     return true;
    00451   }
    00452
    00453   // folds a value into bounds
    00454   virtual void foldsInBounds(double &  _r) const
    00455   {
    00456     // easy as a pie: symmetry w.r.t. maximum
    00457     if (_r > repMaximum)           // nothing to do otherwise
    00458       _r = 2*repMaximum - _r;
    00459     return ;
    00460   }
    00461
    00462   // truncates to the bounds
    00463   virtual void truncate(double & _r) const
    00464   {
    00465     if (_r > repMaximum)
    00466       _r = repMaximum;
    00467     return;
    00468   }
    00469
    00470   // methods from eoPersistent
    00477   virtual void readFrom(std::istream& _is)
    00478   {
    00479     throw std::runtime_error("Should not use eoRealAboveBound::readFrom");
    00480   }
    00481
    00486   virtual void printOn(std::ostream& _os) const
    00487   {
    00488     _os << "[-inf," << repMaximum << "]";
    00489   }
    00490
    00492   virtual eoRealBounds * dup() const
    00493   {
    00494     return new eoRealAboveBound(*this);
    00495   }
    00496
    00497 private :
    00498   double repMaximum;
    00499 };
    00500
    00502
    00506 class eoGeneralRealBounds : public eoRealBounds
    00507 {
    00508 public:
    00510   eoGeneralRealBounds(std::string _s = "[-infinity,+infinity]")
    00511   {
    00512     repBound = getBoundsFromString(_s);
    00513   }
    00514
    00516   eoGeneralRealBounds(const eoGeneralRealBounds & _b):eoRealBounds(_b)
    00517   {
    00518     // replicate the embedded bound (I'm pretty sure there is another
    00519     // way to do that !!!
    00520
    00521     bool minBounded = _b.isMinBounded();
    00522     bool maxBounded = _b.isMaxBounded();
    00523     double minimum, maximum;
    00524     const eoRealBounds & bb = _b.theBounds();
    00525     if (minBounded) minimum = bb.minimum();
    00526     if (maxBounded) maximum = bb.maximum();
    00527
    00528       if (minBounded && maxBounded)
    00529         repBound = new eoRealInterval(minimum, maximum);
    00530       else if (!minBounded && !maxBounded)      // no bound at all
    00531         repBound = new eoRealNoBounds;
    00532       else if (!minBounded && maxBounded)
    00533         repBound = new eoRealAboveBound(maximum);
    00534       else if (minBounded && !maxBounded)
    00535         repBound = new eoRealBelowBound(minimum);
    00536   }
    00537
    00538   eoGeneralRealBounds& operator=(const eoGeneralRealBounds& _b)
    00539   {
    00540     // replicate the embedded bound (I'm pretty sure there is another
    00541     // way to do that !!!
    00542
    00543     bool minBounded = _b.isMinBounded();
    00544     bool maxBounded = _b.isMaxBounded();
    00545     double minimum, maximum;
    00546     const eoRealBounds & bb = _b.theBounds();
    00547     if (minBounded) minimum = bb.minimum();
    00548     if (maxBounded) maximum = bb.maximum();
    00549
    00550     // first delete the embedded bounds if necessary
    00551     if (repBound)
    00552       delete repBound;
    00553     // now reallocate
    00554       if (minBounded && maxBounded)
    00555         repBound = new eoRealInterval(minimum, maximum);
    00556       else if (!minBounded && !maxBounded)      // no bound at all
    00557         repBound = new eoRealNoBounds;
    00558       else if (!minBounded && maxBounded)
    00559         repBound = new eoRealAboveBound(maximum);
    00560       else if (minBounded && !maxBounded)
    00561         repBound = new eoRealBelowBound(minimum);
    00562       return (*this);
    00563   }
    00564
    00565
    00567   ~eoGeneralRealBounds()
    00568   {
    00569     delete repBound;
    00570   }
    00571
    00573
    00575   virtual bool isBounded(void)  const {return repBound->isBounded();}
    00576
    00580   virtual bool hasNoBoundAtAll(void)  const {return repBound->hasNoBoundAtAll();}
    00581
    00584   virtual bool isMinBounded(void)  const {return repBound->isMinBounded();}
    00585
    00588   virtual bool isMaxBounded(void) const {return repBound->isMaxBounded();}
    00589
    00592   virtual bool isInBounds(double _x)  const {return repBound->isInBounds(_x);}
    00593
    00596   virtual void foldsInBounds(double & _x) const {return repBound->foldsInBounds(_x);}
    00597
    00600   virtual void truncate(double & _x)  const {return repBound->truncate(_x);}
    00601
    00605   virtual double minimum()  const {return repBound->minimum();}
    00609   virtual double maximum() const {return repBound->maximum();}
    00613   virtual double range()  const {return repBound->range();}
    00614
    00618   virtual double uniform(eoRng & _rng = eo::rng)  const {return repBound->uniform();}
    00619
    00621   virtual eoRealBounds * dup() const  {return repBound->dup();}
    00622
    00624   const eoRealBounds & theBounds()  const { return *repBound;}
    00625
    00629   virtual void printOn(std::ostream& _os) const
    00630   {
    00631     repBound->printOn(_os);
    00632   }
    00633
    00635   virtual void readFrom(std::istream& _is)
    00636   {
    00637     std::string s;
    00638     _is >> s;
    00639     if (repBound)
    00640       delete repBound;
    00641     repBound = getBoundsFromString(s);
    00642   }
    00643
    00644 private:
    00645   // reading from a string
    00646   eoRealBounds * getBoundsFromString(std::string);
    00647
    00648   eoRealBounds * repBound;
    00649 };
    00650
    00651
    00652 #endif