diff --git a/eo/src/utils/Makefile.am b/eo/src/utils/Makefile.am index 5767df46..5c041cb7 100644 --- a/eo/src/utils/Makefile.am +++ b/eo/src/utils/Makefile.am @@ -9,6 +9,7 @@ libeoutils_a_SOURCES = eoParser.cpp \ eoFileMonitor.cpp \ eoStdoutMonitor.cpp \ eoRealBounds.cpp \ + eoIntBounds.cpp \ make_help.cpp AM_CXXFLAGS = -I$(top_srcdir)/src @@ -35,6 +36,7 @@ utilsinclude_HEADERS = checkpointing \ eoPopStat.h \ eoRNG.h \ eoRealBounds.h \ + eoIntBounds.h \ eoRealVectorBounds.h \ eoRndGenerators.h \ eoScalarFitnessStat.h \ diff --git a/eo/src/utils/eoIntBounds.cpp b/eo/src/utils/eoIntBounds.cpp new file mode 100644 index 00000000..924efe29 --- /dev/null +++ b/eo/src/utils/eoIntBounds.cpp @@ -0,0 +1,99 @@ +#ifdef _MSC_VER +// to avoid long name warnings +#pragma warning(disable:4786) +#endif + +#include + +#ifdef HAVE_SSTREAM +#include +#else +#include +#endif + +#include "eoIntBounds.h" + + +// the global dummy bounds +// (used for unbounded variables when bounds are required) +eoIntNoBounds eoDummyIntNoBounds; + +///////////// helper read functions defined in eoRealBounds.cpp +extern bool remove_leading(std::string & _s, const std::string _delim); +extern double read_double(std::string _s); +extern long int read_int(std::string _s); + + +/** the constructor for eoGeneralIntBound - from a string + */ +eoIntBounds* eoGeneralIntBounds::getBoundsFromString(std::string _value) +{ + // now read + std::string delim(",; "); + std::string beginOrClose("[(])"); + if (!remove_leading(_value, delim)) // only delimiters were left + throw std::runtime_error("Syntax error in eoGeneralIntBounds Ctor"); + + // look for opening char + size_t posDeb = _value.find_first_of(beginOrClose); // allow ]a,b] + if (posDeb >= _value.size()) // nothing left to read + throw std::runtime_error("Syntax error in eoGeneralIntBounds Ctor"); + + // ending char: next {}() after posDeb + size_t posFin = _value.find_first_of(beginOrClose,posDeb+1); + if (posFin >= _value.size()) // not found + throw std::runtime_error("Syntax error in eoGeneralIntBounds Ctor"); + + // the bounds + std::string sBounds = _value.substr(posDeb+1, posFin-posDeb-1); + // and remove from original string + _value = _value.substr(posFin+1); + + remove_leading(sBounds, delim); + size_t posDelim = sBounds.find_first_of(delim); + if (posDelim >= sBounds.size()) + throw std::runtime_error("Syntax error in eoGeneralIntBounds Ctor"); + + bool minBounded=false, maxBounded=false; + long int minBound=0, maxBound=0; + + // min bound + std::string sMinBounds = sBounds.substr(0,posDelim); + + if ( (sMinBounds != std::string("-inf")) && + (sMinBounds != std::string("-infinity")) + ) + { + minBounded = true; + minBound = read_int(sMinBounds); + } + + // max bound + size_t posEndDelim = sBounds.find_first_not_of(delim,posDelim); + + std::string sMaxBounds = sBounds.substr(posEndDelim); + + if ( (sMaxBounds != std::string("+inf")) && + (sMaxBounds != std::string("+infinity")) + ) + { + maxBounded = true; + maxBound = read_int(sMaxBounds); + } + + // now create the embedded eoIntBounds object + eoIntBounds * locBound; + if (minBounded && maxBounded) + { + if (maxBound <= minBound) + throw std::runtime_error("Syntax error in eoGeneralIntBounds Ctor"); + locBound = new eoIntInterval(minBound, maxBound); + } + else if (!minBounded && !maxBounded) // no bound at all + locBound = new eoIntNoBounds; + else if (!minBounded && maxBounded) + locBound = new eoIntAboveBound(maxBound); + else if (minBounded && !maxBounded) + locBound = new eoIntBelowBound(minBound); + return locBound; +} diff --git a/eo/src/utils/eoIntBounds.h b/eo/src/utils/eoIntBounds.h new file mode 100644 index 00000000..a38253b4 --- /dev/null +++ b/eo/src/utils/eoIntBounds.h @@ -0,0 +1,689 @@ +// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + +//----------------------------------------------------------------------------- +// eoIntBounds.h +// (c) Marc Schoenauer 2001, Maarten Keijzer 2000, GeNeura Team, 1998 +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Contact: todos@geneura.ugr.es, http://geneura.ugr.es + Marc.Schoenauer@polytechnique.fr + mak@dhi.dk + */ +//----------------------------------------------------------------------------- + +#ifndef _eoIntBounds_h +#define _eoIntBounds_h + +#include // std::exceptions! +#include + +/** +\defgroup EvolutionStrategies + +*/ + + +/** +\class eoIntBounds eoIntBounds.h es/eoIntBounds.h +\ingroup EvolutionStrategies + + Defines bound classes for real numbers. + +Scalar type: +------------ +Basic class is eoIntBounds, a pure virtual. + +The following pure virtual methods are to be used in mutations: +- void foldsInBounds(long int &) that folds any value that falls out of + the bounds back into the bounds, by bouncing on the limit (if any) +- bool isInBounds(long int) that simply says whether or not the argument + is in the bounds +- void truncate(long int &) that set the argument to the bound value it +it exceeds it + +So mutation can choose +- iterate trying until they fall in bounds, +- only try once and "restd::pair" by using the foldsInBounds method +- only try once and restd::pair using the truncate method (will create a + huge bias toward the bound if the soluiton is not far from the bounds) + +There is also a uniform() method that generates a uniform value +(if possible, i.e. if bounded) in the interval. + +Derived class are +eoIntInterval that holds a minimum and maximum value, +eoIntNoBounds the "unbounded bounds" (-infinity, +infinity) +eoIntBelowBound the half-bounded interval [min, +infinity) +eoIntAboveBound the half-bounded interval (-infinity, max] + +THis file also contains the declaration of *the* global object that +is the unbounded bound +*/ +class eoIntBounds : public eoPersistent +{ +public: + virtual ~eoIntBounds(){} + + /** Self-Test: true if ***both*** a min and a max + */ + virtual bool isBounded(void) const = 0; + + /** Self-Test: true if no min ***and*** no max + * hence no further need to test/truncate/fold anything + */ + virtual bool hasNoBoundAtAll(void) const = 0; + + /** Self-Test: bounded from below??? + */ + virtual bool isMinBounded(void) const = 0; + + /** Self-Test: bounded from above??? + */ + virtual bool isMaxBounded(void) const = 0; + + /** Test on a value: is it in bounds? + */ + virtual bool isInBounds(double) const = 0; + + /** Put value back into bounds - by folding back and forth + */ + virtual void foldsInBounds(double &) const = 0; + + /** foldsInBounds for ints: + * call the method for double and convert back */ + virtual void foldsInBounds(long int & i) const + { + double r = double(i); + foldsInBounds(r); + i = (long int)(r); + } + + /** Put value back into bounds - by truncating to a boundary value + */ + virtual void truncate(double &) const = 0; + + /** truncate for ints: call the method for double and convert back + */ + virtual void truncate(long int & i) const + { + double r = double(i); + truncate(r); + i = (long int)(r); + } + + /** get minimum value + * @std::exception if does not exist + */ + virtual long int minimum() const = 0 ; + /** get maximum value + * @std::exception if does not exist + */ + virtual long int maximum() const = 0 ; + /** get range + * @std::exception if unbounded + */ + virtual long int range() const = 0; + + /** random generator of uniform numbers in bounds + * uses same naming convention than eo::rng + * @std::exception if unbounded + */ + virtual double uniform(eoRng & _rng = eo::rng) const = 0; + virtual long int random(eoRng & _rng = eo::rng) const = 0; + + /** for memory managements - ugly */ + virtual eoIntBounds * dup() const = 0; +}; + +/** A default class for unbounded variables + */ +class eoIntNoBounds : public eoIntBounds +{ +public: + virtual ~eoIntNoBounds(){} + + virtual bool isBounded(void) const {return false;} + virtual bool hasNoBoundAtAll(void) const {return true;} + virtual bool isMinBounded(void) const {return false;} + virtual bool isMaxBounded(void) const {return false;} + virtual void foldsInBounds(double &) const {return;} + virtual void truncate(double &) const {return;} + virtual bool isInBounds(double) const {return true;} + + virtual long int minimum() const + { + throw std::logic_error("Trying to get minimum of unbounded eoIntBounds"); + } + virtual long int maximum() const + { + throw std::logic_error("Trying to get maximum of unbounded eoIntBounds"); + } + virtual long int range() const + { + throw std::logic_error("Trying to get range of unbounded eoIntBounds"); + } + + virtual double uniform(eoRng & _rng = eo::rng) const + { + throw std::logic_error("Trying to generate uniform values in unbounded eoIntBounds"); + } + virtual long int random(eoRng & _rng = eo::rng) const + { + throw std::logic_error("Trying to generate uniform values in unbounded eoIntBounds"); + } + + // methods from eoPersistent + /** + * Read object. + * @param _is A std::istream. + * but reading should not be done here, because of bound problems + * see eoIntVectorBounds + */ + virtual void readFrom(std::istream& _is) + { + throw std::runtime_error("Should not use eoIntBounds::readFrom"); + } + + /** + * Write object. It's called printOn since it prints the object on a stream. + * @param _os A std::ostream. + */ + virtual void printOn(std::ostream& _os) const + { + _os << "[-inf,+inf]"; + } + + /** for memory managements - ugly */ + virtual eoIntBounds * dup() const + { + return new eoIntNoBounds(*this); + } + +}; + +// one object for all - see eoIntBounds.cpp +extern eoIntNoBounds eoDummyIntNoBounds; + +/** + * fully bounded eoIntBound == interval + */ +class eoIntInterval : public eoIntBounds +{ +public : + virtual ~eoIntInterval(){} + + /** + Simple bounds = minimum and maximum (allowed) + */ + eoIntInterval(long int _min=0, long int _max=1) : + repMinimum(_min), repMaximum(_max), repRange(_max-_min) + { + if (repRange<=0) + throw std::logic_error("Void range in eoIntBounds"); + } + + // accessors + virtual long int minimum() const { return repMinimum; } + virtual long int maximum() const { return repMaximum; } + virtual long int range() const { return repRange; } + + // description + virtual bool isBounded(void) const {return true;} + virtual bool hasNoBoundAtAll(void) const {return false;} + virtual bool isMinBounded(void) const {return true;} + virtual bool isMaxBounded(void) const {return true;} + + virtual double uniform(eoRng & _rng = eo::rng) const + { + return repMinimum + _rng.uniform(repRange); + } + + virtual long int random(eoRng & _rng = eo::rng) const + { + return repMinimum + _rng.random(repRange); + } + + // says if a given double is within the bounds + virtual bool isInBounds(double _r) const + { + if (_r < repMinimum) + return false; + if (_r > repMaximum) + return false; + return true; + } + + // folds a value into bounds + virtual void foldsInBounds(double & _r) const + { + long iloc; + double dlargloc = 2 * range() ; + + if (fabs(_r) > 1.0E9) // iloc too large! + { + _r = uniform(); + return; + } + + if ( (_r > maximum()) ) + { + iloc = (long) ( (_r-minimum()) / dlargloc ) ; + _r -= dlargloc * iloc ; + if ( _r > maximum() ) + _r = 2*maximum() - _r ; + } + + if (_r < minimum()) + { + iloc = (long) ( (maximum()-_r) / dlargloc ) ; + _r += dlargloc * iloc ; + if (_r < minimum()) + _r = 2*minimum() - _r ; + } + } + + // truncates to the bounds + virtual void truncate(double & _r) const + { + if (_r < repMinimum) + _r = repMinimum; + else if (_r > repMaximum) + _r = repMaximum; + return; + } + + // methods from eoPersistent + /** + * Read object. + * @param _is A std::istream. + * but reading should not be done here, because of bound problems + * see eoIntVectorBounds + */ + virtual void readFrom(std::istream& _is) + { + throw std::runtime_error("Should not use eoIntInterval::readFrom"); + } + + /** + * Write object. It's called printOn since it prints the object on a stream. + * @param _os A std::ostream. + */ + virtual void printOn(std::ostream& _os) const + { + _os << "[" << repMinimum << "," << repMaximum << "]"; + } + + /** for memory managements - ugly */ + virtual eoIntBounds * dup() const + { + return new eoIntInterval(*this); + } + +private : + long int repMinimum; + long int repMaximum; + long int repRange; // to minimize operations ??? +}; + +/** + * an eoIntBound bounded from below only + */ +class eoIntBelowBound : public eoIntBounds +{ +public : + virtual ~eoIntBelowBound(){} + /** + Simple bounds = minimum + */ + eoIntBelowBound(long int _min=0) : + repMinimum(_min) + {} + + // accessors + virtual long int minimum() const { return repMinimum; } + + virtual long int maximum() const + { + throw std::logic_error("Trying to get maximum of eoIntBelowBound"); + } + virtual long int range() const + { + throw std::logic_error("Trying to get range of eoIntBelowBound"); + } + + virtual double uniform(eoRng & _rng = eo::rng) const + { + throw std::logic_error("Trying to generate uniform values in eoIntBelowBound"); + } + virtual long int random(eoRng & _rng = eo::rng) const + { + throw std::logic_error("Trying to generate uniform values in eoIntBelowBound"); + } + + // description + virtual bool isBounded(void) const {return false;} + virtual bool hasNoBoundAtAll(void) const {return false;} + virtual bool isMinBounded(void) const {return true;} + virtual bool isMaxBounded(void) const {return false;} + + // says if a given double is within the bounds + virtual bool isInBounds(double _r) const + { + if (_r < repMinimum) + return false; + return true; + } + + // folds a value into bounds + virtual void foldsInBounds(double & _r) const + { + // easy as a pie: symmetry w.r.t. minimum + if (_r < repMinimum) // nothing to do otherwise + _r = 2*repMinimum - _r; + return ; + } + + // truncates to the bounds + virtual void truncate(double & _r) const + { + if (_r < repMinimum) + _r = repMinimum; + return; + } + + // methods from eoPersistent + /** + * Read object. + * @param _is A std::istream. + * but reading should not be done here, because of bound problems + * see eoIntVectorBounds + */ + virtual void readFrom(std::istream& _is) + { + throw std::runtime_error("Should not use eoIntBelowBound::readFrom"); + } + + /** + * Write object. It's called printOn since it prints the object on a stream. + * @param _os A std::ostream. + */ + virtual void printOn(std::ostream& _os) const + { + _os << "[" << repMinimum << ",+inf]"; + } + + /** for memory managements - ugly */ + virtual eoIntBounds * dup() const + { + return new eoIntBelowBound(*this); + } + +private : + long int repMinimum; +}; + +/** +An eoIntBound bounded from above only +*/ +class eoIntAboveBound : public eoIntBounds +{ +public : + virtual ~eoIntAboveBound(){} + + /** + Simple bounds = minimum + */ + eoIntAboveBound(long int _max=0) : + repMaximum(_max) + {} + + // accessors + virtual long int maximum() const { return repMaximum; } + + virtual long int minimum() const + { + throw std::logic_error("Trying to get minimum of eoIntAboveBound"); + } + virtual long int range() const + { + throw std::logic_error("Trying to get range of eoIntAboveBound"); + } + + virtual double uniform(eoRng & _rng = eo::rng) const + { + throw std::logic_error("Trying to generate uniform values in eoIntAboveBound"); + } + virtual long int random(eoRng & _rng = eo::rng) const + { + throw std::logic_error("Trying to generate uniform values in eoIntAboveBound"); + } + + // description + virtual bool isBounded(void) const {return false;} + virtual bool hasNoBoundAtAll(void) const {return false;} + virtual bool isMinBounded(void) const {return false;} + virtual bool isMaxBounded(void) const {return true;} + + // says if a given double is within the bounds + virtual bool isInBounds(double _r) const + { + if (_r > repMaximum) + return false; + return true; + } + + // folds a value into bounds + virtual void foldsInBounds(double & _r) const + { + // easy as a pie: symmetry w.r.t. maximum + if (_r > repMaximum) // nothing to do otherwise + _r = 2*repMaximum - _r; + return ; + } + + // truncates to the bounds + virtual void truncate(double & _r) const + { + if (_r > repMaximum) + _r = repMaximum; + return; + } + + // methods from eoPersistent + /** + * Read object. + * @param _is A std::istream. + * but reading should not be done here, because of bound problems + * see eoIntVectorBounds + */ + virtual void readFrom(std::istream& _is) + { + throw std::runtime_error("Should not use eoIntAboveBound::readFrom"); + } + + /** + * Write object. It's called printOn since it prints the object on a stream. + * @param _os A std::ostream. + */ + virtual void printOn(std::ostream& _os) const + { + _os << "[-inf," << repMaximum << "]"; + } + + /** for memory managements - ugly */ + virtual eoIntBounds * dup() const + { + return new eoIntAboveBound(*this); + } + +private : + long int repMaximum; +}; + +//////////////////////// tentative for a general BOUND class that is constructed from a string + +class eoGeneralIntBounds : public eoIntBounds +{ +public: + /** Ctor: from a string, chooses the type of bound */ + eoGeneralIntBounds(std::string _s) + { + repBound = getBoundsFromString(_s); + } + + /** Need a Cpy Ctor because we are allocating memory */ + eoGeneralIntBounds(eoGeneralIntBounds & _b) + { + // replicate the embedded bound (I'm pretty sure there is another + // way to do that !!! + + bool minBounded = _b.isMinBounded(); + bool maxBounded = _b.isMaxBounded(); + long int minimum, maximum; + const eoIntBounds & bb = _b.theBounds(); + if (minBounded) minimum = bb.minimum(); + if (maxBounded) maximum = bb.maximum(); + + if (minBounded && maxBounded) + repBound = new eoIntInterval(minimum, maximum); + else if (!minBounded && !maxBounded) // no bound at all + repBound = new eoIntNoBounds; + else if (!minBounded && maxBounded) + repBound = new eoIntAboveBound(maximum); + else if (minBounded && !maxBounded) + repBound = new eoIntBelowBound(minimum); + } + + eoGeneralIntBounds& operator=(const eoGeneralIntBounds& _b) + { + // replicate the embedded bound (I'm pretty sure there is another + // way to do that !!! + + bool minBounded = _b.isMinBounded(); + bool maxBounded = _b.isMaxBounded(); + long int minimum, maximum; + const eoIntBounds & bb = _b.theBounds(); + if (minBounded) minimum = bb.minimum(); + if (maxBounded) maximum = bb.maximum(); + + // first delete the embedded bounds if necessary + if (repBound) + delete repBound; + // now reallocate + if (minBounded && maxBounded) + repBound = new eoIntInterval(minimum, maximum); + else if (!minBounded && !maxBounded) // no bound at all + repBound = new eoIntNoBounds; + else if (!minBounded && maxBounded) + repBound = new eoIntAboveBound(maximum); + else if (minBounded && !maxBounded) + repBound = new eoIntBelowBound(minimum); + return (*this); + } + + + /** Need a Dtor because we allocate an actual bound */ + ~eoGeneralIntBounds() + { + delete repBound; + } + + ///// and now all methods from the embedded bounds + /** Self-Test: true if ***both*** a min and a max + */ + virtual bool isBounded(void) const {return repBound->isBounded();} + + /** Self-Test: true if no min ***and*** no max + * hence no further need to test/truncate/fold anything + */ + virtual bool hasNoBoundAtAll(void) const {return repBound->hasNoBoundAtAll();} + + /** Self-Test: bounded from below??? + */ + virtual bool isMinBounded(void) const {return repBound->isMinBounded();} + + /** Self-Test: bounded from above??? + */ + virtual bool isMaxBounded(void) const {return repBound->isMaxBounded();} + + /** Test on a value: is it in bounds? + */ + virtual bool isInBounds(double _x) const {return repBound->isInBounds(_x);} + + /** Put value back into bounds - by folding back and forth + */ + virtual void foldsInBounds(double & _x) const {return repBound->foldsInBounds(_x);} + + /** Put value back into bounds - by truncating to a boundary value + */ + virtual void truncate(double & _x) const {return repBound->truncate(_x);} + + /** get minimum value + * @std::exception if does not exist + */ + virtual long int minimum() const {return repBound->minimum();} + /** get maximum value + * @std::exception if does not exist + */ + virtual long int maximum() const {return repBound->maximum();} + /** get range + * @std::exception if unbounded + */ + virtual long int range() const {return repBound->range();} + + /** random generator of uniform doubles in bounds + * @std::exception if unbounded + */ + virtual double uniform(eoRng & _rng = eo::rng) const {return repBound->uniform();} + + /** random generator of uniform ints in bounds + * @std::exception if unbounded + */ + virtual long int random(eoRng & _rng = eo::rng) const {return repBound->random();} + + /** for memory managements - ugly */ + virtual eoIntBounds * dup() const {return repBound->dup();} + + /** for efficiency, it's better to use the embedded boud directly */ + const eoIntBounds & theBounds() const { return *repBound;} + + /** don't forget the printOn method - + * again that of the embedded bound + */ + virtual void printOn(std::ostream& _os) const + { + repBound->printOn(_os); + } + + /** no readFrom ??? Have to check that later */ + virtual void readFrom(std::istream& _is) + { + std::string s; + _is >> s; + if (repBound) + delete repBound; + repBound = getBoundsFromString(s); + } + +private: + // reading from a string + eoIntBounds * getBoundsFromString(std::string); + + eoIntBounds * repBound; +}; + + +#endif diff --git a/eo/src/utils/eoRealBounds.cpp b/eo/src/utils/eoRealBounds.cpp index 4b8fabb8..cd59620b 100644 --- a/eo/src/utils/eoRealBounds.cpp +++ b/eo/src/utils/eoRealBounds.cpp @@ -17,6 +17,7 @@ #include "eoRealBounds.h" #include "eoRealVectorBounds.h" + // the global dummy bounds // (used for unbounded variables when bounds are required) eoRealNoBounds eoDummyRealNoBounds; @@ -46,14 +47,14 @@ double read_double(std::string _s) return r; } -int read_int(std::string _s) +long int read_int(std::string _s) { #ifdef HAVE_SSTREAM std::istringstream is(_s); #else std::istrstream is(_s.c_str()); #endif - int i; + long int i; is >> i; return i; } @@ -191,3 +192,80 @@ void eoRealVectorBounds::adjust_size(unsigned _dim) factor[factor.size()-1] += missing; } } + +/** the constructor for eoGeneralRealBound - from a string + * very similar to the eoRealVectorBounds::readFrom above + * but was written much later so the readFrom does not call this one + * as it should do + */ +eoRealBounds* eoGeneralRealBounds::getBoundsFromString(std::string _value) +{ + // now read + std::string delim(",; "); + std::string beginOrClose("[(])"); + if (!remove_leading(_value, delim)) // only delimiters were left + throw std::runtime_error("Syntax error in eoGeneralRealBounds Ctor"); + + // look for opening char + size_t posDeb = _value.find_first_of(beginOrClose); // allow ]a,b] + if (posDeb >= _value.size()) // nothing left to read + throw std::runtime_error("Syntax error in eoGeneralRealBounds Ctor"); + + // ending char: next {}() after posDeb + size_t posFin = _value.find_first_of(beginOrClose,posDeb+1); + if (posFin >= _value.size()) // not found + throw std::runtime_error("Syntax error in eoGeneralRealBounds Ctor"); + + // the bounds + std::string sBounds = _value.substr(posDeb+1, posFin-posDeb-1); + // and remove from original string + _value = _value.substr(posFin+1); + + remove_leading(sBounds, delim); + size_t posDelim = sBounds.find_first_of(delim); + if (posDelim >= sBounds.size()) + throw std::runtime_error("Syntax error in eoGeneralRealBounds Ctor"); + + bool minBounded=false, maxBounded=false; + double minBound=0, maxBound=0; + + // min bound + std::string sMinBounds = sBounds.substr(0,posDelim); + + if ( (sMinBounds != std::string("-inf")) && + (sMinBounds != std::string("-infinity")) + ) + { + minBounded = true; + minBound = read_double(sMinBounds); + } + + // max bound + size_t posEndDelim = sBounds.find_first_not_of(delim,posDelim); + + std::string sMaxBounds = sBounds.substr(posEndDelim); + + if ( (sMaxBounds != std::string("+inf")) && + (sMaxBounds != std::string("+infinity")) + ) + { + maxBounded = true; + maxBound = read_double(sMaxBounds); + } + + // now create the embedded eoRealBounds object + eoRealBounds * locBound; + if (minBounded && maxBounded) + { + if (maxBound <= minBound) + throw std::runtime_error("Syntax error in eoGeneralRealBounds Ctor"); + locBound = new eoRealInterval(minBound, maxBound); + } + else if (!minBounded && !maxBounded) // no bound at all + locBound = new eoRealNoBounds; + else if (!minBounded && maxBounded) + locBound = new eoRealAboveBound(maxBound); + else if (minBounded && !maxBounded) + locBound = new eoRealBelowBound(minBound); + return locBound; +} diff --git a/eo/src/utils/eoRealBounds.h b/eo/src/utils/eoRealBounds.h index 0ed662b0..fa69e440 100644 --- a/eo/src/utils/eoRealBounds.h +++ b/eo/src/utils/eoRealBounds.h @@ -79,53 +79,53 @@ public: /** Self-Test: true if ***both*** a min and a max */ - virtual bool isBounded(void) = 0; + virtual bool isBounded(void) const = 0; /** Self-Test: true if no min ***and*** no max * hence no further need to test/truncate/fold anything */ - virtual bool hasNoBoundAtAll(void) = 0; + virtual bool hasNoBoundAtAll(void) const = 0; /** Self-Test: bounded from below??? */ - virtual bool isMinBounded(void) = 0; + virtual bool isMinBounded(void) const = 0; /** Self-Test: bounded from above??? */ - virtual bool isMaxBounded(void) = 0; + virtual bool isMaxBounded(void) const = 0; /** Test on a value: is it in bounds? */ - virtual bool isInBounds(double) = 0; + virtual bool isInBounds(double) const = 0; /** Put value back into bounds - by folding back and forth */ - virtual void foldsInBounds(double &) = 0; + virtual void foldsInBounds(double &) const = 0; /** Put value back into bounds - by truncating to a boundary value */ - virtual void truncate(double &) = 0; + virtual void truncate(double &) const = 0; /** get minimum value * @std::exception if does not exist */ - virtual double minimum() = 0; + virtual double minimum() const = 0 ; /** get maximum value * @std::exception if does not exist */ - virtual double maximum() = 0; + virtual double maximum() const = 0 ; /** get range * @std::exception if unbounded */ - virtual double range() = 0; + virtual double range() const = 0; /** random generator of uniform numbers in bounds * @std::exception if unbounded */ - virtual double uniform(eoRng & _rng = eo::rng) = 0; + virtual double uniform(eoRng & _rng = eo::rng) const = 0; /** for memory managements - ugly */ - virtual eoRealBounds * dup() = 0; + virtual eoRealBounds * dup() const = 0; }; /** A default class for unbounded variables @@ -135,28 +135,28 @@ class eoRealNoBounds : public eoRealBounds public: virtual ~eoRealNoBounds(){} - virtual bool isBounded(void) {return false;} - virtual bool hasNoBoundAtAll(void) {return true;} - virtual bool isMinBounded(void) {return false;} - virtual bool isMaxBounded(void) {return false;} - virtual void foldsInBounds(double &) {return;} - virtual void truncate(double &) {return;} - virtual bool isInBounds(double) {return true;} + virtual bool isBounded(void) const {return false;} + virtual bool hasNoBoundAtAll(void) const {return true;} + virtual bool isMinBounded(void) const {return false;} + virtual bool isMaxBounded(void) const {return false;} + virtual void foldsInBounds(double &) const {return;} + virtual void truncate(double &) const {return;} + virtual bool isInBounds(double) const {return true;} - virtual double minimum() + virtual double minimum() const { throw std::logic_error("Trying to get minimum of unbounded eoRealBounds"); } - virtual double maximum() + virtual double maximum() const { throw std::logic_error("Trying to get maximum of unbounded eoRealBounds"); } - virtual double range() + virtual double range() const { throw std::logic_error("Trying to get range of unbounded eoRealBounds"); } - virtual double uniform(eoRng & _rng = eo::rng) + virtual double uniform(eoRng & _rng = eo::rng) const { throw std::logic_error("Trying to generate uniform values in unbounded eoRealBounds"); } @@ -183,7 +183,7 @@ public: } /** for memory managements - ugly */ - virtual eoRealBounds * dup() + virtual eoRealBounds * dup() const { return new eoRealNoBounds(*this); } @@ -212,23 +212,23 @@ public : } // accessors - virtual double minimum() { return repMinimum; } - virtual double maximum() { return repMaximum; } - virtual double range() { return repRange; } + virtual double minimum() const { return repMinimum; } + virtual double maximum() const { return repMaximum; } + virtual double range() const { return repRange; } // description - virtual bool isBounded(void) {return true;} - virtual bool hasNoBoundAtAll(void) {return false;} - virtual bool isMinBounded(void) {return true;} - virtual bool isMaxBounded(void) {return true;} + virtual bool isBounded(void) const {return true;} + virtual bool hasNoBoundAtAll(void) const {return false;} + virtual bool isMinBounded(void) const {return true;} + virtual bool isMaxBounded(void) const {return true;} - virtual double uniform(eoRng & _rng = eo::rng) + virtual double uniform(eoRng & _rng = eo::rng) const { return repMinimum + _rng.uniform(repRange); } // says if a given double is within the bounds - virtual bool isInBounds(double _r) + virtual bool isInBounds(double _r) const { if (_r < repMinimum) return false; @@ -238,7 +238,7 @@ public : } // folds a value into bounds - virtual void foldsInBounds(double & _r) + virtual void foldsInBounds(double & _r) const { long iloc; double dlargloc = 2 * range() ; @@ -267,7 +267,7 @@ public : } // truncates to the bounds - virtual void truncate(double & _r) + virtual void truncate(double & _r) const { if (_r < repMinimum) _r = repMinimum; @@ -298,7 +298,7 @@ public : } /** for memory managements - ugly */ - virtual eoRealBounds * dup() + virtual eoRealBounds * dup() const { return new eoRealInterval(*this); } @@ -324,31 +324,31 @@ public : {} // accessors - virtual double minimum() { return repMinimum; } + virtual double minimum() const { return repMinimum; } - virtual double maximum() + virtual double maximum() const { throw std::logic_error("Trying to get maximum of eoRealBelowBound"); } - virtual double range() + virtual double range() const { throw std::logic_error("Trying to get range of eoRealBelowBound"); } // random generators - virtual double uniform(eoRng & _rng = eo::rng) + virtual double uniform(eoRng & _rng = eo::rng) const { throw std::logic_error("Trying to generate uniform values in eoRealBelowBound"); } // description - virtual bool isBounded(void) {return false;} - virtual bool hasNoBoundAtAll(void) {return false;} - virtual bool isMinBounded(void) {return true;} - virtual bool isMaxBounded(void) {return false;} + virtual bool isBounded(void) const {return false;} + virtual bool hasNoBoundAtAll(void) const {return false;} + virtual bool isMinBounded(void) const {return true;} + virtual bool isMaxBounded(void) const {return false;} // says if a given double is within the bounds - virtual bool isInBounds(double _r) + virtual bool isInBounds(double _r) const { if (_r < repMinimum) return false; @@ -356,7 +356,7 @@ public : } // folds a value into bounds - virtual void foldsInBounds(double & _r) + virtual void foldsInBounds(double & _r) const { // easy as a pie: symmetry w.r.t. minimum if (_r < repMinimum) // nothing to do otherwise @@ -365,7 +365,7 @@ public : } // truncates to the bounds - virtual void truncate(double & _r) + virtual void truncate(double & _r) const { if (_r < repMinimum) _r = repMinimum; @@ -394,7 +394,7 @@ public : } /** for memory managements - ugly */ - virtual eoRealBounds * dup() + virtual eoRealBounds * dup() const { return new eoRealBelowBound(*this); } @@ -419,31 +419,31 @@ public : {} // accessors - virtual double maximum() { return repMaximum; } + virtual double maximum() const { return repMaximum; } - virtual double minimum() + virtual double minimum() const { throw std::logic_error("Trying to get minimum of eoRealAboveBound"); } - virtual double range() + virtual double range() const { throw std::logic_error("Trying to get range of eoRealAboveBound"); } // random generators - virtual double uniform(eoRng & _rng = eo::rng) + virtual double uniform(eoRng & _rng = eo::rng) const { throw std::logic_error("Trying to generate uniform values in eoRealAboveBound"); } // description - virtual bool isBounded(void) {return false;} - virtual bool hasNoBoundAtAll(void) {return false;} - virtual bool isMinBounded(void) {return false;} - virtual bool isMaxBounded(void) {return true;} + virtual bool isBounded(void) const {return false;} + virtual bool hasNoBoundAtAll(void) const {return false;} + virtual bool isMinBounded(void) const {return false;} + virtual bool isMaxBounded(void) const {return true;} // says if a given double is within the bounds - virtual bool isInBounds(double _r) + virtual bool isInBounds(double _r) const { if (_r > repMaximum) return false; @@ -451,7 +451,7 @@ public : } // folds a value into bounds - virtual void foldsInBounds(double & _r) + virtual void foldsInBounds(double & _r) const { // easy as a pie: symmetry w.r.t. maximum if (_r > repMaximum) // nothing to do otherwise @@ -460,7 +460,7 @@ public : } // truncates to the bounds - virtual void truncate(double & _r) + virtual void truncate(double & _r) const { if (_r > repMaximum) _r = repMaximum; @@ -489,7 +489,7 @@ public : } /** for memory managements - ugly */ - virtual eoRealBounds * dup() + virtual eoRealBounds * dup() const { return new eoRealAboveBound(*this); } @@ -498,4 +498,152 @@ private : double repMaximum; }; +//////////////////////// tentative for a general BOUND class that is constructed from a string + +class eoGeneralRealBounds : public eoRealBounds +{ +public: + /** Ctor: from a string, chooses the type of bound */ + eoGeneralRealBounds(std::string _s) + { + repBound = getBoundsFromString(_s); + } + + /** Need a Cpy Ctor because we are allocating memory */ + eoGeneralRealBounds(eoGeneralRealBounds & _b) + { + // replicate the embedded bound (I'm pretty sure there is another + // way to do that !!! + + bool minBounded = _b.isMinBounded(); + bool maxBounded = _b.isMaxBounded(); + double minimum, maximum; + const eoRealBounds & bb = _b.theBounds(); + if (minBounded) minimum = bb.minimum(); + if (maxBounded) maximum = bb.maximum(); + + if (minBounded && maxBounded) + repBound = new eoRealInterval(minimum, maximum); + else if (!minBounded && !maxBounded) // no bound at all + repBound = new eoRealNoBounds; + else if (!minBounded && maxBounded) + repBound = new eoRealAboveBound(maximum); + else if (minBounded && !maxBounded) + repBound = new eoRealBelowBound(minimum); + } + + eoGeneralRealBounds& operator=(const eoGeneralRealBounds& _b) + { + // replicate the embedded bound (I'm pretty sure there is another + // way to do that !!! + + bool minBounded = _b.isMinBounded(); + bool maxBounded = _b.isMaxBounded(); + double minimum, maximum; + const eoRealBounds & bb = _b.theBounds(); + if (minBounded) minimum = bb.minimum(); + if (maxBounded) maximum = bb.maximum(); + + // first delete the embedded bounds if necessary + if (repBound) + delete repBound; + // now reallocate + if (minBounded && maxBounded) + repBound = new eoRealInterval(minimum, maximum); + else if (!minBounded && !maxBounded) // no bound at all + repBound = new eoRealNoBounds; + else if (!minBounded && maxBounded) + repBound = new eoRealAboveBound(maximum); + else if (minBounded && !maxBounded) + repBound = new eoRealBelowBound(minimum); + return (*this); + } + + + /** Need a Dtor because we allocate an actual bound */ + ~eoGeneralRealBounds() + { + delete repBound; + } + + ///// and now all methods from the embedded bounds + /** Self-Test: true if ***both*** a min and a max + */ + virtual bool isBounded(void) const {return repBound->isBounded();} + + /** Self-Test: true if no min ***and*** no max + * hence no further need to test/truncate/fold anything + */ + virtual bool hasNoBoundAtAll(void) const {return repBound->hasNoBoundAtAll();} + + /** Self-Test: bounded from below??? + */ + virtual bool isMinBounded(void) const {return repBound->isMinBounded();} + + /** Self-Test: bounded from above??? + */ + virtual bool isMaxBounded(void) const {return repBound->isMaxBounded();} + + /** Test on a value: is it in bounds? + */ + virtual bool isInBounds(double _x) const {return repBound->isInBounds(_x);} + + /** Put value back into bounds - by folding back and forth + */ + virtual void foldsInBounds(double & _x) const {return repBound->foldsInBounds(_x);} + + /** Put value back into bounds - by truncating to a boundary value + */ + virtual void truncate(double & _x) const {return repBound->truncate(_x);} + + /** get minimum value + * @std::exception if does not exist + */ + virtual double minimum() const {return repBound->minimum();} + /** get maximum value + * @std::exception if does not exist + */ + virtual double maximum() const {return repBound->maximum();} + /** get range + * @std::exception if unbounded + */ + virtual double range() const {return repBound->range();} + + /** random generator of uniform numbers in bounds + * @std::exception if unbounded + */ + virtual double uniform(eoRng & _rng = eo::rng) const {return repBound->uniform();} + + /** for memory managements - ugly */ + virtual eoRealBounds * dup() const {return repBound->dup();} + + /** for efficiency, it's better to use the embedded boud directly */ + const eoRealBounds & theBounds() const { return *repBound;} + + /** don't forget the printOn method - + * again that of the embedded bound + */ + virtual void printOn(std::ostream& _os) const + { + repBound->printOn(_os); + } + + /** no readFrom ??? Have to check that later */ + virtual void readFrom(std::istream& _is) + { + std::string s; + _is >> s; + if (repBound) + delete repBound; + repBound = getBoundsFromString(s); + } + +private: + // reading from a string + eoRealBounds * getBoundsFromString(std::string); + + eoRealBounds * repBound; +}; + + #endif