# eoIntBounds.h

    00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
    00002
    00003 //-----------------------------------------------------------------------------
    00004 // eoIntBounds.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 _eoIntBounds_h
    00028 #define _eoIntBounds_h
    00029
    00030 #include <stdexcept>               // std::exceptions!
    00031 #include <utils/eoRNG.h>
    00032
    00075 class eoIntBounds : public eoPersistent
    00076 {
    00077 public:
    00078   virtual ~eoIntBounds(){}
    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 foldsInBounds(long int & i)  const
    00108   {
    00109     double r = double(i);
    00110     foldsInBounds(r);
    00111     i = (long int)(r);
    00112   }
    00113
    00116   virtual void truncate(double &)  const = 0;
    00117
    00120   virtual void truncate(long int & i)  const
    00121   {
    00122     double r = double(i);
    00123     truncate(r);
    00124     i = (long int)(r);
    00125   }
    00126
    00130   virtual long int minimum()  const = 0 ;
    00134   virtual long int maximum()  const = 0 ;
    00138   virtual long int range()  const = 0;
    00139
    00144   virtual double uniform(eoRng & _rng = eo::rng)  const = 0;
    00145   virtual long int random(eoRng & _rng = eo::rng)  const = 0;
    00146
    00148   virtual eoIntBounds * dup()  const = 0;
    00149 };
    00150
    00153 class eoIntNoBounds : public eoIntBounds
    00154 {
    00155 public:
    00156   virtual ~eoIntNoBounds(){}
    00157
    00158   virtual bool isBounded(void)  const {return false;}
    00159   virtual bool hasNoBoundAtAll(void) const  {return true;}
    00160   virtual bool isMinBounded(void)  const {return false;}
    00161   virtual bool isMaxBounded(void)  const {return false;}
    00162   virtual void foldsInBounds(double &)  const {return;}
    00163   virtual void truncate(double &)  const {return;}
    00164   virtual bool isInBounds(double)  const {return true;}
    00165
    00166   virtual long int minimum() const
    00167   {
    00168     throw std::logic_error("Trying to get minimum of unbounded eoIntBounds");
    00169   }
    00170   virtual long int maximum() const
    00171   {
    00172     throw std::logic_error("Trying to get maximum of unbounded eoIntBounds");
    00173   }
    00174   virtual long int range() const
    00175   {
    00176     throw std::logic_error("Trying to get range of unbounded eoIntBounds");
    00177   }
    00178
    00179   virtual double uniform(eoRng & _rng = eo::rng) const
    00180   {
    00181     throw std::logic_error("Trying to generate uniform values in unbounded eoIntBounds");
    00182   }
    00183   virtual long int random(eoRng & _rng = eo::rng) const
    00184   {
    00185     throw std::logic_error("Trying to generate uniform values in unbounded eoIntBounds");
    00186   }
    00187
    00188   // methods from eoPersistent
    00195   virtual void readFrom(std::istream& _is)
    00196   {
    00197     throw std::runtime_error("Should not use eoIntBounds::readFrom");
    00198   }
    00199
    00204   virtual void printOn(std::ostream& _os) const
    00205   {
    00206     _os << "[-inf,+inf]";
    00207   }
    00208
    00210   virtual eoIntBounds * dup() const
    00211   {
    00212     return new eoIntNoBounds(*this);
    00213   }
    00214
    00215 };
    00216
    00217 // one object for all - see eoIntBounds.cpp
    00218 extern eoIntNoBounds eoDummyIntNoBounds;
    00219
    00223 class eoIntInterval : public eoIntBounds
    00224 {
    00225 public :
    00226   virtual ~eoIntInterval(){}
    00227
    00231   eoIntInterval(long int _min=0, long int _max=1) :
    00232     repMinimum(_min), repMaximum(_max), repRange(_max-_min)
    00233   {
    00234     if (repRange<=0)
    00235       throw std::logic_error("Void range in eoIntBounds");
    00236   }
    00237
    00238   // accessors
    00239   virtual long int minimum() const { return repMinimum; }
    00240   virtual long int maximum() const { return repMaximum; }
    00241   virtual long int range()  const { return repRange; }
    00242
    00243   // description
    00244   virtual bool isBounded(void)  const {return true;}
    00245   virtual bool hasNoBoundAtAll(void)  const {return false;}
    00246   virtual bool isMinBounded(void)  const {return true;}
    00247   virtual bool isMaxBounded(void)  const {return true;}
    00248
    00249   virtual double uniform(eoRng & _rng = eo::rng) const
    00250   {
    00251     return repMinimum + _rng.uniform(repRange);
    00252   }
    00253
    00254   virtual long int random(eoRng & _rng = eo::rng) const
    00255   {
    00256     return repMinimum + _rng.random(repRange);
    00257   }
    00258
    00259   // says if a given double is within the bounds
    00260   virtual bool isInBounds(double _r) const
    00261   {
    00262     if (_r < repMinimum)
    00263       return false;
    00264     if (_r > repMaximum)
    00265       return false;
    00266     return true;
    00267   }
    00268
    00269   // folds a value into bounds
    00270   virtual void foldsInBounds(double &  _r) const
    00271   {
    00272     long iloc;
    00273     double dlargloc = 2 * range() ;
    00274
    00275     if (fabs(_r) > 1.0E9)               // iloc too large!
    00276       {
    00277         _r = uniform();
    00278         return;
    00279       }
    00280
    00281     if ( (_r > maximum()) )
    00282       {
    00283         iloc = (long) ( (_r-minimum()) / dlargloc ) ;
    00284         _r -= dlargloc * iloc ;
    00285         if ( _r > maximum() )
    00286           _r = 2*maximum() - _r ;
    00287       }
    00288
    00289     if (_r < minimum())
    00290       {
    00291         iloc = (long) ( (maximum()-_r) / dlargloc ) ;
    00292         _r += dlargloc * iloc ;
    00293         if (_r < minimum())
    00294           _r = 2*minimum() - _r ;
    00295       }
    00296   }
    00297
    00298   // truncates to the bounds
    00299   virtual void truncate(double & _r) const
    00300   {
    00301     if (_r < repMinimum)
    00302       _r = repMinimum;
    00303     else if (_r > repMaximum)
    00304       _r = repMaximum;
    00305     return;
    00306   }
    00307
    00308   // methods from eoPersistent
    00315   virtual void readFrom(std::istream& _is)
    00316   {
    00317     throw std::runtime_error("Should not use eoIntInterval::readFrom");
    00318   }
    00319
    00324   virtual void printOn(std::ostream& _os) const
    00325   {
    00326     _os << "[" << repMinimum << "," << repMaximum << "]";
    00327   }
    00328
    00330   virtual eoIntBounds * dup() const
    00331   {
    00332     return new eoIntInterval(*this);
    00333   }
    00334
    00335 private :
    00336   long int repMinimum;
    00337   long int repMaximum;
    00338   long int repRange;                       // to minimize operations ???
    00339 };
    00340
    00344 class eoIntBelowBound : public eoIntBounds
    00345 {
    00346 public :
    00347   virtual ~eoIntBelowBound(){}
    00351   eoIntBelowBound(long int _min=0) :
    00352     repMinimum(_min)
    00353   {}
    00354
    00355   // accessors
    00356   virtual long int minimum() const { return repMinimum; }
    00357
    00358   virtual long int maximum() const
    00359   {
    00360     throw std::logic_error("Trying to get maximum of eoIntBelowBound");
    00361   }
    00362   virtual long int range() const
    00363   {
    00364     throw std::logic_error("Trying to get range of eoIntBelowBound");
    00365   }
    00366
    00367   virtual double uniform(eoRng & _rng = eo::rng) const
    00368   {
    00369     throw std::logic_error("Trying to generate uniform values in eoIntBelowBound");
    00370   }
    00371   virtual long int random(eoRng & _rng = eo::rng) const
    00372   {
    00373     throw std::logic_error("Trying to generate uniform values in eoIntBelowBound");
    00374   }
    00375
    00376   // description
    00377   virtual bool isBounded(void)  const {return false;}
    00378   virtual bool hasNoBoundAtAll(void)  const {return false;}
    00379   virtual bool isMinBounded(void)  const {return true;}
    00380   virtual bool isMaxBounded(void) const  {return false;}
    00381
    00382   // says if a given double is within the bounds
    00383   virtual bool isInBounds(double _r) const
    00384   {
    00385     if (_r < repMinimum)
    00386       return false;
    00387     return true;
    00388   }
    00389
    00390   // folds a value into bounds
    00391   virtual void foldsInBounds(double &  _r) const
    00392   {
    00393     // easy as a pie: symmetry w.r.t. minimum
    00394     if (_r < repMinimum)           // nothing to do otherwise
    00395       _r = 2*repMinimum - _r;
    00396     return ;
    00397   }
    00398
    00399   // truncates to the bounds
    00400   virtual void truncate(double & _r) const
    00401   {
    00402     if (_r < repMinimum)
    00403       _r = repMinimum;
    00404     return;
    00405   }
    00406
    00407   // methods from eoPersistent
    00414   virtual void readFrom(std::istream& _is)
    00415   {
    00416     throw std::runtime_error("Should not use eoIntBelowBound::readFrom");
    00417   }
    00418
    00423   virtual void printOn(std::ostream& _os) const
    00424   {
    00425     _os << "[" << repMinimum << ",+inf]";
    00426   }
    00427
    00429   virtual eoIntBounds * dup() const
    00430   {
    00431     return new eoIntBelowBound(*this);
    00432   }
    00433
    00434 private :
    00435   long int repMinimum;
    00436 };
    00437
    00441 class eoIntAboveBound : public eoIntBounds
    00442 {
    00443 public :
    00444   virtual ~eoIntAboveBound(){}
    00445
    00449   eoIntAboveBound(long int _max=0) :
    00450     repMaximum(_max)
    00451   {}
    00452
    00453   // accessors
    00454   virtual long int maximum() const  { return repMaximum; }
    00455
    00456   virtual long int minimum() const
    00457   {
    00458     throw std::logic_error("Trying to get minimum of eoIntAboveBound");
    00459   }
    00460   virtual long int range() const
    00461   {
    00462     throw std::logic_error("Trying to get range of eoIntAboveBound");
    00463   }
    00464
    00465   virtual double uniform(eoRng & _rng = eo::rng) const
    00466   {
    00467     throw std::logic_error("Trying to generate uniform values in eoIntAboveBound");
    00468   }
    00469   virtual long int random(eoRng & _rng = eo::rng) const
    00470   {
    00471     throw std::logic_error("Trying to generate uniform values in eoIntAboveBound");
    00472   }
    00473
    00474   // description
    00475   virtual bool isBounded(void)  const {return false;}
    00476   virtual bool hasNoBoundAtAll(void)  const {return false;}
    00477   virtual bool isMinBounded(void)  const {return false;}
    00478   virtual bool isMaxBounded(void)  const {return true;}
    00479
    00480   // says if a given double is within the bounds
    00481   virtual bool isInBounds(double _r) const
    00482   {
    00483     if (_r > repMaximum)
    00484       return false;
    00485     return true;
    00486   }
    00487
    00488   // folds a value into bounds
    00489   virtual void foldsInBounds(double &  _r) const
    00490   {
    00491     // easy as a pie: symmetry w.r.t. maximum
    00492     if (_r > repMaximum)           // nothing to do otherwise
    00493       _r = 2*repMaximum - _r;
    00494     return ;
    00495   }
    00496
    00497   // truncates to the bounds
    00498   virtual void truncate(double & _r) const
    00499   {
    00500     if (_r > repMaximum)
    00501       _r = repMaximum;
    00502     return;
    00503   }
    00504
    00505   // methods from eoPersistent
    00512   virtual void readFrom(std::istream& _is)
    00513   {
    00514     throw std::runtime_error("Should not use eoIntAboveBound::readFrom");
    00515   }
    00516
    00521   virtual void printOn(std::ostream& _os) const
    00522   {
    00523     _os << "[-inf," << repMaximum << "]";
    00524   }
    00525
    00527   virtual eoIntBounds * dup() const
    00528   {
    00529     return new eoIntAboveBound(*this);
    00530   }
    00531
    00532 private :
    00533   long int repMaximum;
    00534 };
    00535
    00537
    00541 class eoGeneralIntBounds : public eoIntBounds
    00542 {
    00543 public:
    00545   eoGeneralIntBounds(std::string _s = "[-infinity,+infinity]")
    00546   {
    00547     repBound = getBoundsFromString(_s);
    00548   }
    00549
    00551   eoGeneralIntBounds(const eoGeneralIntBounds & _b) : eoIntBounds(_b)
    00552   {
    00553     // replicate the embedded bound (I'm pretty sure there is another
    00554     // way to do that !!!
    00555
    00556     bool minBounded = _b.isMinBounded();
    00557     bool maxBounded = _b.isMaxBounded();
    00558     long int minimum, maximum;
    00559     const eoIntBounds & bb = _b.theBounds();
    00560     if (minBounded) minimum = bb.minimum();
    00561     if (maxBounded) maximum = bb.maximum();
    00562
    00563       if (minBounded && maxBounded)
    00564         repBound = new eoIntInterval(minimum, maximum);
    00565       else if (!minBounded && !maxBounded)      // no bound at all
    00566         repBound = new eoIntNoBounds;
    00567       else if (!minBounded && maxBounded)
    00568         repBound = new eoIntAboveBound(maximum);
    00569       else if (minBounded && !maxBounded)
    00570         repBound = new eoIntBelowBound(minimum);
    00571   }
    00572
    00573   eoGeneralIntBounds& operator=(const eoGeneralIntBounds& _b)
    00574   {
    00575     // replicate the embedded bound (I'm pretty sure there is another
    00576     // way to do that !!!
    00577
    00578     bool minBounded = _b.isMinBounded();
    00579     bool maxBounded = _b.isMaxBounded();
    00580     long int minimum, maximum;
    00581     const eoIntBounds & bb = _b.theBounds();
    00582     if (minBounded) minimum = bb.minimum();
    00583     if (maxBounded) maximum = bb.maximum();
    00584
    00585     // first delete the embedded bounds if necessary
    00586     if (repBound)
    00587       delete repBound;
    00588     // now reallocate
    00589       if (minBounded && maxBounded)
    00590         repBound = new eoIntInterval(minimum, maximum);
    00591       else if (!minBounded && !maxBounded)      // no bound at all
    00592         repBound = new eoIntNoBounds;
    00593       else if (!minBounded && maxBounded)
    00594         repBound = new eoIntAboveBound(maximum);
    00595       else if (minBounded && !maxBounded)
    00596         repBound = new eoIntBelowBound(minimum);
    00597       return (*this);
    00598   }
    00599
    00600
    00602   ~eoGeneralIntBounds()
    00603   {
    00604     delete repBound;
    00605   }
    00606
    00608
    00610   virtual bool isBounded(void)  const {return repBound->isBounded();}
    00611
    00615   virtual bool hasNoBoundAtAll(void)  const {return repBound->hasNoBoundAtAll();}
    00616
    00619   virtual bool isMinBounded(void)  const {return repBound->isMinBounded();}
    00620
    00623   virtual bool isMaxBounded(void) const {return repBound->isMaxBounded();}
    00624
    00627   virtual bool isInBounds(double _x)  const {return repBound->isInBounds(_x);}
    00628
    00631   virtual void foldsInBounds(double & _x) const {return repBound->foldsInBounds(_x);}
    00632
    00635   virtual void truncate(double & _x)  const {return repBound->truncate(_x);}
    00636
    00640   virtual long int minimum()  const {return repBound->minimum();}
    00644   virtual long int maximum() const {return repBound->maximum();}
    00648   virtual long int range()  const {return repBound->range();}
    00649
    00653   virtual double uniform(eoRng & _rng = eo::rng)  const {return repBound->uniform();}
    00654
    00658   virtual long int random(eoRng & _rng = eo::rng)  const {return repBound->random();}
    00659
    00661   virtual eoIntBounds * dup() const  {return repBound->dup();}
    00662
    00664   const eoIntBounds & theBounds()  const { return *repBound;}
    00665
    00669   virtual void printOn(std::ostream& _os) const
    00670   {
    00671     repBound->printOn(_os);
    00672   }
    00673
    00675   virtual void readFrom(std::istream& _is)
    00676   {
    00677     std::string s;
    00678     _is >> s;
    00679     if (repBound)
    00680       delete repBound;
    00681     repBound = getBoundsFromString(s);
    00682   }
    00683
    00684 private:
    00685   // reading from a string
    00686   eoIntBounds * getBoundsFromString(std::string);
    00687
    00688   eoIntBounds * repBound;
    00689 };
    00690
    00691
    00692 #endif