From 09388c8ed57acb42f33ece6e69ba32df3d24432b Mon Sep 17 00:00:00 2001 From: evomarc Date: Tue, 8 May 2001 04:41:51 +0000 Subject: [PATCH] Bing change in eoRealBounds: it is now deriving from eoPersistent. More important, the eoRealVectorBounds, vectorized version (a vector has also become an eoPersistent object and now derives from an eoRealBaseVectorBounds class. A useful consequence (and actual motivatino) was to be able to have soem eoValueParam with all possibilities for input (see doc for Lesson4 in the tutorial for the syntax). --- eo/src/es/eoRealInitBounded.h | 2 +- eo/src/es/eoRealOp.h | 2 +- eo/src/es/make_genotype_real.h | 26 +- eo/src/es/make_op_es.h | 36 +-- eo/src/es/make_op_real.h | 44 +--- eo/src/utils/eoRealBounds.cpp | 167 +++++++++++- eo/src/utils/eoRealBounds.h | 394 +++++++++------------------- eo/src/utils/eoRealVectorBounds.h | 413 ++++++++++++++++++++++++++++++ eo/test/t-eoStateAndParser.cpp | 13 + eo/tutorial/html/eoLesson4.html | 112 ++++---- 10 files changed, 788 insertions(+), 421 deletions(-) create mode 100644 eo/src/utils/eoRealVectorBounds.h diff --git a/eo/src/es/eoRealInitBounded.h b/eo/src/es/eoRealInitBounded.h index f35a20b48..8d8fb05b6 100644 --- a/eo/src/es/eoRealInitBounded.h +++ b/eo/src/es/eoRealInitBounded.h @@ -31,7 +31,7 @@ #include #include #include -#include +#include /** Simple initialization for any EOT that derives from vector * uniformly in some bounds diff --git a/eo/src/es/eoRealOp.h b/eo/src/es/eoRealOp.h index 9e20201b8..9125b28a7 100644 --- a/eo/src/es/eoRealOp.h +++ b/eo/src/es/eoRealOp.h @@ -31,7 +31,7 @@ #include // swap_ranges #include #include -#include +#include //----------------------------------------------------------------------------- diff --git a/eo/src/es/make_genotype_real.h b/eo/src/es/make_genotype_real.h index 490071059..bd1fae01a 100644 --- a/eo/src/es/make_genotype_real.h +++ b/eo/src/es/make_genotype_real.h @@ -29,6 +29,7 @@ #include #include +#include // also need the parser and param includes #include #include @@ -66,27 +67,8 @@ eoEsChromInit & do_make_genotype(eoParameterLoader& _parser, eoState& _stat // for eoReal, only thing needed is the size eoValueParam& vecSize = _parser.createParam(unsigned(10), "vecSize", "The number of variables ", 'n',"Genotype Initialization"); - // to build an eoReal Initializer, we need bounds - eoValueParam& boundsParam = _parser.createParam(eoParamParamType("(0,1)"), "initBounds", "Bounds for uniform initialization", 'B', "Genotype Initialization"); - - eoParamParamType & ppBounds = boundsParam.value(); // pair > - // transform into a vector - vector v; - vector::iterator it; - for (it=ppBounds.second.begin(); itc_str()); - double r; - is >> r; - v.push_back(r); - } - // now create the eoRealVectorBounds object - eoRealVectorBounds * ptBounds = NULL; - if (v.size() == 2) // a min and a max for all variables - ptBounds = new eoRealVectorBounds(vecSize.value(), v[0], v[1]); - else // no time now - throw runtime_error("Sorry, only unique bounds for all variables implemented at the moment. Come back later"); - // we need to give ownership of this pointer to somebody + // to build an eoReal Initializer, we need bounds: [-1,1] by default + eoValueParam& boundsParam = _parser.createParam(eoRealVectorBounds(vecSize.value(),-1,1), "initBounds", "Bounds for initialization (MUST be bounded)", 'B', "Genotype Initialization"); // now some initial value for sigmas - even if useless? // shoudl be used in Normal mutation @@ -97,7 +79,7 @@ eoEsChromInit & do_make_genotype(eoParameterLoader& _parser, eoState& _stat throw runtime_error("Invalid sigma"); eoEsChromInit * init = - new eoEsChromInit(*ptBounds, sigmaParam.value()); + new eoEsChromInit(boundsParam.value(), sigmaParam.value()); // satore in state _state.storeFunctor(init); return *init; diff --git a/eo/src/es/make_op_es.h b/eo/src/es/make_op_es.h index fdda4cd35..846ac9e3c 100644 --- a/eo/src/es/make_op_es.h +++ b/eo/src/es/make_op_es.h @@ -70,41 +70,11 @@ template eoGenOp & do_make_op(eoParameterLoader& _parser, eoState& _state, eoRealInitBounded& _init) { - // First, decide whether the objective variables are bounded - eoValueParam& boundsParam = _parser.createParam(eoParamParamType("(0,1)"), "objectBounds", "Bounds for variables (unbounded if absent)", 'B', "Variation Operators"); - // get vector size unsigned vecSize = _init.size(); - // the bounds pointer - eoRealVectorBounds * ptBounds; - if (_parser.isItThere(boundsParam)) // otherwise, no bounds - { - /////Warning: this code should probably be replaced by creating - ///// some eoValueParam with specific implementation - //// in eoParser.cpp. At the moment, it is there (cf also make_genotype - eoParamParamType & ppBounds = boundsParam.value(); // pair > - // transform into a vector - vector v; - vector::iterator it; - for (it=ppBounds.second.begin(); itc_str()); - double r; - is >> r; - v.push_back(r); - } - // now create the eoRealVectorBounds object - if (v.size() == 2) // a min and a max for all variables - ptBounds = new eoRealVectorBounds(vecSize, v[0], v[1]); - else // no time now - throw runtime_error("Sorry, only unique bounds for all variables implemented at the moment. Come back later"); - // we need to give ownership of this pointer to somebody - /////////// end of temporary code - } - else // no param for bounds was given - ptBounds = new eoRealVectorNoBounds(vecSize); // DON'T USE eoDummyVectorNoBounds - // as it does not have any dimension + // First, decide whether the objective variables are bounded + eoValueParam& boundsParam = _parser.createParam(eoRealVectorBounds(vecSize,eoDummyRealNoBounds), "objectBounds", "Bounds for variables", 'B', "Variation Operators"); // now we read Pcross and Pmut, eoValueParam& operatorParam = _parser.createParam(string("SGA"), "operator", "Description of the operator (SGA only now)", 'o', "Variation Operators"); @@ -173,7 +143,7 @@ eoGenOp & do_make_op(eoParameterLoader& _parser, eoState& _state, eoRealIni // Proxy for the mutation parameters eoEsMutationInit mutateInit(_parser, "Variation Operators"); - eoEsMutate * ptMon = new eoEsMutate(mutateInit, *ptBounds); + eoEsMutate * ptMon = new eoEsMutate(mutateInit, boundsParam.value()); _state.storeFunctor(ptMon); // encapsulate into an eoGenop diff --git a/eo/src/es/make_op_real.h b/eo/src/es/make_op_real.h index 9de9c171b..75aa85699 100644 --- a/eo/src/es/make_op_real.h +++ b/eo/src/es/make_op_real.h @@ -67,41 +67,11 @@ template eoGenOp & do_make_op(eoParameterLoader& _parser, eoState& _state, eoRealInitBounded& _init) { - // First, decide whether the objective variables are bounded - eoValueParam& boundsParam = _parser.createParam(eoParamParamType("(0,1)"), "objectBounds", "Bounds for variables (unbounded if absent)", 'B', "Variation Operators"); - // get vector size unsigned vecSize = _init.size(); - // the bounds pointer - eoRealVectorBounds * ptBounds; - if (_parser.isItThere(boundsParam)) // otherwise, no bounds - { - /////Warning: this code should probably be replaced by creating - ///// some eoValueParam with specific implementation - //// in eoParser.cpp. At the moemnt, it is there (cf also make_genotype - eoParamParamType & ppBounds = boundsParam.value(); // pair > - // transform into a vector - vector v; - vector::iterator it; - for (it=ppBounds.second.begin(); itc_str()); - double r; - is >> r; - v.push_back(r); - } - // now create the eoRealVectorBounds object - if (v.size() == 2) // a min and a max for all variables - ptBounds = new eoRealVectorBounds(vecSize, v[0], v[1]); - else // no time now - throw runtime_error("Sorry, only unique bounds for all variables implemented at the moment. Come back later"); - // we need to give ownership of this pointer to somebody - /////////// end of temporary code - } - else // no param for bounds was given - ptBounds = new eoRealVectorNoBounds(vecSize); // DON'T USE eoDummyVectorNoBounds - // as it does not have any dimension + // First, decide whether the objective variables are bounded + eoValueParam& boundsParam = _parser.createParam(eoRealVectorBounds(vecSize,eoDummyRealNoBounds), "objectBounds", "Bounds for variables", 'B', "Variation Operators"); // this is a temporary version(!), // while Maarten codes the full tree-structured general operator input @@ -167,12 +137,12 @@ eoGenOp & do_make_op(eoParameterLoader& _parser, eoState& _state, eoRealIni if (bCross) { // segment crossover for bitstring - pass it the bounds - ptQuad = new eoSegmentCrossover(*ptBounds, alphaParam.value()); + ptQuad = new eoSegmentCrossover(boundsParam.value(), alphaParam.value()); _state.storeFunctor(ptQuad); ptCombinedQuadOp = new eoPropCombinedQuadOp(*ptQuad, segmentRateParam.value()); // hypercube crossover - ptQuad = new eoHypercubeCrossover(*ptBounds, alphaParam.value()); + ptQuad = new eoHypercubeCrossover(boundsParam.value(), alphaParam.value()); _state.storeFunctor(ptQuad); ptCombinedQuadOp->add(*ptQuad, hypercubeRateParam.value()); @@ -228,18 +198,18 @@ eoGenOp & do_make_op(eoParameterLoader& _parser, eoState& _state, eoRealIni { // uniform mutation on all components: // offspring(i) uniformly chosen in [parent(i)-epsilon, parent(i)+epsilon] - ptMon = new eoUniformMutation(*ptBounds, epsilonParam.value()); + ptMon = new eoUniformMutation(boundsParam.value(), epsilonParam.value()); _state.storeFunctor(ptMon); // create the CombinedMonOp ptCombinedMonOp = new eoPropCombinedMonOp(*ptMon, uniformMutRateParam.value()); // mutate exactly 1 component (uniformly) per individual - ptMon = new eoDetUniformMutation(*ptBounds, epsilonParam.value()); + ptMon = new eoDetUniformMutation(boundsParam.value(), epsilonParam.value()); _state.storeFunctor(ptMon); ptCombinedMonOp->add(*ptMon, detMutRateParam.value()); // mutate all component using Gaussian mutation - ptMon = new eoNormalMutation(*ptBounds, sigmaParam.value()); + ptMon = new eoNormalMutation(boundsParam.value(), sigmaParam.value()); _state.storeFunctor(ptMon); ptCombinedMonOp->add(*ptMon, normalMutRateParam.value()); _state.storeFunctor(ptCombinedMonOp); diff --git a/eo/src/utils/eoRealBounds.cpp b/eo/src/utils/eoRealBounds.cpp index 5349ed822..53d788012 100644 --- a/eo/src/utils/eoRealBounds.cpp +++ b/eo/src/utils/eoRealBounds.cpp @@ -1,7 +1,172 @@ #include +#include #include "eoRealBounds.h" +#include "eoRealVectorBounds.h" // the global dummy bounds // (used for unbounded variables when bounds are required) eoRealNoBounds eoDummyRealNoBounds; -eoRealVectorNoBounds eoDummyVectorNoBounds; +eoRealVectorNoBounds eoDummyVectorNoBounds(0); + +///////////// helper read functions - could be somewhere else + +// removes leading delimiters - return false if nothing else left +bool remove_leading(std::string & _s, const string _delim) +{ + size_t posDebToken = _s.find_first_not_of(_delim); + if (posDebToken >= _s.size()) + return false; + _s = _s.substr(posDebToken); + return true; +} + +double read_double(std::string _s) +{ + istrstream is(_s.c_str()); + double r; + is >> r; + return r; +} + +int read_int(std::string _s) +{ + istrstream is(_s.c_str()); + int i; + is >> i; + return i; +} + +// need to rewrite copy ctor and assignement operator because of ownedBounds +eoRealVectorBounds::eoRealVectorBounds(const eoRealVectorBounds & _b): + eoRealBaseVectorBounds(_b) +{ + factor = _b.factor; + ownedBounds = _b.ownedBounds; + // duplicate all pointers! + if (ownedBounds.size()>0) + for (unsigned i=0; idup(); +} + + +// the readFrom method of eoRealVectorNoBounds: +// only calls the readFrom(string) - for param reading +void eoRealVectorBounds::readFrom(istream& _is) +{ + string value; + _is >> value; + readFrom(value); + return; +} + +void eoRealVectorBounds::readFrom(std::string _value) +{ + // keep track of old size - to adjust in the end + unsigned oldSize = size(); + // clean-up before filling in + if (ownedBounds.size()>0) + for (unsigned i = 0; i < ownedBounds.size(); ++i) + { + delete ownedBounds[i]; + } + ownedBounds.resize(0); + factor.resize(0); + resize(0); + + // now read + string delim(",; "); + while (_value.size()>0) + { + if (!remove_leading(_value, delim)) // only delimiters were left + break; + // look for opening char + size_t posDeb = _value.find_first_of("[("); + cout << posDeb << endl; + if (posDeb >= _value.size()) // nothing left to read (though probably a syntax error there) + { + break; + } + // ending char + string closeChar = (_value[posDeb] == '(' ? string(")") : string("]") ); + + size_t posFin = _value.find_first_of(string(closeChar)); + if (posFin >= _value.size()) + throw runtime_error("Syntax error when reading bounds"); + + // y a-t-il un nbre devant + unsigned count = 1; + if (posDeb > 0) // something before opening + { + string sCount = _value.substr(0, posDeb); + count = read_int(sCount); + if (count <= 0) + throw runtime_error("Syntax error when reading bounds"); + } + + // the bounds + 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 runtime_error("Syntax error when reading bounds"); + + bool minBounded=false, maxBounded=false; + double minBound=0, maxBound=0; + + // min bound + string sMinBounds = sBounds.substr(0,posDelim); + if (sMinBounds != string("-inf")) + { + minBounded = true; + minBound = read_double(sMinBounds); + } + + // max bound + size_t posEndDelim = sBounds.find_first_not_of(delim,posDelim); + + string sMaxBounds = sBounds.substr(posEndDelim); + if (sMaxBounds != string("+inf")) + { + maxBounded = true; + maxBound = read_double(sMaxBounds); + } + + // now create the eoRealBounds objects + eoRealBounds *ptBounds; + if (minBounded && maxBounded) + ptBounds = new eoRealInterval(minBound, maxBound); + else if (!minBounded && !maxBounded) // no bound at all + ptBounds = new eoRealNoBounds; + else if (!minBounded && maxBounded) + ptBounds = new eoRealAboveBound(maxBound); + else if (minBounded && !maxBounded) + ptBounds = new eoRealBelowBound(minBound); + // store it for memory management + ownedBounds.push_back(ptBounds); + // push the count + factor.push_back(count); + // and add count of it to the actual bounds + for (unsigned i=0; i 1 already!) + factor[factor.size()-1] += missing; + } +} diff --git a/eo/src/utils/eoRealBounds.h b/eo/src/utils/eoRealBounds.h index 52bf836d2..73bd761cf 100644 --- a/eo/src/utils/eoRealBounds.h +++ b/eo/src/utils/eoRealBounds.h @@ -69,20 +69,10 @@ eoRealNoBounds the "unbounded bounds" (-infinity, +infinity) eoRealBelowBound the half-bounded interval [min, +infinity) eoRealAboveBound the half-bounded interval (-infinity, max] -Vector type: ------------- -Class eoRealVectorBounds implements the vectorized version: -it is basically a vector of eoRealBounds * and forwards all request -to the elements of the vector. - -This file also contains te 2 global variables eoDummyRealNoBounds and -eoDummyVectorNoBounds that are used as defaults in ctors (i.e. when no -bounds are given, it is assumed unbounded values) - -TODO: have an eoRealBounds.cpp with the longuish parts of the code -(and the 2 global variables). +THis file also contains the declaration of *the* global object that +is the unbounded bound */ -class eoRealBounds +class eoRealBounds : public eoPersistent { public: virtual ~eoRealBounds(){} @@ -133,6 +123,9 @@ public: * @exception if unbounded */ virtual double uniform(eoRng & _rng = eo::rng) = 0; + + /** for memory managements - ugly */ + virtual eoRealBounds * dup() = 0; }; /** A default class for unbounded variables @@ -167,6 +160,34 @@ public: { throw logic_error("Trying to generate uniform values in unbounded eoRealBounds"); } + + // methods from eoPersistent + /** + * Read object. + * @param _is A istream. + * but reading should not be done here, because of bound problems + * see eoRealVectorBounds + */ + virtual void readFrom(istream& _is) + { + throw runtime_error("Should not use eoRealBounds::readFrom"); + } + + /** + * Write object. It's called printOn since it prints the object on a stream. + * @param _os A ostream. + */ + virtual void printOn(ostream& _os) const + { + _os << "[-inf,+inf]"; + } + + /** for memory managements - ugly */ + virtual eoRealBounds * dup() + { + return new eoRealNoBounds(*this); + } + }; // one object for all - see eoRealBounds.cpp @@ -255,6 +276,33 @@ public : return; } + // methods from eoPersistent + /** + * Read object. + * @param _is A istream. + * but reading should not be done here, because of bound problems + * see eoRealVectorBounds + */ + virtual void readFrom(istream& _is) + { + throw runtime_error("Should not use eoRealInterval::readFrom"); + } + + /** + * Write object. It's called printOn since it prints the object on a stream. + * @param _os A ostream. + */ + virtual void printOn(ostream& _os) const + { + _os << "[" << repMinimum << "," << repMaximum << "]"; + } + + /** for memory managements - ugly */ + virtual eoRealBounds * dup() + { + return new eoRealInterval(*this); + } + private : double repMinimum; double repMaximum; @@ -323,6 +371,34 @@ public : _r = repMinimum; return; } + + // methods from eoPersistent + /** + * Read object. + * @param _is A istream. + * but reading should not be done here, because of bound problems + * see eoRealVectorBounds + */ + virtual void readFrom(istream& _is) + { + throw runtime_error("Should not use eoRealBelowBound::readFrom"); + } + + /** + * Write object. It's called printOn since it prints the object on a stream. + * @param _os A ostream. + */ + virtual void printOn(ostream& _os) const + { + _os << "[" << repMinimum << ",+inf]"; + } + + /** for memory managements - ugly */ + virtual eoRealBounds * dup() + { + return new eoRealBelowBound(*this); + } + private : double repMinimum; }; @@ -391,273 +467,35 @@ public : return; } + // methods from eoPersistent + /** + * Read object. + * @param _is A istream. + * but reading should not be done here, because of bound problems + * see eoRealVectorBounds + */ + virtual void readFrom(istream& _is) + { + throw runtime_error("Should not use eoRealAboveBound::readFrom"); + } + + /** + * Write object. It's called printOn since it prints the object on a stream. + * @param _os A ostream. + */ + virtual void printOn(ostream& _os) const + { + _os << "[-inf," << repMaximum << "]"; + } + + /** for memory managements - ugly */ + virtual eoRealBounds * dup() + { + return new eoRealAboveBound(*this); + } + private : double repMaximum; }; -///////////////////////////////////////////////////////////////////// -// The 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 -{ -public: - // virtual desctructor (to avoid warning?) - virtual ~eoRealVectorBounds(){} - - /** Default Ctor. I don't like it, as it leaves NULL pointers around - */ - eoRealVectorBounds(unsigned _dim=0) : vector(_dim) {} - - /** Simple bounds = minimum and maximum (allowed) - */ - eoRealVectorBounds(unsigned _dim, double _min, double _max) : - vector(_dim, new eoRealInterval(_min, _max)) - { - if (_max-_min<=0) - throw std::logic_error("Void range in eoRealVectorBounds"); - } - - /** Ctor: same bonds for everybody, given as an eoRealBounds - */ - eoRealVectorBounds(unsigned _dim, eoRealBounds & _bounds) : - vector(_dim, &_bounds) - {} - - /** Ctor: different bonds for different variables, vectors of double - */ - eoRealVectorBounds(vector _min, vector _max) - { - if (_max.size() != _min.size()) - throw std::logic_error("Dimensions don't match in eoRealVectorBounds"); - for (unsigned i=0; i<_min.size(); i++) - { - push_back( new eoRealInterval(_min[i], _max[i])); - } - } - - /** Ctor, particular case of dim-2 - */ - eoRealVectorBounds(eoRealBounds & _xbounds, eoRealBounds & _ybounds) : - vector(0) - { - push_back( &_xbounds); - push_back( &_ybounds); - } - - /** test: is i_th component bounded - */ - virtual bool isBounded(unsigned _i) - { - return (*this)[_i]->isBounded(); - } - - /** test: bounded iff all are bounded - */ - virtual bool isBounded(void) - { - for (unsigned i=0; iisBounded()) - return false; - return true; - } - - /** 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();} ; - - /** Folds a real value back into the bounds - i_th component - */ - virtual void foldsInBounds(unsigned _i, double & _r) - { - (*this)[_i]->foldsInBounds(_r); - } - - /** Folds all variables of a vector of real values into the bounds - */ - virtual void foldsInBounds(vector & _v) - { - for (unsigned i=0; ifoldsInBounds(_v[i]); - } - } - - /** 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? - */ - virtual bool isInBounds(vector _v) - { - for (unsigned i=0; iminimum();} - 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; - for (unsigned i=0; iuniform(); - return r; - } - - /** 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) - { - _v.resize(size()); - for (unsigned i=0; i - */ -class eoRealVectorNoBounds: public eoRealVectorBounds -{ -public: - // virtual desctructor (to avoid warning?) - virtual ~eoRealVectorNoBounds(){} - - /** - * Ctor: nothing to do, but beware of dimension: call base class ctor - */ - eoRealVectorNoBounds(unsigned _dim=0) : eoRealVectorBounds(_dim) - { - // avoid NULL pointers, even though they shoudl (at the moment) never be used! - if (_dim) - for (unsigned i=0; i<_dim; i++) - operator[](i)=&eoDummyRealNoBounds; - } - - - 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 eoRealVectorNoBounds"); - } - virtual double maximum(unsigned) - { - throw logic_error("Trying to get maximum of eoRealVectorNoBounds"); - } - virtual double range(unsigned) - { - throw logic_error("Trying to get range of eoRealVectorNoBounds"); - } - - virtual double averageRange() - { - 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 eoRealVectorNoBounds"); - } - - // fills a vector with uniformly chosen variables in bounds - void uniform(vector &, eoRng & _rng = eo::rng) - { - throw logic_error("No uniform distribution on eoRealVectorNoBounds"); - } - -}; - -// one object for all - see eoRealBounds.cpp -extern eoRealVectorNoBounds eoDummyVectorNoBounds; #endif diff --git a/eo/src/utils/eoRealVectorBounds.h b/eo/src/utils/eoRealVectorBounds.h new file mode 100644 index 000000000..8f51d4be5 --- /dev/null +++ b/eo/src/utils/eoRealVectorBounds.h @@ -0,0 +1,413 @@ +// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + +//----------------------------------------------------------------------------- +// eoRealVectorBounds.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 _eoRealVectorBounds_h +#define _eoRealVectorBounds_h + +#include // exceptions! +#include +#include + +/** +\defgroup EvolutionStrategies + +*/ + + +/** +Vector type for bounds (see eoRealBounds.h for scalar types) +------------ +Class eoRealVectorBounds implements the vectorized version: +it is basically a vector of eoRealBounds * and forwards all request +to the elements of the vector. + +This file also contains the global variables and eoDummyVectorNoBounds +that are used as defaults in ctors (i.e. when no +bounds are given, it is assumed unbounded values) + +THe 2 main classes defined here are + +eoRealBaseVectorBounds, base class that handles all useful functions +eoRealVectorBounds which derives from the preceding *and* eoPersistent + and also has a mechanism for memory handling of the pointers + it has to allocate +*/ +class eoRealBaseVectorBounds : public vector +{ +public: + // virtual desctructor (to avoid warning?) + virtual ~eoRealBaseVectorBounds(){} + + /** Default Ctor. + */ + eoRealBaseVectorBounds() : vector(0) {} + + /** Ctor: same bounds for everybody, given as an eoRealBounds + */ + eoRealBaseVectorBounds(unsigned _dim, eoRealBounds & _bounds) : + vector(_dim, &_bounds) + {} + + /** Ctor, particular case of dim-2 + */ + eoRealBaseVectorBounds(eoRealBounds & _xbounds, eoRealBounds & _ybounds) : + vector(0) + { + push_back( &_xbounds); + push_back( &_ybounds); + } + + /** test: is i_th component bounded + */ + virtual bool isBounded(unsigned _i) + { + return (*this)[_i]->isBounded(); + } + + /** test: bounded iff all are bounded + */ + virtual bool isBounded(void) + { + for (unsigned i=0; iisBounded()) + return false; + return true; + } + + /** 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();} ; + + /** Folds a real value back into the bounds - i_th component + */ + virtual void foldsInBounds(unsigned _i, double & _r) + { + (*this)[_i]->foldsInBounds(_r); + } + + /** Folds all variables of a vector of real values into the bounds + */ + virtual void foldsInBounds(vector & _v) + { + for (unsigned i=0; ifoldsInBounds(_v[i]); + } + } + + /** 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? + */ + virtual bool isInBounds(vector _v) + { + for (unsigned i=0; iminimum();} + 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; + for (unsigned i=0; iuniform(); + return r; + } + + /** 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) + { + _v.resize(size()); + for (unsigned i=0; iprintOn(_os); + _os << ";"; + } + } +}; + +//////////////////////////////////////////////////////////////////// +/** Now a derived class, for parser reading + * It holds some of the bounds (and destroy them when dying) + */ +class eoRealVectorBounds : public eoRealBaseVectorBounds, public eoPersistent +{ +public: + /** Default Ctor will call base class default ctor + */ + eoRealVectorBounds():eoRealBaseVectorBounds() {} + + /** Ctor: same bounds for everybody, given as an eoRealBounds + */ + eoRealVectorBounds(unsigned _dim, eoRealBounds & _bounds) : + eoRealBaseVectorBounds(_dim, _bounds), factor(1,_dim), ownedBounds(0) + {} + + /** Ctor, particular case of dim-2 + */ + eoRealVectorBounds(eoRealBounds & _xbounds, eoRealBounds & _ybounds) : + eoRealBaseVectorBounds(_xbounds, _ybounds), factor(1,2), ownedBounds(0) + {} + + /** Simple bounds = minimum and maximum (allowed) + */ + eoRealVectorBounds(unsigned _dim, double _min, double _max) : + eoRealBaseVectorBounds(), factor(1, _dim), ownedBounds(0) + { + if (_max-_min<=0) + throw std::logic_error("Void range in eoRealVectorBounds"); + eoRealBounds *ptBounds = new eoRealInterval(_min, _max); + // handle memory once + ownedBounds.push_back(ptBounds); + // same bound for everyone + for (unsigned int i=0; i<_dim; i++) + push_back(ptBounds); + } + + /** Ctor: different bounds for different variables, vectors of double + */ + eoRealVectorBounds(vector _min, vector _max) : + factor(_min.size(), 1), ownedBounds(0) + { + if (_max.size() != _min.size()) + throw std::logic_error("Dimensions don't match in eoRealVectorBounds"); + // the bounds + eoRealBounds *ptBounds; + for (unsigned i=0; i<_min.size(); i++) + { + ptBounds = new eoRealInterval(_min[i], _max[i]); + ownedBounds.push_back(ptBounds); + push_back(ptBounds); + } + } + + /** Dtor: destroy all ownedBounds - BUG ???*/ + virtual ~eoRealVectorBounds() + { +// cout << "Dtor, avec size = " << ownedBounds.size() << endl; +// for (unsigned i = 0; i < ownedBounds.size(); ++i) +// { +// delete ownedBounds[i]; +// } +} + + + // methods from eoPersistent + /** + * Read object from a stream + * only calls the readFrom(string) - for param reading + * @param _is A istream. + */ + virtual void readFrom(istream& _is) ; + + /** + * Read object from a string + * @param _is A istream. + */ + virtual void readFrom(string _s) ; + + /** overload printOut method to save space */ + virtual void printOn(ostream& _os) const + { + if (factor[0]>1) + _os << factor[0] ; + operator[](0)->printOn(_os); + + // other bounds + unsigned int index=factor[0]; + if (factor.size()>1) + for (unsigned i=1; i 1) + _os << factor[i]; + operator[](index)->printOn(_os); + index += factor[i]; + } + } + + /** Eventually increases the size by duplicating last bound */ + void adjust_size(unsigned _dim); + + /** need to rewrite copy ctor and assignement operator + * because of ownedBounds */ + eoRealVectorBounds(const eoRealVectorBounds &); + +private:// WARNING: there is no reason for both vector below + //to be synchronized in any manner + vector factor; // list of nb of "grouped" bounds + vector ownedBounds; +// keep this one private + eoRealVectorBounds& operator=(const eoRealVectorBounds&); + }; + +////////////////////////////////////////////////////////////// +/** 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 +{ +public: + // virtual desctructor (to avoid warning?) + virtual ~eoRealVectorNoBounds(){} + + /** + * Ctor: nothing to do, but beware of dimension: call base class ctor + */ + eoRealVectorNoBounds(unsigned _dim) : + eoRealVectorBounds( (_dim?_dim:1), eoDummyRealNoBounds) + {} + + + 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 eoRealVectorNoBounds"); + } + virtual double maximum(unsigned) + { + throw logic_error("Trying to get maximum of eoRealVectorNoBounds"); + } + virtual double range(unsigned) + { + throw logic_error("Trying to get range of eoRealVectorNoBounds"); + } + + virtual double averageRange() + { + 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 eoRealVectorNoBounds"); + } + + // fills a vector with uniformly chosen variables in bounds + void uniform(vector &, eoRng & _rng = eo::rng) + { + throw logic_error("No uniform distribution on eoRealVectorNoBounds"); + } + +}; + + + +// one object for all - see eoRealBounds.cpp +extern eoRealVectorNoBounds eoDummyVectorNoBounds; +#endif diff --git a/eo/test/t-eoStateAndParser.cpp b/eo/test/t-eoStateAndParser.cpp index c29338ddc..1f2ac1c2d 100644 --- a/eo/test/t-eoStateAndParser.cpp +++ b/eo/test/t-eoStateAndParser.cpp @@ -23,6 +23,8 @@ // include package checkpointing #include +// and provisions for Bounds reading +#include struct Dummy : public EO { @@ -40,6 +42,7 @@ int the_main(int argc, char **argv) eoParser parser(argc, argv); // Define Parameters + eoValueParam dimParam((unsigned int)(5), "dimension", "dimension"); eoValueParam rate(0.01, "mutationRatePerBit", "Initial value for mutation rate per bit"); eoValueParam factor(0.99, "mutationFactor", "Decrease factor for mutation rate"); eoValueParam seed(time(0), "seed", "Random number seed"); @@ -51,17 +54,27 @@ int the_main(int argc, char **argv) eoValueParam load_name("", "Load","Load",'L'); eoValueParam save_name("", "Save","Save",'S'); + // Register them + parser.processParam(dimParam, "Genetic Operators"); parser.processParam(rate, "Genetic Operators"); parser.processParam(factor, "Genetic Operators"); parser.processParam(load_name, "Persistence"); parser.processParam(save_name, "Persistence"); parser.processParam(seed, "Rng seeding"); + // a bound param (need dim) + eoValueParam boundParam(eoRealVectorBounds(dimParam.value(),eoDummyRealNoBounds), "bounds","bounds",'b'); + + parser.processParam(boundParam, "Genetic Operators"); + + cout << "Bounds: " << boundParam.value() << endl; + eoState state; state.registerObject(parser); + if (load_name.value() != "") { // load the parser. This is only neccessary when the user wants to // be able to change the parameters in the state file by hand. diff --git a/eo/tutorial/html/eoLesson4.html b/eo/tutorial/html/eoLesson4.html index fd37d4bb6..e8b518ab7 100644 --- a/eo/tutorial/html/eoLesson4.html +++ b/eo/tutorial/html/eoLesson4.html @@ -2,8 +2,8 @@ - - Tutorial: Lesson 3 + + Tutorial: Lesson 4 Lesson 3 - @@ -478,18 +478,22 @@ parameters for genitype initialization number of variables
Integer parameter: The initilization requires the length of the vector<double>. -

# --initBounds=(0,1) # -B -: Bounds for uniform initialization -
Special string parameter: -Bounds for uniform initialization of the real variables. At the moment -only the same bounds for all variables can be chosen, and the format is -(min,max) without any white space.  This argument is mandatory, and -default is (0,1). +

# --initBounds=10[-1,1] # +-B : Bounds for uniform initialization +
Bounds parameter: +Bounds for uniform initialization of the real variables. The syntax for +this parameter given in the objectBounds +parameter description below. This argument is mandatory, furthermore the +given bounds must be bounded. +The default is [-1,1] +for all variables. +
Note that this parameter is independent of the objectBounds +parameter below.

# --sigmaInit=0.3 # -s : Initial value for Sigma(s)
Floating-point parameter: The initial value for all standard-deviation mutation strategy parameters. -Useless when no self-adaptive mutation mechanism is used. +Useless when no self-adaptive mutation mechanism is used.


Section ######    @@ -497,21 +501,28 @@ Variation Operators    ######
This section allows to tune the way the variation operators will be applied to the individuals (in the strict limit of SGA model at the moment, see below). -

# --objectBounds=(0,1) # --B : Bounds for variables (unbounded if absent) -
Special string parameter: -Bounds for the variables to be met by all variation operators (see format -in initBounds -above). If this parameter is absent, unbounded -variables are assumed (but they still -need some initBounds -for initialization). For the arithmetic crossovers below, and when parameter -alpha is greater than 0, those bounds result in restricting the values -of possible combination factors. For the uniform mutation, the interval -of uniform choice of the variables is restricted by those bounds. Finally, -in the case of Gaussian mutation, the probability distribution is folded -back into the boundeds as many times as necesssary. No -default (i.e. unbounded variables). +

# --objectBounds=10[-inf,+inf] +# -B : Bounds for variables +
Bounds parameter: +Bounds for object variables. The syntax for this parameter is a succession +of (optionally semi-colon separated) items of the form N[min,Max]where +the optional integer N +indicates how many variables have the given bounds. min +and Max +are either floating point numbers, or -inf +(resp. +inf) +to indicate unbounded direction. If not enough bounds are provided, the +remaining variables will have the same bounds as the last bounds given. +
This argument is mandatory, and +default +is [-inf,+inf], i.e. unbounded variables. +

Examples: +10[-1,1]is +equivalent to simply [-1,1] +or to the extended  [-1,1][-1,1][-1,1][-1,1][-1,1][-1,1][-1,1][-1,1][-1,1][-1,1]. +
And [-1,1];2[0,1];[-inf,10]results +in the first variable staying in [-1,1], the second and the third in [0,1] +and all remaining variables below 10.

# --operator=SGA # -o : Description of the operator (SGA only now)
String parameter: @@ -547,7 +558,7 @@ for combination factor in real crossover
Floating-point parameter: Bound for the choices of linear combination factors in both crossover belows (similar to BLX-alpha notation). Default is -0 (i.e. combination factor are chosen in [0,1]). +0 (i.e. combination factor are chosen in [0,1]).

# --segmentRate=1 # -s : Relative rate for segment crossover
Floating-point parameter: @@ -556,7 +567,8 @@ to hypercube and uniform crossovers (see alpha,1+alpha]. -Default is 1. +Default +is 1.

# --hypercubeRate=1 # -A : Relative rate for hypercube crossover
Floating-point parameter: @@ -566,7 +578,7 @@ parameter). Hypercube crossover generates offspring uniformly on the hypercube whose diagonal is the segment joining both parents, i.e. by doing linear combinations of each variable independently (a random number in [alpha,1+alpha] is drawn anew for each variable). Default -is 1. +is 1.

