From 2b46277eedef09dc032410f94751cf90e2b3843f Mon Sep 17 00:00:00 2001 From: evomarc Date: Mon, 29 Jan 2001 10:25:44 +0000 Subject: [PATCH] Added the truncate and the hasNoBoundAtAll methods in eoRealBounds. The former simply set values to the boundary values in case they are out The latter allows to short-cut all bound-checks when no need SOme day I will put this in utils, and have a eoRealBounds.cpp in the pre-compiled library --- eo/src/es/eoGenericRealOp.h | 6 +- eo/src/es/eoRealBounds.h | 295 ++++++++++++++++++++++++++++++++---- 2 files changed, 272 insertions(+), 29 deletions(-) diff --git a/eo/src/es/eoGenericRealOp.h b/eo/src/es/eoGenericRealOp.h index 88aa5a29..c29fd162 100644 --- a/eo/src/es/eoGenericRealOp.h +++ b/eo/src/es/eoGenericRealOp.h @@ -222,7 +222,7 @@ template class eoGenericSegmentCrossover: public eoGenericQuadOp double r1, r2, fact; double alphaMin = -alpha; double alphaMax = 1+alpha; - if (alpha == 0.0) // no check to perform + if ( (alpha == 0.0) || bounds.hasNoBoundAtAll() ) // no check to perform fact = -alpha + rng.uniform(range); // in [-alpha,1+alpha) else // look for the bounds for fact { @@ -319,7 +319,7 @@ template class eoGenericArithmeticCrossover: { unsigned i; double r1, r2, fact; - if (alpha == 0.0) // no check to perform + if ( (alpha == 0.0) || bounds.hasNoBoundAtAll() ) // no check to perform for (i=0; i<_eo1.size(); i++) { r1=_eo1[i]; @@ -328,7 +328,7 @@ template class eoGenericArithmeticCrossover: _eo1[i] = fact * r1 + (1-fact) * r2; _eo2[i] = (1-fact) * r1 + fact * r2; } - else // check the bounds + else // must check the bounds for (i=0; i<_eo1.size(); i++) { r1=_eo1[i]; diff --git a/eo/src/es/eoRealBounds.h b/eo/src/es/eoRealBounds.h index 02174487..be544a99 100644 --- a/eo/src/es/eoRealBounds.h +++ b/eo/src/es/eoRealBounds.h @@ -73,33 +73,71 @@ to the elements of the vector. class eoRealBounds { public: + virtual ~eoRealBounds(){} + + /** Self-Test: true if ***both*** a min and a max + */ virtual bool isBounded(void) = 0; + + /** Self-Test: true if no min ***and*** no max + * hence no further need to test/truncate/fold anything + */ + virtual bool hasNoBoundAtAll(void) = 0; + + /** Self-Test: bounded from below??? + */ virtual bool isMinBounded(void) = 0; + + /** Self-Test: bounded from above??? + */ virtual bool isMaxBounded(void) = 0; - virtual void foldsInBounds(double &) = 0; + + /** Test on a value: is it in bounds? + */ virtual bool isInBounds(double) = 0; - // accessors + /** Put value back into bounds - by folding back and forth + */ + virtual void foldsInBounds(double &) = 0; + + /** Put value back into bounds - by truncating to a boundary value + */ + virtual void truncate(double &) = 0; + + /** get minimum value + * @exception if does not exist + */ virtual double minimum() = 0; + /** get maximum value + * @exception if does not exist + */ virtual double maximum() = 0; + /** get range + * @exception if unbounded + */ virtual double range() = 0; - // random generators + /** random generator of uniform numbers in bounds + * @exception if unbounded + */ virtual double uniform(eoRng & _rng = eo::rng) = 0; }; +/** A default class for unbounded variables + */ 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;} - // accessors virtual double minimum() { throw logic_error("Trying to get minimum of unbounded eoRealBounds"); @@ -113,17 +151,19 @@ public: throw logic_error("Trying to get range of unbounded eoRealBounds"); } - // random generators virtual double uniform(eoRng & _rng = eo::rng) { throw logic_error("Trying to generate uniform values in unbounded eoRealBounds"); } }; -/* fully bounded == interval */ +////////////////////////////////////////////////////////////// +// fully bounded == interval +///////////////////////////////////////////////////////////// class eoRealInterval : public eoRealBounds { public : + virtual ~eoRealInterval(){} /** Simple bounds = minimum and maximum (allowed) @@ -142,10 +182,11 @@ public : // 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;} - double uniform(eoRng & _rng = eo::rng) + virtual double uniform(eoRng & _rng = eo::rng) { return repMinimum + _rng.uniform(repRange); } @@ -161,7 +202,7 @@ public : } // folds a value into bounds - void foldsInBounds(double & _r) + virtual void foldsInBounds(double & _r) { long iloc; double dlargloc = 2 * range() ; @@ -189,17 +230,171 @@ public : } } + // truncates to the bounds + virtual void truncate(double & _r) + { + if (_r < repMinimum) + _r = repMinimum; + else if (_r > repMaximum) + _r = repMaximum; + return; + } + private : double repMinimum; double repMaximum; double repRange; // to minimize operations ??? }; +////////////////////////////////////////////////////////////// +// bounded from below +///////////////////////////////////////////////////////////// +class eoRealBelowBound : public eoRealBounds +{ +public : + virtual ~eoRealBelowBound(){} + /** + Simple bounds = minimum + */ + eoRealBelowBound(double _min=0) : + repMinimum(_min) + {} + + // accessors + virtual double minimum() { return repMinimum; } + + virtual double maximum() + { + throw logic_error("Trying to get maximum of eoRealBelowBound"); + } + virtual double range() + { + throw logic_error("Trying to get range of eoRealBelowBound"); + } + + // random generators + virtual double uniform(eoRng & _rng = eo::rng) + { + throw 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;} + + // says if a given double is within the bounds + virtual bool isInBounds(double _r) + { + if (_r < repMinimum) + return false; + return true; + } + + // folds a value into bounds + virtual void foldsInBounds(double & _r) + { + // 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) + { + if (_r < repMinimum) + _r = repMinimum; + return; + } +private : + double repMinimum; +}; + +////////////////////////////////////////////////////////////// +// bounded from above +///////////////////////////////////////////////////////////// +class eoRealAboveBound : public eoRealBounds +{ +public : + virtual ~eoRealAboveBound(){} + + /** + Simple bounds = minimum + */ + eoRealAboveBound(double _max=0) : + repMaximum(_max) + {} + + // accessors + virtual double maximum() { return repMaximum; } + + virtual double minimum() + { + throw logic_error("Trying to get minimum of eoRealAboveBound"); + } + virtual double range() + { + throw logic_error("Trying to get range of eoRealAboveBound"); + } + + // random generators + virtual double uniform(eoRng & _rng = eo::rng) + { + throw 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;} + + // says if a given double is within the bounds + virtual bool isInBounds(double _r) + { + if (_r > repMaximum) + return false; + return true; + } + + // folds a value into bounds + virtual void foldsInBounds(double & _r) + { + // 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) + { + if (_r > repMaximum) + _r = repMaximum; + return; + } + +private : + double repMaximum; +}; + +///////////////////////////////////////////////////////////////////// +// Vectorized versions +///////////////////////////////////////////////////////////////////// /** Class eoRealVectorBounds implements the vectorized version: it is basically a vector of eoRealBounds * and forwards all request to the elements of the vector. +Probably it would have been cleaner if there had been an empty base class +from which eoRealVectorBounds AND eoRealVectorNoBounds would have derived. +This is because I started to write eoRealVectorNoBounds as a + vector whose compoenents would have been eoRealNoBounds + but then realize that you don't necessarily have the dimension + when construction this vector - hence I added the eoRealVectorNoBounds ... +Anyone with extra time in his agenda is welcome to change that :-) */ class eoRealVectorBounds : public vector { @@ -207,14 +402,13 @@ public: // virtual desctructor (to avoid warining?) virtual ~eoRealVectorBounds(){} - // Default Ctor + /** Default Ctor + */ eoRealVectorBounds() : vector(0) {} - /** - Simple bounds = minimum and maximum (allowed) + /** Simple bounds = minimum and maximum (allowed) */ - // Ctor: same bonds for everybody, explicit eoRealVectorBounds(unsigned _dim, double _min, double _max) : vector(_dim, new eoRealInterval(_min, _max)) { @@ -222,7 +416,8 @@ public: throw std::logic_error("Void range in eoRealVectorBounds"); } - // Ctor: same bonds for everybody, given as a eoRealBounds + /** Ctor: same bonds for everybody, given as an eoRealBounds + */ eoRealVectorBounds(unsigned _dim, eoRealBounds & _bounds) : vector(_dim, &_bounds) {} @@ -265,36 +460,69 @@ public: return true; } - // these do not make any sense as vectors! + /** Self-test: true iff i_th component has no bounds at all + */ + virtual bool hasNoBoundAtAll(unsigned _i) + { + return (*this)[_i]->hasNoBoundAtAll(); + } + + /** Self-test: true iff all components have no bound at all + */ + virtual bool hasNoBoundAtAll(void) + { + for (unsigned i=0; ihasNoBoundAtAll()) + return false; + return true; + } + virtual bool isMinBounded(unsigned _i) { return (*this)[_i]->isMinBounded();} ; virtual bool isMaxBounded(unsigned _i) { return (*this)[_i]->isMaxBounded();} ; - /** Modifies a real value so that it stays in the bounds - i_th component + /** Folds a real value back into the bounds - i_th component */ virtual void foldsInBounds(unsigned _i, double & _r) { (*this)[_i]->foldsInBounds(_r); } - /** Modifies a vector of real value so that it stays in the bounds + /** Folds all variables of a vector of real values into the bounds */ virtual void foldsInBounds(vector & _v) { for (unsigned i=0; ifoldsInBounds(_v[i]); } } - /** test: is i_th component within the bounds + /** Truncates a real value to the bounds - i_th component + */ + virtual void truncate(unsigned _i, double & _r) + { + (*this)[_i]->truncate(_r); + } + + /** truncates all variables of a vector of real values to the bounds + */ + virtual void truncate(vector & _v) + { + for (unsigned i=0; itruncate(_v[i]); + } + } + + /** test: is i_th component within the bounds? */ virtual bool isInBounds(unsigned _i, double _r) { return (*this)[_i]->isInBounds(_r); } - /** test: are ALL components within the bounds + /** test: are ALL components within the bounds? */ virtual bool isInBounds(vector _v) { @@ -304,11 +532,15 @@ public: return true; } - // accessors + /** Accessors: will raise an exception if these do not exist + */ virtual double minimum(unsigned _i) {return (*this)[_i]->minimum();} virtual double maximum(unsigned _i) {return (*this)[_i]->maximum();} virtual double range(unsigned _i) {return (*this)[_i]->range();} + /** Computes the average range + * An exception will be raised if one of the component is unbounded + */ virtual double averageRange() { double r=0.0; @@ -318,6 +550,7 @@ public: } /** Generates a random number in i_th range + * An exception will be raised if one of the component is unbounded */ virtual double uniform(unsigned _i, eoRng & _rng = eo::rng) { @@ -326,6 +559,7 @@ public: } /** fills a vector with uniformly chosen variables in bounds + * An exception will be raised if one of the component is unbounded */ void uniform(vector & _v, eoRng & _rng = eo::rng) { @@ -338,6 +572,8 @@ public: }; /** the dummy unbounded eoRealVectorBounds: usefull if you don't need bounds! + * everything is inlined. + * Warning: we do need this class, and not only a vector */ class eoRealVectorNoBounds: public eoRealVectorBounds { @@ -354,44 +590,51 @@ public: virtual bool isBounded(unsigned) {return false;} virtual bool isBounded(void) {return false;} + + virtual bool hasNoBoundAtAll(unsigned) {return true;} + virtual bool hasNoBoundAtAll(void) {return true;} + virtual bool isMinBounded(unsigned) {return false;} virtual bool isMaxBounded(unsigned) {return false;} virtual void foldsInBounds(unsigned, double &) {return;} virtual void foldsInBounds(vector &) {return;} + virtual void truncate(unsigned, double &) {return;} + virtual void truncate(vector &) {return;} + virtual bool isInBounds(unsigned, double) {return true;} virtual bool isInBounds(vector) {return true;} // accessors virtual double minimum(unsigned) { - throw logic_error("Trying to get minimum of unbounded eoRealBounds"); + throw logic_error("Trying to get minimum of eoRealVectorNoBounds"); } virtual double maximum(unsigned) { - throw logic_error("Trying to get maximum of unbounded eoRealBounds"); + throw logic_error("Trying to get maximum of eoRealVectorNoBounds"); } virtual double range(unsigned) { - throw logic_error("Trying to get range of unbounded eoRealBounds"); + throw logic_error("Trying to get range of eoRealVectorNoBounds"); } virtual double averageRange() { - throw logic_error("Trying to get average range of unbounded eoRealBounds"); + throw logic_error("Trying to get average range of eoRealVectorNoBounds"); } // random generators virtual double uniform(unsigned, eoRng & _rng = eo::rng) { - throw logic_error("No uniform distribution on unbounded eoRealBounds"); + throw logic_error("No uniform distribution on eoRealVectorNoBounds"); } // fills a vector with uniformly chosen variables in bounds void uniform(vector &, eoRng & _rng = eo::rng) { - throw logic_error("No uniform distribution on unbounded eoRealBounds"); + throw logic_error("No uniform distribution on eoRealVectorNoBounds"); } };