# --uxoverRate=1 # -A : Relative rate for uniform crossover
Floating-point parameter: @@ -574,14 +586,16 @@ Rate of application of the segment crossover rel to hypercube and segment crossovers (see pCross parameter). Uniform crossover simply exchanges values of variables, i.e. uniformly picks up two other summits of the hypercube defined by the parents. -Default is 1. +Default +is 1.

# --epsilon=0.01 # -e : Half-size of interval for Uniform Mutation
Floating-point parameter: The uniform and deterministic-uniform mutations will choose values of variable X uniformly in [X-epsilon, X+epsilon]. -Default is 0.01. +Default +is 0.01.

# --uniformMutRate=1 # -u : Relative rate for uniform mutation
Floating-point parameter: @@ -589,7 +603,7 @@ Rate of aplication of the uniform mutation relat to determinitic uniform and the normal mutations (see pMut above). Uniform mutation modifies all variables by choosing new values uniformly on an interval centered on the old value of width 2*epsilon -(see above). Default is1. +(see above). Default is1.

# --detMutRate=1 # -d : Relative rate for deterministic uniform mutation
Floating-point parameter: @@ -597,13 +611,14 @@ Rate of aplication of the determinisitc-uniform mutation pMut
above). Deterministic-uniform mutation modifies one single variable uniformly based on epsilon epsilon. -Default is1. +Default +is1.

# --normalMutRate=1 # -d : Relative rate for Gaussian mutation
Floating-point parameter: Rate of aplication of the normal mutation relatively to two uniform mutations above (see pMut -above). Default is1. +above). Default is1.

# --sigma=0.3 # -s : Sigma (fixed) for Gaussian mutation
Floating-point parameter: @@ -634,35 +649,35 @@ mutation will be used. There are three available types: isotropic mutation, using one standard deviation for each individual, that will be applied to all variables; anisotropic mutation, where each individual carries as many standard deviations as it has variables; and correlated mutation where -each individuals has its own full correlation matrix. +each individuals has its own full correlation matrix.

# --Isotropic=1 # -i : Isotropic self-adaptive mutation
Boolean parameter: If true, at least one self-adaptive parameter will be used for each individual. -Default is true. +Default +is true.

# --Stdev=0 # -s : One self-adaptive stDev per variable
Boolean parameter: If true, at least one self-adaptive parameter per variable will be used -for each individual. Default is false. +for each individual. Default is false.

# --Correl=0 # -c : Use correlated mutations
Boolean parameter: If true, full correalted self-adaptive mutation will be used for each individual. -Default is false. +Default +is false.

Note: The -default values result in an isotropic self-adaptive mutation to be chosen. +default values result in an isotropic self-adaptive mutation to be chosen.


Section ######    Variation Operators    ######
Only the parameters that are specific to ESEA -are presented here - the objectBounds, -operator, -pCross +are presented here - the objectBounds,operator,pCross and pMut are exactly the same as for RealEA -above. +above.

# --crossType=global # -C : Type of ES recombination (global or standard)
String parameter:  @@ -671,7 +686,7 @@ the standardRealEA parameters above. But new parents can also be chosen anew for each variable before doing the crossover for that variable - and this is called global -recombination. +recombination.

# --crossObj=discrete # -O : Recombination of object variables (discrete or intermediate)
String parameter:  @@ -682,31 +697,32 @@ a linear combination of parents;variables - it si similar to the hypercube crossover described for  with alpah parameter set to 0. This parameter allso to choose the type of crossover that will be applied to the object variables (i.e. the origianl variables -of the problem). Default is discrete. +of the problem). Default is discrete.

# --crossStdev=intermediate # -S : Recombination of mutation strategy parameters (intermediate or discrete)
String parameter:  This parameter allows to choose the type of crossover (see above) that will be applied to the mutation strategy parameters that are part of the genotype. -Default is intermediate. +Default +is intermediate.

# --TauLoc=1 # -l : Local Tau (before normalization)
Floating-point parameter: The local factor for the mutation of the mutation strategy parameters (the only one used when a single standard deviation is used). Default -is 1. +is 1.

# --TauGlob=1 # -g : Global Tau (before normalization)
Floating-point parameter: The global factor for the mutation of the mutation strategy parameters (only useful when more than one standard deviation are used). Default -is 1. +is 1.

# --Beta=0.0873 # -b : Beta
Floating-point parameter: The factor for the mutation of the rotation angles in the case of the full correlated mutation. Default is 0.0873 -(following Schwefel). +(following Schwefel).



Programmer's