diff --git a/archive_current.sh b/archive_current.sh index d43952087..3ba2d2bc2 100755 --- a/archive_current.sh +++ b/archive_current.sh @@ -1,3 +1,5 @@ today=`date --iso-8601` -git archive --format zip master > paradisEO-${today}.zip +name=paradiseo_$today +git archive --prefix=$name/ --format zip master > $name.zip +echo $name.zip diff --git a/cmake/Config.cmake b/cmake/Config.cmake index 8b08ff1c0..02593bac3 100644 --- a/cmake/Config.cmake +++ b/cmake/Config.cmake @@ -31,17 +31,12 @@ endif() ### 0) Define general CXX flags for DEBUG and RELEASE ###################################################################################### -#if(DEBUG) -# set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "" FORCE) -#else(DEBUG) -# set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE) -#endif(DEBUG) - add_definitions(-DDEPRECATED_MESSAGES) set(CMAKE_CXX_FLAGS_DEBUG "-Wunknown-pragmas -O0 -g -Wall -Wextra -ansi -pedantic" CACHE STRING "" FORCE) set(CMAKE_CXX_FLAGS_RELEASE "-Wunknown-pragmas -O2" CACHE STRING "" FORCE) if(SMP) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 -pthread" CACHE STRING "" FORCE) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11 -pthread" CACHE STRING "" FORCE) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11 -pthread" CACHE STRING "" FORCE) add_definitions(-D_GLIBCXX_USE_NANOSLEEP) diff --git a/edo/src/edoTransform.h b/edo/src/edoTransform.h new file mode 100644 index 000000000..20421d5b1 --- /dev/null +++ b/edo/src/edoTransform.h @@ -0,0 +1,111 @@ +/* +The Evolving Distribution Objects framework (EDO) is a template-based, +ANSI-C++ evolutionary computation library which helps you to write your +own estimation of distribution algorithms. + +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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Copyright (C) 2013 Thales group +*/ +/* +Authors: + Johann Dréo +*/ + +#ifndef _edoTransform_h +#define _edoTransform_h + +#include // eoTransform + +/** @defgroup Wrappers + * + * Wrappers to interact with other parts of the framework + */ + +/** Abstract base class for wrapping an estimator and a sampler as an eoTransform + * + * @ingroup Wrappers + */ +template +class edoTransform : public eoTransform< eoPop& > +{ +public: + typedef typename D::EOType EOType; + + edoTransform( edoEstimator & estimator, edoSampler & sampler ) : + _estimator(estimator), _sampler(sampler) + {} + + virtual void operator()( eoPop & pop ) = 0; + +protected: + edoEstimator & _estimator; + edoSampler & _sampler; +}; + + +/** Wrapping an estimator and a sampler as an eoTransform. + * + * @ingroup Wrappers + */ +template +class edoTransformAdaptive : public edoTransform +{ +public: + typedef typename D::EOType EOType; + + edoTransformAdaptive( D & distrib, edoEstimator & estimator, edoSampler & sampler ) + : _distrib(distrib), _estimator(estimator), _sampler(sampler) + {} + + virtual void operator()( eoPop & pop ) + { + _distrib = _estimator( pop ); + pop.clear(); + for( unsigned int i = 0; i < pop.size(); ++i ) { + pop.push_back( _sampler(_distrib) ); + } + } + +protected: + D & _distrib; + edoEstimator & _estimator; + edoSampler & _sampler; +}; + + +/** Wrapping an estimator and a sampler as an eoTransform, + * the distribution is created at instanciation and replaced at each call. + * + * @ingroup Wrappers + */ +template +class edoTransformStateless : public edoTransformAdaptive +{ +public: + typedef typename D::EOType EOType; + + edoTransformStateless( edoEstimator & estimator, edoSampler & sampler ) + : edoTransformAdaptive( *(new D), estimator, sampler ) + {} + + ~edoTransformStateless() + { + // delete the temporary distrib allocated in constructor + delete &(this->_distrib); + } +}; + +#endif // !_edoTransform_h diff --git a/eo/NEWS b/eo/NEWS index 6657f36b8..0723eec0e 100644 --- a/eo/NEWS +++ b/eo/NEWS @@ -1,4 +1,8 @@ * current release: + - added an EOT& parameter to the moCoolingSchedule::update interface method because some cooling schedules need it + - eoMonitor's are no more executed in moCheckpoint::init to prevent access to uninitialized data + - renamed classes moSAexplorer->moSAExplorer, MetropolisHasting->MetropolisHastings and MetropolisHastingExplorer -> MetropolisHastingsExplorer + - reordered param order in moSA's 2nd constructor ('cool' is now before 'eval' because 'eval' now has a default value) * release 1.3.1 (2012-07-27) - the eo::mpi modules is no longer dependent from boost::mpi diff --git a/eo/src/eo b/eo/src/eo index 8196e2b14..5057371d3 100644 --- a/eo/src/eo +++ b/eo/src/eo @@ -35,6 +35,7 @@ // general purpose #include #include +#include #include #include #include diff --git a/eo/src/eoDualFitness.h b/eo/src/eoDualFitness.h index 674fe075c..ff952db66 100644 --- a/eo/src/eoDualFitness.h +++ b/eo/src/eoDualFitness.h @@ -74,6 +74,25 @@ class eoDualFitness //! Flag that marks if the individual is feasible bool _is_feasible; + /** Flag to prevent partial initialization + * + * The reason behind the use of this flag is a bit complicated. + * Normally, we would not want to allow initialization on a scalar. + * But in MOEO, this would necessitate to re-implement most of the + * operator computing metrics, as they expect generic scalars. + * + * As this would be too much work, we use derived metric classes and + * overload them so that they initialize dual fitnesses with the + * feasibility flag. But the compiler still must compile the base + * methods, that use the scalar interface. + * + * Thus, eoDualFitness has a scalar interface, but this flag add a + * security against partial initialization. In DEBUG mode, asserts + * will fail if the feasibility has not been explicitly initialized + * at runtime. + */ + bool _feasible_init; + public: //! Empty initialization @@ -81,68 +100,104 @@ class eoDualFitness * Unfeasible by default */ eoDualFitness() : - _value(), - _is_feasible(false) + _value(0.0), + _is_feasible(false), + _feasible_init(false) {} + //! Initialization with only the value, the fitness will be unfeasible. + /*! + * WARNING: this is what is used when you initialize a new fitness from a double. + * If you use this interface, you MUST set the feasibility BEFORE + * asking for it or the value. Or else, an assert will fail in debug mode. + */ + template + eoDualFitness( T value ) : + _value(value), + _is_feasible(false), + _feasible_init(false) + { + } + + //! Copy constructor eoDualFitness(const eoDualFitness& other) : _value(other._value), - _is_feasible(other._is_feasible) + _is_feasible(other._is_feasible), + _feasible_init(true) {} //! Constructor from explicit value/feasibility eoDualFitness(const BaseType& v, const bool& is_feasible) : _value(v), - _is_feasible(is_feasible) + _is_feasible(is_feasible), + _feasible_init(true) {} //! From a std::pair (first element is the value, second is the feasibility) eoDualFitness(const std::pair& dual) : _value(dual.first), - _is_feasible(dual.second) + _is_feasible(dual.second), + _feasible_init(true) {} - // FIXME is it a good idea to include implicit conversion here? /** Conversion operator: it permits to use a fitness instance as its scalar * type, if needed. For example, this is possible: * eoDualFitness > fit; * double val = 1.0; - * fit = val; * val = fit; */ operator BaseType(void) const { return _value; } - + inline bool is_feasible() const { + assert( _feasible_init ); return _is_feasible; } + //! Explicitly set the feasibility. Useful if you have used previously the instantiation on a single scalar. + inline void is_feasible( bool feasible ) + { + this->is_feasible( feasible ); + this->_feasible_init = true; + } + inline BaseType value() const { + assert( _feasible_init ); return _value; } //! Copy operator from a std::pair - eoDualFitness& operator=(const std::pair& v) + eoDualFitness& operator=( const std::pair& v ) { - _value = v.first; - _is_feasible = v.second; + this->_value = v.first; + this->is_feasible( v.second ); return *this; } //! Copy operator from another eoDualFitness template - eoDualFitness & operator=(const eoDualFitness& other ) + eoDualFitness & operator=( const eoDualFitness& other ) { if (this != &other) { this->_value = other._value; - this->_is_feasible = other._is_feasible; + this->is_feasible( other.is_feasible() ); } return *this; } + //! Copy operator from a scalar + template + eoDualFitness& operator=(const T v) + { + this->_value = v; + this->_is_feasible = false; + this->_feasible_init = false; + return *this; + } + //! Comparison that separate feasible individuals from unfeasible ones. Feasible are always better /*! * Use less as a default comparison operator @@ -154,11 +209,11 @@ class eoDualFitness // am I better (less, by default) than the other ? // if I'm feasible and the other is not - if( this->_is_feasible && !other._is_feasible ) { + if( this->is_feasible() && !other.is_feasible() ) { // no, the other has a better fitness return false; - } else if( !this->_is_feasible && other._is_feasible ) { + } else if( !this->is_feasible() && other.is_feasible() ) { // yes, a feasible fitness is always better than an unfeasible one return true; @@ -183,69 +238,137 @@ class eoDualFitness public: + /* FIXME it would be better to raise errors (or warnings) if one try to apply arithmetics operators between feasible + * and unfeasible fitnesses. This necessitates to add wrappers for operators that aggregates sets of dual fitnesses + * (like eoStat), both for separating feasibility and for aggregating them. + */ + + // NOTE: we cannot declare this set of operator classes as friend, because there is two differerent templated classes declared later + // (for minimizing and maximizing) + //! Add a given fitness to the current one - template - friend - eoDualFitness & operator+=( eoDualFitness & from, const eoDualFitness & that ) + template + eoDualFitness & operator+=( const T that ) { - from._value += that._value; + this->_value += that; + return *this; + } + + //! Add a given fitness to the current one + eoDualFitness & operator+=( const eoDualFitness & that ) + { + // from._value += that._value; + this->_value += that._value; // true only if the two are feasible, else false - from._is_feasible = from._is_feasible && that._is_feasible; + // from._is_feasible = from._is_feasible && that._is_feasible; + this->_is_feasible = this->_is_feasible && that._is_feasible; - return from; + return *this; } //! Substract a given fitness to the current one - template - friend - eoDualFitness & operator-=( eoDualFitness & from, const eoDualFitness & that ) + template + eoDualFitness & operator-=( const T that ) + { + this->_value -= that; + return *this; + } + + //! Substract a given fitness to the current one + eoDualFitness & operator-=( const eoDualFitness & that ) + { + this->_value -= that._value; + + // true only if the two are feasible, else false + this->_is_feasible = this->_is_feasible && that._is_feasible; + + return *this; + } + + + //! Add a given fitness to the current one + template + eoDualFitness & operator/=( T that ) + { + this->_value /= that; + return *this; + } + + //! Add a given fitness to the current one + eoDualFitness & operator/=( const eoDualFitness & that ) { - from._value -= that._value; + this->_value /= that._value; // true only if the two are feasible, else false - from._is_feasible = from._is_feasible && that._is_feasible; + this->_is_feasible = this->_is_feasible && that._is_feasible; + + return *this; + } - return from; + template + eoDualFitness operator+( T that ) + { + this->_value += that; + return *this; } // Add this fitness's value to that other, and return a _new_ instance with the result. - template - eoDualFitness operator+(const eoDualFitness & that) + eoDualFitness operator+( const eoDualFitness & that ) { - eoDualFitness from( *this ); + eoDualFitness from( *this ); return from += that; } + template + eoDualFitness operator-( T that ) + { + this->_value -= that; + return *this; + } + // Add this fitness's value to that other, and return a _new_ instance with the result. - template - eoDualFitness operator-(const eoDualFitness & that) + eoDualFitness operator-( const eoDualFitness & that ) { - eoDualFitness from( *this ); + eoDualFitness from( *this ); return from -= that; } + + template + eoDualFitness operator/( T that ) + { + this->_value /= that; + return *this; + } + + // Add this fitness's value to that other, and return a _new_ instance with the result. + eoDualFitness operator/( const eoDualFitness & that ) + { + eoDualFitness from( *this ); + return from /= that; + } + //! Print an eoDualFitness instance as a pair of numbers, separated by a space - template friend - std::ostream& operator<<(std::ostream& os, const eoDualFitness& f) + std::ostream& operator<<( std::ostream& os, const eoDualFitness & fitness ) { - os << f._value << " " << f._is_feasible; + os << fitness._value << " " << fitness.is_feasible(); return os; } //! Read an eoDualFitness instance as a pair of numbers, separated by a space - template friend - std::istream& operator>>(std::istream& is, eoDualFitness& f) + std::istream& operator>>( std::istream& is, eoDualFitness & fitness ) { - F value; + BaseType value; is >> value; bool feasible; is >> feasible; - f = std::make_pair( value, feasible ); + fitness._value = value; + fitness.is_feasible( feasible ); return is; } }; @@ -263,35 +386,24 @@ template< class EOT> bool eoIsFeasible ( const EOT & sol ) { return sol.fitness().is_feasible(); } -/** Embed two eoStat and call the first one on the feasible individuals and - * the second one on the unfeasible ones, merge the two resulting value in - * a string, separated by a given marker. +/** Separate the population into two: one with only feasible individuals, the other with unfeasible ones. */ -//template -template -class eoDualStatSwitch : public eoStat< EOT, std::string > +template +class eoDualPopSplit : public eoUF&, void> { -public: - using eoStat::value; - -// eoDualStatSwitch( eoStat & stat_feasible, eoStat & stat_unfeasible, std::string sep=" " ) : - eoDualStatSwitch( EOSTAT & stat_feasible, EOSTAT & stat_unfeasible, std::string sep=" " ) : - eoStat( - "?"+sep+"?", - stat_feasible.longName()+sep+stat_unfeasible.longName() - ), - _stat_feasible(stat_feasible), - _stat_unfeasible(stat_unfeasible), - _sep(sep) - { } +protected: + eoPop _pop_feasible; + eoPop _pop_unfeasible; - virtual void operator()( const eoPop & pop ) +public: + //! Split the pop and keep them in members + void operator()( const eoPop& pop ) { - eoPop pop_feasible; - pop_feasible.reserve(pop.size()); + _pop_feasible.clear(); + _pop_feasible.reserve(pop.size()); - eoPop pop_unfeasible; - pop_unfeasible.reserve(pop.size()); + _pop_unfeasible.clear(); + _pop_unfeasible.reserve(pop.size()); for( typename eoPop::const_iterator ieot=pop.begin(), iend=pop.end(); ieot!=iend; ++ieot ) { /* @@ -300,28 +412,71 @@ class eoDualStatSwitch : public eoStat< EOT, std::string > } */ if( ieot->fitness().is_feasible() ) { - pop_feasible.push_back( *ieot ); + _pop_feasible.push_back( *ieot ); } else { - pop_unfeasible.push_back( *ieot ); + _pop_unfeasible.push_back( *ieot ); } } + } - _stat_feasible( pop_feasible ); - _stat_unfeasible( pop_unfeasible ); + //! Merge feasible and unfeasible populations into a new one + eoPop merge() const + { + eoPop merged; + merged.reserve( _pop_feasible.size() + _pop_unfeasible.size() ); + std::copy( _pop_feasible.begin(), _pop_feasible.end(), std::back_inserter >(merged) ); + std::copy( _pop_unfeasible.begin(), _pop_unfeasible.end(), std::back_inserter >(merged) ); + return merged; + } - std::ostringstream out; - out << _stat_feasible.value() << _sep << _stat_unfeasible.value(); + eoPop& feasible() { return _pop_feasible; } + eoPop& unfeasible() { return _pop_unfeasible; } +}; - value() = out.str(); - } +/** Embed two eoStat and call the first one on the feasible individuals and + * the second one on the unfeasible ones, merge the two resulting value in + * a string, separated by a given marker. + */ +template +class eoDualStatSwitch : public eoStat< typename EOSTAT::EOType, std::string > +{ +public: + typedef typename EOSTAT::EOType EOType; protected: -// eoStat & _stat_feasible; -// eoStat & _stat_unfeasible; EOSTAT & _stat_feasible; EOSTAT & _stat_unfeasible; std::string _sep; + + eoDualPopSplit _pop_split; + +public: + using eoStat::value; + + eoDualStatSwitch( EOSTAT & stat_feasible, EOSTAT & stat_unfeasible, std::string sep=" " ) : + eoStat( + "?"+sep+"?", + stat_feasible.longName()+sep+stat_unfeasible.longName() + ), + _stat_feasible(stat_feasible), + _stat_unfeasible(stat_unfeasible), + _sep(sep) + { } + + virtual void operator()( const eoPop & pop ) + { + // create two separated pop in this operator + _pop_split( pop ); + + _stat_feasible( _pop_split.feasible() ); + _stat_unfeasible( _pop_split.unfeasible() ); + + std::ostringstream out; + out << _stat_feasible.value() << _sep << _stat_unfeasible.value(); + + value() = out.str(); + } }; /** @} */ diff --git a/eo/src/eoOptional.h b/eo/src/eoOptional.h new file mode 100644 index 000000000..9143be3cd --- /dev/null +++ b/eo/src/eoOptional.h @@ -0,0 +1,130 @@ +// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + +/* +(c) Thales group, 2013 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +/** + +A utility class for wrapping non-const references and use them as default arguments in functions. +This especially is useful for avoiding constructor multiplication. + +For example, this is not valid C++98 code: + +\code +struct MyClass { + MyClass(T& my_T = default_T) + : actual_T(my_T) + { } +private: + T default_T; + T& actual_T; +}; +\endcode + +This is the same code using eoOptional, which is valid: + +\code +struct MyClass { + MyClass(eoOptional my_T = NULL) + : actual_T(my_T.getOr(default_T)) + { } +private: + T default_T; + T& actual_T; +}; +\endcode + +And from the point of view of the user, it is transparent: + +\code +// Three ways of using MyClass: +MyClass mc1; +MyClass mc2(NULL); +T t; +MyClass mc3(t); +\endcode + + +@ingroup Utilities +@{ +*/ + +#ifndef _EOOPTIONAL_H +#define _EOOPTIONAL_H + +#include +#include +//#include + + +template< class T > +class eoOptional { +public: + static const eoOptional null; // = eoOptional(); + + eoOptional (T& init) + : _val(&init) + { } + + // used mainly for converting NULL to this class + eoOptional (T* init) + : _val(init) + { } + + bool hasValue() const + { + return _val != NULL; + } + + T& get () const + { + if (!hasValue()) + throw std::runtime_error("Cannot get a reference from a eoOptional wrapper with no value"); + //throw eoEx; + return *_val; + } + + T& getOr (T& defaultValue) const + { + return hasValue()? *_val: defaultValue; + } + +protected: + eoOptional () + : _val(NULL) + { } + +private: + T* _val; +}; + +template< class T > +const eoOptional eoOptional::null = eoOptional(); + + +#endif // _EOOPTIONAL_H + + +/** @} */ + diff --git a/eo/src/serial/Utils.h b/eo/src/serial/Utils.h index b6ea360b3..5acc558ba 100644 --- a/eo/src/serial/Utils.h +++ b/eo/src/serial/Utils.h @@ -155,7 +155,7 @@ namespace eoserial inline void unpackBasePushBack( const Entity* obj, T& container ) { const Array* arr = static_cast( obj ); - for( auto it = arr->begin(), end = arr->end(); + for( Array::const_iterator it = arr->begin(), end = arr->end(); it != end; ++it ) { @@ -190,7 +190,7 @@ namespace eoserial inline void unpackBase( const Entity* entity, std::map & m ) { const Object* obj = static_cast< const Object* >( entity ); - for( auto it = obj->begin(), end = obj->end(); + for( Object::const_iterator it = obj->begin(), end = obj->end(); it != end; ++it ) { @@ -298,7 +298,7 @@ namespace eoserial inline Entity* packIterable( const T& container ) { Array* arr = new Array; - for( auto it = container.begin(), end = container.end(); + for( Array::const_iterator it = container.begin(), end = container.end(); it != end; ++it ) { @@ -332,7 +332,7 @@ namespace eoserial inline Entity* pack( const std::map& map ) { Object* obj = new Object; - for( auto it = map.begin(), end = map.end(); + for( Object::const_iterator it = map.begin(), end = map.end(); it != end; ++it ) { diff --git a/eo/src/utils/eoFileMonitor.cpp b/eo/src/utils/eoFileMonitor.cpp index 3cc96deb1..4927fe2ab 100644 --- a/eo/src/utils/eoFileMonitor.cpp +++ b/eo/src/utils/eoFileMonitor.cpp @@ -73,16 +73,18 @@ eoMonitor& eoFileMonitor::operator()(void) eoMonitor& eoFileMonitor::operator()(std::ostream& os) { - - iterator it = vec.begin(); - - os << (*it)->getValue(); - - for(++it; it != vec.end(); ++it) + if (vec.size() > 0) { - os << delim.c_str() << (*it)->getValue(); + iterator it = vec.begin(); + + os << (*it)->getValue(); + + for(++it; it != vec.end(); ++it) + { + os << delim.c_str() << (*it)->getValue(); + } } - + os << std::endl; return *this; diff --git a/eo/src/utils/eoGetterUpdater.h b/eo/src/utils/eoGetterUpdater.h new file mode 100644 index 000000000..e73988159 --- /dev/null +++ b/eo/src/utils/eoGetterUpdater.h @@ -0,0 +1,85 @@ +/* + +(c) Thales group, 2010 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +#ifndef _eoGetterUpdater_h +#define _eoGetterUpdater_h + +#include + +template class eoCheckPoint; + +/** + eoGetterUpdater is an eoUpdater that updates its eoValueParam::value() from + the specified object and the specified getter method on this object. + + @ingroup Utilities +*/ +template +class eoGetterUpdater : public eoUpdater, public eoValueParam +{ +public: + using eoValueParam::value; + + virtual std::string className(void) const { return "eoGetterUpdater"; } + + typedef V (T::*MethodType)(); + + eoGetterUpdater(T& _instance, MethodType _method) + : instance(_instance), method(_method) + { } + + // Overload to accept const getter methods; safely casts them to non-const + eoGetterUpdater(T& _instance, V (T::*_method)() const) + : instance(_instance), method((MethodType)_method) + { } + + virtual void operator()() + { + value() = (instance.*method)(); + } + +private: + T& instance; + MethodType method; // ie: V (T::*method)(); +}; + + + +#endif + + + + + + + + + + + + + + + diff --git a/eo/src/utils/eoLogger.cpp b/eo/src/utils/eoLogger.cpp index 1330c5323..10371b0a0 100644 --- a/eo/src/utils/eoLogger.cpp +++ b/eo/src/utils/eoLogger.cpp @@ -37,14 +37,20 @@ Caner Candan #include // used to define EOF #include +#include // std::find #include "eoLogger.h" + +#ifdef USE_SET +typedef std::set::iterator StreamIter; +#else +typedef std::vector::iterator StreamIter; +#endif + + void eoLogger::_init() { - _standard_io_streams[&std::cout] = 1; - _standard_io_streams[&std::clog] = 2; - _standard_io_streams[&std::cerr] = 2; // /!\ If you want to add a level dont forget to add it at the header file in the enumerator Levels @@ -55,26 +61,11 @@ void eoLogger::_init() addLevel("logging", eo::logging); addLevel("debug", eo::debug); addLevel("xdebug", eo::xdebug); -} -eoLogger::eoLogger() : - std::ostream(NULL), - - _verbose("quiet", "verbose", "Set the verbose level", 'v'), - _printVerboseLevels(false, "print-verbose-levels", "Print verbose levels", 'l'), - _output("", "output", "Redirect a standard output to a file", 'o'), - - _selectedLevel(eo::progress), - _contextLevel(eo::quiet), - _fd(2), - _obuf(_fd, _contextLevel, _selectedLevel) -{ - std::ostream::init(&_obuf); - _init(); } -eoLogger::eoLogger(eo::file file) : - std::ostream(NULL), +eoLogger::eoLogger() : + std::ostream(NULL), _verbose("quiet", "verbose", "Set the verbose level", 'v'), _printVerboseLevels(false, "print-verbose-levels", "Print verbose levels", 'l'), @@ -82,17 +73,17 @@ eoLogger::eoLogger(eo::file file) : _selectedLevel(eo::progress), _contextLevel(eo::quiet), - _fd(2), - _obuf(_fd, _contextLevel, _selectedLevel) + _obuf(_contextLevel, _selectedLevel) { - std::ostream::init(&_obuf); + std::ostream::init(&_obuf); _init(); - *this << file; } eoLogger::~eoLogger() { - if (_fd > 2) { ::close(_fd); } + if (_obuf._ownedFileStream != NULL) { + delete _obuf._ownedFileStream; + } } void eoLogger::_createParameters( eoParser& parser ) @@ -110,19 +101,21 @@ void eoLogger::_createParameters( eoParser& parser ) //------------------------------------------------------------------ - // we're gonna redirect the log to the given filename if -o is used. + // we redirect the log to the given filename if -o is used. //------------------------------------------------------------------ if ( ! _output.value().empty() ) { - eo::log << eo::file( _output.value() ); + redirect(_output.value()); } + + //------------------------------------------------------------------ //------------------------------------------------------------------ - // we're gonna print the list of levels if -l parameter is used. + // we print the list of levels if -l parameter is used. //------------------------------------------------------------------ if ( _printVerboseLevels.value() ) @@ -163,12 +156,6 @@ eoLogger& operator<<(eoLogger& l, const eo::Levels lvl) return l; } -eoLogger& operator<<(eoLogger& l, eo::file f) -{ - l._fd = ::open(f._f.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644); - return l; -} - eoLogger& operator<<(eoLogger& l, eo::setlevel v) { l._selectedLevel = (v._lvl < 0 ? l._levels[v._v] : v._lvl); @@ -177,37 +164,106 @@ eoLogger& operator<<(eoLogger& l, eo::setlevel v) eoLogger& operator<<(eoLogger& l, std::ostream& os) { - if (l._standard_io_streams.find(&os) != l._standard_io_streams.end()) - { - l._fd = l._standard_io_streams[&os]; - } +#warning deprecated + l.addRedirect(os); return l; } -eoLogger::outbuf::outbuf(const int& fd, - const eo::Levels& contexlvl, +void eoLogger::redirect(std::ostream& os) +{ + doRedirect(&os); +} + +void eoLogger::doRedirect(std::ostream* os) +{ + if (_obuf._ownedFileStream != NULL) { + delete _obuf._ownedFileStream; + _obuf._ownedFileStream = NULL; + } + _obuf._outStreams.clear(); + if (os != NULL) + #ifdef USE_SET + _obuf._outStreams.insert(os); + #else + _obuf._outStreams.push_back(os); + #endif +} + +void eoLogger::addRedirect(std::ostream& os) +{ + bool already_there = tryRemoveRedirect(&os); +#ifdef USE_SET + _obuf._outStreams.insert(&os); +#else + _obuf._outStreams.push_back(&os); +#endif + if (already_there) + eo::log << eo::warnings << "Cannot redirect the logger to a stream it is already redirected to." << std::endl; +} + +void eoLogger::removeRedirect(std::ostream& os) +{ + if (!tryRemoveRedirect(&os)) + eo::log << eo::warnings << "Cannot remove from the logger a stream it was not redirected to."; +} + +bool eoLogger::tryRemoveRedirect(std::ostream* os) +{ + StreamIter it = find(_obuf._outStreams.begin(), _obuf._outStreams.end(), os); + if (it == _obuf._outStreams.end()) + return false; + _obuf._outStreams.erase(it); + return true; +} + +void eoLogger::redirect(const char * filename) +{ + std::ofstream * os; + if (filename == NULL) { + os = NULL; + } else { + os = new std::ofstream(filename); + } + doRedirect(os); + _obuf._ownedFileStream = os; +} + +void eoLogger::redirect(const std::string& filename) +{ + redirect(filename.c_str()); +} + + +eoLogger::outbuf::outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl) - : _fd(fd), _contextLevel(contexlvl), _selectedLevel(selectedlvl) -{} + : +#ifndef USE_SET + _outStreams(1, &std::cout), +#endif + _ownedFileStream(NULL), _contextLevel(contexlvl), _selectedLevel(selectedlvl) +{ +#ifdef USE_SET + _outStreams.insert(&std::cout); +#endif +} int eoLogger::outbuf::overflow(int_type c) { if (_selectedLevel >= _contextLevel) - { - if (_fd >= 0 && c != EOF) - { - ::write(_fd, &c, 1); - } - } + { + for (StreamIter it = _outStreams.begin(); it != _outStreams.end(); it++) + { + if (c != EOF) + { + (**it) << (char) c; + } + } + } return c; } namespace eo { - file::file(const std::string f) - : _f(f) - {} - setlevel::setlevel(const std::string v) : _v(v), _lvl((Levels)-1) {} diff --git a/eo/src/utils/eoLogger.h b/eo/src/utils/eoLogger.h index 9ac1c2115..98ba09660 100644 --- a/eo/src/utils/eoLogger.h +++ b/eo/src/utils/eoLogger.h @@ -1,6 +1,7 @@ // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- /* + (c) Thales group, 2010 This library is free software; you can redistribute it and/or @@ -30,56 +31,7 @@ Caner Candan Global logger for EO. - Here's an example explaning how to use eoLogger: -\code - #include - - int main(int ac, char** av) - { - // We are declaring the usual eoParser class - eoParser parser(ac, av); - - // This call is important to allow -v parameter to change user level. - make_verbose(parser); - - // At this time we are switching to warning message and messages - // which are going to follow it are going to be warnings message too. - // These messages can be displayed only if the user level (sets with - // eo::setlevel function) is set to eo::warnings. - eo::log << eo::warnings; - - // With the following eo::file function we are defining that - // all future logs are going to this new file resource which is - // test.txt - eo::log << eo::file("test.txt") << "In FILE" << std::endl; - - // Now we are changing again the resources destination to cout which - // is the standard output. - eo::log << std::cout << "In COUT" << std::endl; - - // Here are 2 differents examples of how to set the errors user level - // in using either a string or an identifier. - eo::log << eo::setlevel("errors"); - eo::log << eo::setlevel(eo::errors); - - // Now we are writting a message, that will be displayed only if we are above the "quiet" level - eo::log << eo::quiet << "1) Must be in quiet mode to see that" << std::endl; - - // And so on... - eo::log << eo::setlevel(eo::warnings) << eo::warnings << "2) Must be in warnings mode to see that" << std::endl; - - eo::log << eo::setlevel(eo::logging); - - eo::log << eo::errors; - eo::log << "3) Must be in errors mode to see that"; - eo::log << std::endl; - - eo::log << eo::debug << 4 << ')' - << " Must be in debug mode to see that\n"; - - return 0; - } -\endcode + For an example explaning how to use eoLogger, please refer to paradiseo/eo/test/t-eoLogger.cpp @{ */ @@ -91,10 +43,23 @@ Caner Candan #include #include #include +#include #include "eoObject.h" #include "eoParser.h" +#define USE_SET // defines if a set is to be used instead of a vector for storing streams the logger is redirected to +#undef USE_SET +/* expriments have shown that here a vector is by far faster than a set even if O(n), + * because it needs less dynamic allocations, uses less memory and less instructions + */ + + +#ifdef USE_SET +#include +#endif + + namespace eo { /** @@ -110,16 +75,6 @@ namespace eo debug, xdebug}; - /** - * file - * this structure combined with the friend operator<< below is an easy way to select a file as output. - */ - struct file - { - explicit file(const std::string f); - const std::string _f; - }; - /** * setlevel * this structure combined with the friend operator<< below is an easy way to set a verbose level. @@ -146,7 +101,7 @@ class eoLogger : public eoObject, eoLogger(); //! overidded ctor in order to instanciate a logger with a file define in parameter - eoLogger(eo::file file); + //eoLogger(eo::file file); //! dtor ~eoLogger(); @@ -181,6 +136,12 @@ class eoLogger : public eoObject, //! used by the set of ctors to initiate some useful variables void _init(); + //! helper function regrouping redirection operations; takes a pointer because can be given NULL + void doRedirect(std::ostream*); + + //! helper function searching for a stream and removing it, returning true if successful, false otherwise + bool tryRemoveRedirect(std::ostream*); + private: /** * outbuf @@ -189,11 +150,19 @@ class eoLogger : public eoObject, class outbuf : public std::streambuf { public: - outbuf(const int& fd, const eo::Levels& contexlvl, const eo::Levels& selectedlvl); + outbuf(const eo::Levels& contexlvl, const eo::Levels& selectedlvl); + //std::ostream * _outStream; + + #ifdef USE_SET + std::set _outStreams; + #else + std::vector _outStreams; + #endif + + std::ofstream * _ownedFileStream; protected: virtual int overflow(int_type c); private: - const int& _fd; const eo::Levels& _contextLevel; const eo::Levels& _selectedLevel; }; @@ -211,12 +180,6 @@ class eoLogger : public eoObject, //! in order to use stream style to define the context verbose level where the following logs will be saved friend eoLogger& operator<<(eoLogger&, const eo::Levels); - /** - * operator<< used there to set a filename through the class file. - */ - //! in order to use stream style to define a file to dump instead the standart output - friend eoLogger& operator<<(eoLogger&, eo::file); - /** * operator<< used there to set a verbose level through the class setlevel. */ @@ -224,12 +187,39 @@ class eoLogger : public eoObject, friend eoLogger& operator<<(eoLogger&, eo::setlevel); /** - * operator<< used there to be able to use std::cout to say that we wish to redirect back the buffer to a standard output. + * DEPRECATED: Use instead the redirect or addRedirect method; has the same effect as addRedirect */ - //! in order to use stream style to go back to a standart output defined by STL - //! and to get retro-compatibility friend eoLogger& operator<<(eoLogger&, std::ostream&); + /** + * Redirects the logger to a given output stream. + * Closing the stream and returning its memory is at the charge of the caller, + * but should not be done while the log is still redirected to it. + * This resets all previous redirections set up with redirect and add_redirect. + */ + void redirect(std::ostream&); + + /** + * Adds a redirection from the logger to a given output stream. + * Closing the stream and returning its memory is at the charge of the caller, + * but should not be done while the log is still redirected to it. + * This does not reset previous redirections, which remain active. + */ + void addRedirect(std::ostream&); + + /** + * Removes a redirection from the logger to the given output stream. + * This only resets the redirection to the stream passed in argument. + */ + void removeRedirect(std::ostream&); + + /** + * Redirects the logger to a file using a filename. + * Closing the file will be done automatically when the logger is redirected again or destroyed. + */ + void redirect(const char * filename); + void redirect(const std::string& filename); + private: friend void make_verbose(eoParser&); @@ -244,13 +234,7 @@ class eoLogger : public eoObject, eo::Levels _contextLevel; /** - * _fd in storing the file descriptor at this place we can disable easily the buffer in - * changing the value at -1. It is used by operator <<. - */ - int _fd; - - /** - * _obuf std::ostream mandates to use a buffer. _obuf is a outbuf inheriting of std::streambuf. + * _obuf std::ostream mandates to use a buffer. _obuf is a outbuf inheriting from std::streambuf. */ outbuf _obuf; diff --git a/eo/src/utils/eoParam.h b/eo/src/utils/eoParam.h index 948092c93..1c0937528 100644 --- a/eo/src/utils/eoParam.h +++ b/eo/src/utils/eoParam.h @@ -224,7 +224,9 @@ public : void setValue(const std::string& _value) { std::istringstream is(_value); - is >> repValue; + bool read = (is >> repValue); + if (!read) + throw std::runtime_error("Could not read value passed in eoValueParam::setValue"); } protected: diff --git a/eo/src/utils/eoRealBounds.h b/eo/src/utils/eoRealBounds.h index a41646d47..8d55d793a 100644 --- a/eo/src/utils/eoRealBounds.h +++ b/eo/src/utils/eoRealBounds.h @@ -27,9 +27,12 @@ #ifndef _eoRealBounds_h #define _eoRealBounds_h +#include #include #include // std::exceptions! + #include +#include "eoLogger.h" /** \defgroup Real Vector of reals @@ -231,7 +234,7 @@ public : assert( repRange >= 0 ); #ifndef NDEBUG if( repRange == 0 ) { - eo::log << eo::warnings << "Null range in eoRealBounds (min=" << _min << ", max=" << _max << ")" << std::endl; + eo::log << eo::warnings << "Warning: null range in eoRealBounds (min=" << _min << ", max=" << _max << ")" << std::endl; } #endif } diff --git a/eo/src/utils/eoStat.h b/eo/src/utils/eoStat.h index fd26ec228..7099470cd 100644 --- a/eo/src/utils/eoStat.h +++ b/eo/src/utils/eoStat.h @@ -40,6 +40,7 @@ Contact: http://eodev.sourceforge.net #include #include //#include +#include /** @defgroup Stats Statistics computation * @@ -84,6 +85,7 @@ template class eoStat : public eoValueParam, public eoStatBase { public: + typedef EOT EOType; eoStat(T _value, std::string _description) : eoValueParam(_value, _description) @@ -120,6 +122,7 @@ template class eoSortedStat : public eoSortedStatBase, public eoValueParam { public : + typedef EOT EOType; eoSortedStat(ParamType _value, std::string _desc) : eoValueParam(_value, _desc) {} virtual std::string className(void) const { return "eoSortedStat"; } @@ -472,6 +475,51 @@ public : }; */ +//! A robust measure of the mass (generally used to compute the median). Do not alter the given pop. +template +class eoNthElementStat : public eoStat< EOT, typename EOT::Fitness > +{ +protected: + int _nth; + double _ratio; + +public: + using eoStat::value; + + eoNthElementStat( int nth = 0, std::string description = "NthElement") + : eoStat( 0.0, description ), _nth(nth), _ratio(-1.0) + {} + + eoNthElementStat( double ratio = 0.5, std::string description = "Median" ) + : eoStat( 0.0, description ), _nth(-1), _ratio(ratio) + {} + + virtual void operator()( const eoPop & _pop ) + { + if( _nth == -1 ) { // asked for a ratio + _nth = static_cast( std::floor(_pop.size() * _ratio) ); + } else { + assert( _ratio == -1 ); // asked for a position + } + + if( _pop.size() == 0 ) { + //FIXME how to implement value() = 0 ? + eo::log << eo::warnings << "Called " << className() << " on an empty pop, value unchanged" << std::endl; + + } else { + eoPop pop = _pop; // copy, thus no sorting of the original pop + + std::nth_element( pop.begin(), pop.begin()+_nth, pop.end() ); + value() = pop[_nth].fitness(); + } + } + + virtual std::string className(void) const { return "eoNthElementStat"; } +}; +/** @example t-eoIQRStat.cpp + */ + + //! A robust measure of dispersion (also called midspread or middle fifty) that is the difference between the third and the first quartile. template @@ -480,12 +528,13 @@ class eoInterquartileRangeStat : public eoStat< EOT, typename EOT::Fitness > public: using eoStat::value; - eoInterquartileRangeStat( typename EOT::Fitness start, std::string description = "IQR" ) : eoStat( start, description ) {} + eoInterquartileRangeStat( std::string description = "IQR" ) : eoStat( 0.0, description ) {} virtual void operator()( const eoPop & _pop ) { if( _pop.size() == 0 ) { - // how to implement value() = 0 ? + //FIXME how to implement value() = 0 ? + eo::log << eo::warnings << "Called " << className() << " on an empty pop, value unchanged" << std::endl; } else { eoPop pop = _pop; diff --git a/eo/src/utils/eoUpdater.h b/eo/src/utils/eoUpdater.h index 072b9a9bb..70c714bca 100644 --- a/eo/src/utils/eoUpdater.h +++ b/eo/src/utils/eoUpdater.h @@ -50,6 +50,32 @@ class eoUpdater : public eoF eoUpdater& addTo(eoCheckPoint& cp) { cp.add(*this); return *this; } }; +/** + An eoUpdater that simply calls a function with no arguments + + @ingroup Utilities +*/ +class eoFunctionCaller : public eoUpdater +{ +public : + + /** Default Ctor - requires a pointer to the function to call */ + eoFunctionCaller(void (*_fct)()) + : fct(_fct) + { } + + /** Simply call the function */ + virtual void operator()() + { + (*fct)(); + } + + virtual std::string className(void) const { return "eoFunctionCaller"; } + +private: + void (*fct)(); +}; + /** an eoUpdater that simply increments a counter diff --git a/eo/test/CMakeLists.txt b/eo/test/CMakeLists.txt index 15fd22464..e283ab958 100644 --- a/eo/test/CMakeLists.txt +++ b/eo/test/CMakeLists.txt @@ -69,6 +69,7 @@ set (TEST_LIST #t-openmp # does not work anymore since functions used in this test were removed from EO #t-eoDualFitness t-eoParser + t-eoOptional ) diff --git a/eo/test/t-eoLogger.cpp b/eo/test/t-eoLogger.cpp index 198a88720..0406cb6b1 100644 --- a/eo/test/t-eoLogger.cpp +++ b/eo/test/t-eoLogger.cpp @@ -3,30 +3,78 @@ //----------------------------------------------------------------------------- #include +//#include +#include +#include +#include +#include //----------------------------------------------------------------------------- +static void test(); + int main(int ac, char** av) { eoParser parser(ac, av); if (parser.userNeedsHelp()) - { - parser.printHelp(std::cout); - exit(1); - } + { + parser.printHelp(std::cout); + exit(1); + } make_help(parser); make_verbose(parser); + test(); + + return 0; +} + +static void test() +{ eo::log << eo::setlevel(eo::debug); eo::log << eo::warnings; eo::log << "We are writing on the default output stream" << std::endl; - eo::log << eo::file("test.txt") << "In FILE" << std::endl; - eo::log << std::cout << "on COUT" << std::endl; + { + eo::log.redirect("logtest.txt"); + eo::log << "In FILE" << std::endl; + std::ofstream ofs("logtest2.txt"); // closed and destroyed at the en of the scope + eo::log.addRedirect(ofs); + eo::log << "In FILE 2" << std::endl; + eo::log.removeRedirect(ofs); // must be removed because the associated stream is closed + } + + std::ifstream ifs("logtest2.txt"); // stream to logtest2.txt is closed, we can start reading + std::string line; + assert(std::getline(ifs, line)); + assert(line == "In FILE 2"); + assert(!std::getline(ifs, line)); + + std::ostringstream oss; + eo::log.addRedirect(oss); + eo::log << "In STRINGSTREAM"; + + std::cout << "Content of ostringstream: " << oss.str() << std::endl; + assert(oss.str() == "In STRINGSTREAM"); + + eo::log.redirect(std::cout); // removes all previously redirected streams; closes the file logtest.txt + eo::log << "on COUT" << std::endl; + + + ifs.close(); + ifs.open("logtest.txt"); + assert(std::getline(ifs, line)); + assert(line == "In FILE"); + assert(std::getline(ifs, line)); + assert(line == "In FILE 2"); + assert(std::getline(ifs, line)); + assert(line == "In STRINGSTREAM"); + assert(!std::getline(ifs, line)); + eo::log << eo::setlevel("errors"); eo::log << eo::setlevel(eo::errors); @@ -42,9 +90,8 @@ int main(int ac, char** av) eo::log << std::endl; eo::log << eo::debug << 4 << ')' - << "4) in debug mode\n"; - - return 0; + << "4) in debug mode\n"; + } //----------------------------------------------------------------------------- diff --git a/eo/test/t-eoOptional.cpp b/eo/test/t-eoOptional.cpp new file mode 100644 index 000000000..5b4a9fbc2 --- /dev/null +++ b/eo/test/t-eoOptional.cpp @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// t-eoOptional.cpp +//----------------------------------------------------------------------------- + +#include "eoOptional.h" + +//----------------------------------------------------------------------------- + +typedef int T; + +struct MyClass { + MyClass(eoOptional my_T = NULL) + : default_T(42), actual_T(my_T.getOr(default_T)) + { + std::cout << "Value " << actual_T << " was used for construction" << std::endl; + } +private: + T default_T; + T& actual_T; +}; + +int main(int ac, char** av) +{ + // Three ways of using MyClass: + MyClass mc1; + MyClass mc2(NULL); + T t(666); + MyClass mc3(t); +} + diff --git a/mo/src/algo/moLocalSearch.h b/mo/src/algo/moLocalSearch.h index bf77a8f3f..6a6af507d 100644 --- a/mo/src/algo/moLocalSearch.h +++ b/mo/src/algo/moLocalSearch.h @@ -47,99 +47,116 @@ template class moLocalSearch: public eoMonOp { public: - typedef moNeighborhood Neighborhood; - typedef moNeighborhoodExplorer NeighborhoodExplorer; - typedef typename Neighbor::EOT EOT; - - /** - * Constructor of a moLocalSearch - * @param _searchExpl a neighborhood explorer - * @param _cont an external continuator (can be a checkpoint!) - * @param _fullEval a full evaluation function - */ - moLocalSearch(NeighborhoodExplorer& _searchExpl, - moContinuator & _cont, eoEvalFunc& _fullEval) : - searchExplorer(_searchExpl), cont(&_cont), fullEval(_fullEval) { - } - ; - - /** - * Run the local search on a solution - * @param _solution the related solution - */ - virtual bool operator()(EOT & _solution) { - - if (_solution.invalid()) - fullEval(_solution); - - // initialization of the parameter of the search (for example fill empty the tabu list) - searchExplorer.initParam(_solution); - - // initialization of the external continuator (for example the time, or the number of generations) - cont->init(_solution); - - bool b; - do { - // explore the neighborhood of the solution - searchExplorer(_solution); - // if a solution in the neighborhood can be accepted - if (searchExplorer.accept(_solution)) { - searchExplorer.move(_solution); - searchExplorer.moveApplied(true); - } else - searchExplorer.moveApplied(false); - - // update the parameter of the search (for ex. Temperature of the SA) - searchExplorer.updateParam(_solution); - - b = (*cont)(_solution); - } while (b && searchExplorer.isContinue(_solution)); - - searchExplorer.terminate(_solution); - - cont->lastCall(_solution); - - return true; - } - ; - - /** - * Set an external continuator - * @param _cont the external continuator - */ - void setContinuator(moContinuator & _cont) { - cont = &_cont; - } - - /** - * external continuator object - * - * @overload - * @return the external continuator - */ - moContinuator* getContinuator() const { - return cont; - } - - /** - * to get the neighborhood explorer - * - * @overload - * @return the neighborhood explorer - */ - moNeighborhoodExplorer & getNeighborhoodExplorer() const { - return searchExplorer; - } + typedef moNeighborhood Neighborhood; + typedef moNeighborhoodExplorer NeighborhoodExplorer; + typedef typename Neighbor::EOT EOT; + + /** + * Constructor of a moLocalSearch + * @param _searchExpl a neighborhood explorer + * @param _cont an external continuator (can be a checkpoint!) + * @param _fullEval a full evaluation function + */ + moLocalSearch(NeighborhoodExplorer& _searchExpl, moContinuator & _cont, eoEvalFunc& _fullEval) + : searchExplorer(_searchExpl), cont(&_cont), fullEval(_fullEval), currentSolutionFitness(0) + { } + + /** + * Run the local search on a solution + * @param _solution the related solution + */ + virtual bool operator()(EOT & _solution) { + + if (_solution.invalid()) + fullEval(_solution); + + // initialization of the parameter of the search (for example fill empty the tabu list) + searchExplorer.initParam(_solution); + + // initialization of the external continuator (for example the time, or the number of generations) + cont->init(_solution); + + bool b; + + do + { + currentSolutionFitness = _solution.fitness(); + + // explore the neighborhood of the solution + searchExplorer(_solution); + // if a solution in the neighborhood can be accepted + if (searchExplorer.accept(_solution)) { + searchExplorer.move(_solution); + searchExplorer.moveApplied(true); + } else + searchExplorer.moveApplied(false); + + // update the parameter of the search (for ex. Temperature of the SA) + searchExplorer.updateParam(_solution); + + b = (*cont)(_solution); + } + while (b && searchExplorer.isContinue(_solution)); + + searchExplorer.terminate(_solution); + + cont->lastCall(_solution); + + return true; + } + + /** + * Set an external continuator + * @param _cont the external continuator + */ + void setContinuator(moContinuator & _cont) { + cont = &_cont; + } + + /** + * external continuator object + * + * @overload + * @return the external continuator + */ + moContinuator* getContinuator() const { + return cont; + } + + /** + * to get the neighborhood explorer + * + * @overload + * @return the neighborhood explorer + */ + moNeighborhoodExplorer & getNeighborhoodExplorer() const { + return searchExplorer; + } + + /** + * Useful for monitoring with anb eoGetterUpdater + * @return the fitness of the last computed solution + */ + double getCurrentSolutionFitness() const { + return currentSolutionFitness; + } protected: - // make the exploration of the neighborhood according to a local search heuristic - moNeighborhoodExplorer& searchExplorer; - - // external continuator - moContinuator * cont; - - //full evaluation function - eoEvalFunc& fullEval; + + // make the exploration of the neighborhood according to a local search heuristic + moNeighborhoodExplorer& searchExplorer; + + // external continuator + moContinuator * cont; + + //full evaluation function + eoEvalFunc& fullEval; + +private: + + // fitness of the last computed solution + double currentSolutionFitness; + }; #endif diff --git a/mo/src/algo/moMetropolisHasting.h b/mo/src/algo/moMetropolisHastings.h similarity index 53% rename from mo/src/algo/moMetropolisHasting.h rename to mo/src/algo/moMetropolisHastings.h index 5b4292459..dc7ec2f30 100644 --- a/mo/src/algo/moMetropolisHasting.h +++ b/mo/src/algo/moMetropolisHastings.h @@ -2,7 +2,7 @@ Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010 -Sebastien Verel, Arnaud Liefooghe, Jeremie Humeau +Sebastien Verel, Arnaud Liefooghe, Jeremie Humeau, Lionel Parreaux This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can ue, @@ -27,11 +27,12 @@ ParadisEO WebSite : http://paradiseo.gforge.inria.fr Contact: paradiseo-help@lists.gforge.inria.fr */ -#ifndef _moMetropolisHasting_h -#define _moMetropolisHasting_h +#ifndef _moMetropolisHastings_h +#define _moMetropolisHastings_h #include -#include +#include +#include #include #include #include @@ -50,61 +51,50 @@ Contact: paradiseo-help@lists.gforge.inria.fr * the algorithm stops when the number of iterations is too large */ template -class moMetropolisHasting: public moLocalSearch +class moMetropolisHastings: public moLocalSearch { public: typedef typename Neighbor::EOT EOT; typedef moNeighborhood Neighborhood ; - - /** - * Basic constructor of the Metropolis-Hasting - * @param _neighborhood the neighborhood - * @param _fullEval the full evaluation function - * @param _eval neighbor's evaluation function - * @param _nbStep maximum step to do - */ - moMetropolisHasting(Neighborhood& _neighborhood, eoEvalFunc& _fullEval, moEval& _eval, unsigned int _nbStep): - moLocalSearch(explorer, trueCont, _fullEval), - explorer(_neighborhood, _eval, defaultNeighborComp, defaultSolNeighborComp, _nbStep) - {} - - /** - * Simple constructor of the Metropolis-Hasting - * @param _neighborhood the neighborhood - * @param _fullEval the full evaluation function - * @param _eval neighbor's evaluation function - * @param _nbStep maximum step to do - * @param _cont an external continuator - */ - moMetropolisHasting(Neighborhood& _neighborhood, eoEvalFunc& _fullEval, moEval& _eval, unsigned int _nbStep, moContinuator& _cont): - moLocalSearch(explorer, _cont, _fullEval), - explorer(_neighborhood, _eval, defaultNeighborComp, defaultSolNeighborComp, _nbStep) - {} - + /** - * General constructor of the Metropolis-Hasting + * General constructor of the Metropolis-Hastings algotrithm * @param _neighborhood the neighborhood * @param _fullEval the full evaluation function * @param _eval neighbor's evaluation function * @param _nbStep maximum step to do * @param _cont an external continuator - * @param _compN a neighbor vs neighbor comparator * @param _compSN a solution vs neighbor comparator */ - moMetropolisHasting(Neighborhood& _neighborhood, eoEvalFunc& _fullEval, moEval& _eval, unsigned int _nbStep, moContinuator& _cont, moNeighborComparator& _compN, moSolNeighborComparator& _compSN): - moLocalSearch(explorer, _cont, _fullEval), - explorer(_neighborhood, _eval, _compN, _compSN, _nbStep) - {} - + moMetropolisHastings( + Neighborhood& _neighborhood + , eoEvalFunc& _fullEval + , moEval& _eval + , unsigned int _nbStep + , eoOptional< moContinuator > _cont = NULL + , eoOptional< moSolNeighborComparator > _compSN = NULL + ) + : moLocalSearch(explorer, _cont.getOr(trueCont), _fullEval) + , explorer(_neighborhood, _eval, _nbStep, _compSN) + { } + private: + // always true continuator moTrueContinuator trueCont; - // compare the fitness values of neighbors - moNeighborComparator defaultNeighborComp; - // compare the fitness values of the solution and the neighbor - moSolNeighborComparator defaultSolNeighborComp; - // MetropolisHasting explorer - moMetropolisHastingExplorer explorer; + + // Default Metropolis-Hasting explorer + moSimpleMetropolisHastingsExplorer explorer; + }; #endif + + + + + + + + + diff --git a/mo/src/algo/moSA.h b/mo/src/algo/moSA.h index c126f31fc..8bc434233 100644 --- a/mo/src/algo/moSA.h +++ b/mo/src/algo/moSA.h @@ -2,7 +2,7 @@ Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010 -Sébastien Verel, Arnaud Liefooghe, Jérémie Humeau +Sébastien Verel, Arnaud Liefooghe, Jérémie Humeau, Lionel Parreaux This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can ue, @@ -31,12 +31,13 @@ Contact: paradiseo-help@lists.gforge.inria.fr #define _moSA_h #include -#include +#include #include #include #include #include #include +#include /** * Simulated Annealing @@ -60,61 +61,96 @@ class moSA: public moLocalSearch * @param _span number of iteration with equal temperature for cooling schedule (default = 100) * @param _finalT final temperature, threshold of the stopping criteria for cooling schedule (default = 0.01) */ - moSA(Neighborhood& _neighborhood, eoEvalFunc& _fullEval, moEval& _eval, double _initT=10, double _alpha=0.9, unsigned _span=100, double _finalT=0.01): - moLocalSearch(explorer, trueCont, _fullEval), - defaultCool(_initT, _alpha, _span, _finalT), - explorer(_neighborhood, _eval, defaultSolNeighborComp, defaultCool) - {} - - /** - * Simple constructor for a simulated annealing - * @param _neighborhood the neighborhood - * @param _fullEval the full evaluation function - * @param _eval neighbor's evaluation function - * @param _cool a cooling schedule - */ - moSA(Neighborhood& _neighborhood, eoEvalFunc& _fullEval, moEval& _eval, moCoolingSchedule& _cool): - moLocalSearch(explorer, trueCont, _fullEval), - defaultCool(0, 0, 0, 0), - explorer(_neighborhood, _eval, defaultSolNeighborComp, _cool) - {} - + moSA( + Neighborhood& _neighborhood, + eoEvalFunc& _fullEval, + moEval& _eval, + double _initT=10, + double _alpha=0.9, + unsigned _span=100, + double _finalT=0.01 + ) + : moLocalSearch ( + *(explorer_ptr = defaultExplorer = new moSAExplorer(_neighborhood, _eval, *(defaultCool = new moSimpleCoolingSchedule(_initT, _alpha, _span, _finalT)), NULL)), + *(defaultContinuator = new moTrueContinuator()), + _fullEval ), + explorer(*explorer_ptr), + defaultEval(NULL) // removed in C++11 with unique_ptr + { } + /** * General constructor for a simulated annealing * @param _neighborhood the neighborhood * @param _fullEval the full evaluation function - * @param _eval neighbor's evaluation function * @param _cool a cooling schedule + * @param _eval neighbor's evaluation function * @param _cont an external continuator + * @param _comp a solution vs neighbor comparator */ - moSA(Neighborhood& _neighborhood, eoEvalFunc& _fullEval, moEval& _eval, moCoolingSchedule& _cool, moContinuator& _cont): - moLocalSearch(explorer, _cont, _fullEval), - defaultCool(0, 0, 0, 0), - explorer(_neighborhood, _eval, defaultSolNeighborComp, _cool) - {} - + moSA ( + Neighborhood& _neighborhood, + eoEvalFunc& _fullEval, + moCoolingSchedule& _cool, + eoOptional< moEval > _eval = NULL, + eoOptional< moContinuator > _cont = NULL, + eoOptional< moSolNeighborComparator > _comp = NULL + ) + : moLocalSearch ( + *(explorer_ptr = defaultExplorer = new moSAExplorer ( + _neighborhood, + _eval.hasValue()? defaultEval = NULL, _eval.get(): *(defaultEval = new moFullEvalByCopy(_fullEval)), + // C++11: _eval.hasValue()? _eval.get(): *(defaultEval = new moFullEvalByCopy(_fullEval)), + _cool, + _comp )), + // ), + _cont.hasValue()? defaultContinuator = NULL, _cont.get(): *(defaultContinuator = new moTrueContinuator()), + _fullEval ), + explorer(*explorer_ptr), + defaultCool(NULL) // removed in C++11 with unique_ptr + { } + /** - * General constructor for a simulated annealing - * @param _neighborhood the neighborhood + * More general constructor for a simulated annealing, giving the explorer explicitly * @param _fullEval the full evaluation function - * @param _eval neighbor's evaluation function - * @param _cool a cooling schedule - * @param _comp a solution vs neighbor comparator + * @param _explorer the SA explorer * @param _cont an external continuator */ - moSA(Neighborhood& _neighborhood, eoEvalFunc& _fullEval, moEval& _eval, moCoolingSchedule& _cool, moSolNeighborComparator& _comp, moContinuator& _cont): - moLocalSearch(explorer, _cont, _fullEval), - defaultCool(0, 0, 0, 0), - explorer(_neighborhood, _eval, _comp, _cool) - {} - - + moSA ( + eoEvalFunc& _fullEval, + moSAExplorer& _explorer, + eoOptional< moContinuator > _cont = NULL + ) + : moLocalSearch ( + *(explorer_ptr = &_explorer), + _cont.hasValue()? defaultContinuator = NULL, _cont.get(): *(defaultContinuator = new moTrueContinuator()), _fullEval ), + defaultEval(NULL), // removed in C++11 with unique_ptr + defaultExplorer(NULL), // removed in C++11 with unique_ptr + explorer(*explorer_ptr), + defaultCool(NULL) // removed in C++11 with unique_ptr + { } + + virtual ~moSA () + { + // Note: using unique_ptr would allow us to remove this explicit destructor, but they were only introduced in C++11 + if (defaultContinuator != NULL) + delete defaultContinuator; + if (defaultCool != NULL) + delete defaultCool; + if (defaultExplorer != NULL) + delete defaultExplorer; + if (defaultEval != NULL) + delete defaultEval; + } private: - moTrueContinuator trueCont; - moSimpleCoolingSchedule defaultCool; - moSolNeighborComparator defaultSolNeighborComp; - moSAexplorer explorer; + moFullEvalByCopy* defaultEval; + moSAExplorer* defaultExplorer; + moSAExplorer* explorer_ptr; // Should never be NULL + moSAExplorer& explorer; // Not very useful field (not used yet) + moSimpleCoolingSchedule* defaultCool; // C++11: const std::unique_ptr> defaultCool; + moTrueContinuator* defaultContinuator; }; #endif + + diff --git a/mo/src/continuator/moCheckpoint.h b/mo/src/continuator/moCheckpoint.h index 37b5cd610..950b96fa0 100644 --- a/mo/src/continuator/moCheckpoint.h +++ b/mo/src/continuator/moCheckpoint.h @@ -107,14 +107,23 @@ public : virtual void init(EOT& _sol) { for (unsigned i = 0; i < stats.size(); ++i) stats[i]->init(_sol); - counter=1; - + counter = 1; + for (unsigned i = 0; i < moupdaters.size(); ++i) moupdaters[i]->init(); - + + //for (unsigned i = 0; i < updaters.size(); ++i) + // updaters[i]->init(); + + /* + * Removed because there was no reason for it to be done here + * It caused premature monitoring of eoParams with uninitialized values + * (eoUpdater's don't have a init function) + * for (unsigned int i = 0; i < monitors.size(); ++i) (*monitors[i])(); - + */ + for (unsigned i = 0; i < continuators.size(); ++i) continuators[i]->init(_sol); } diff --git a/mo/src/continuator/moCounterMonitorSaver.h b/mo/src/continuator/moCounterMonitorSaver.h index f57e05d2d..6ac5a7062 100644 --- a/mo/src/continuator/moCounterMonitorSaver.h +++ b/mo/src/continuator/moCounterMonitorSaver.h @@ -52,7 +52,11 @@ public : moCounterMonitorSaver(unsigned _interval, eoMonitor& _mon) : interval(_interval), counter(0) { monitors.push_back(&_mon); } - + + moCounterMonitorSaver(unsigned _interval) + : interval(_interval), counter(0) + { } + /** * call monitors if interval is reach by a counter */ diff --git a/mo/src/continuator/moFitnessMomentsStat.h b/mo/src/continuator/moFitnessMomentsStat.h new file mode 100644 index 000000000..4bd550b76 --- /dev/null +++ b/mo/src/continuator/moFitnessMomentsStat.h @@ -0,0 +1,105 @@ +/* + +(c) Thales group, 2010 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +#ifndef moFitnessMomentsStat_h +#define moFitnessMomentsStat_h + +#include +#include + +/** + * Statistic that saves the average and variance of the fitness of the solutions during the search + */ +template +//class moFitnessMomentsStat : public moStat > +class moFitnessMomentsStat : public moStat > +{ +public : + typedef typename EOT::Fitness Fitness; + //typedef std::pair Pair; + typedef std::pair Pair; + using moStat::value; + + /** + * Default Constructor + * @param _reInitSol when true the best so far is reinitialized + */ + moFitnessMomentsStat(bool _reInitSol = true) + : moStat(Pair(Fitness(), 0.0), "moments (average and stdev)"), + reInitSol(_reInitSol), firstTime(true), + nbSolutionsEncountered(0), currentAvg(0), currentVar(0) + { } + + /** + * Initialization of the best solution on the first one + * @param _sol the first solution + */ + virtual void init(EOT & _sol) { + if (reInitSol || firstTime) + { + value() = Pair(0.0,0.0); + nbSolutionsEncountered = currentAvg = currentVar = 0; + firstTime = false; + } + operator()(_sol); + } + + /** + * Update the best solution + * @param _sol the current solution + */ + virtual void operator()(EOT & _sol) { + ++nbSolutionsEncountered; + double x = _sol.fitness(); + double oldAvg = currentAvg; + currentAvg = oldAvg + (x - oldAvg)/nbSolutionsEncountered; + if (nbSolutionsEncountered > 1) // <- not really necessary + { + //value() = (value()/nbSolutionsEncountered + _sol.fitness())/(nbSolutionsEncountered+1); + double oldVar = currentVar; + currentVar = oldVar + (x - oldAvg) * (x - currentAvg); + value() = Pair(currentAvg, currentVar/nbSolutionsEncountered); + } + } + + /** + * @return name of the class + */ + virtual std::string className(void) const { + return "moFitnessVarianceStat"; + } + +protected: + bool reInitSol; + bool firstTime; + double + nbSolutionsEncountered + , currentAvg + , currentVar // actually the var * n + ; + +}; + +#endif // moFitnessMomentsStat_h diff --git a/mo/src/continuator/moFitnessVarianceStat.h b/mo/src/continuator/moFitnessVarianceStat.h new file mode 100644 index 000000000..844b8af5d --- /dev/null +++ b/mo/src/continuator/moFitnessVarianceStat.h @@ -0,0 +1,97 @@ +/* + +(c) Thales group, 2010 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +#ifndef moFitnessVarianceStat_h +#define moFitnessVarianceStat_h + +#include + +/** + * Statistic that incrementally computes the variance of the fitness of the solutions during the search + */ +template +class moFitnessVarianceStat : public moStat +{ +public : + typedef typename EOT::Fitness Fitness; + using moStat< EOT , typename EOT::Fitness >::value; + + /** + * Default Constructor + * @param _reInitSol when true the best so far is reinitialized + */ + moFitnessVarianceStat(bool _reInitSol = true) + : moStat(Fitness(), "var"), + reInitSol(_reInitSol), firstTime(true), + nbSolutionsEncountered(0), currentAvg(0), currentVar(0) + { } + + /** + * Initialization of the best solution on the first one + * @param _sol the first solution + */ + virtual void init(EOT & _sol) { + if (reInitSol || firstTime) + { + value() = 0.0; + nbSolutionsEncountered = currentAvg = currentVar = 0; + firstTime = false; + } + operator()(_sol); + } + + /** + * Update the best solution + * @param _sol the current solution + */ + virtual void operator()(EOT & _sol) { + ++nbSolutionsEncountered; + double x = _sol.fitness(); + double oldAvg = currentAvg; + currentAvg = oldAvg + (x - oldAvg)/nbSolutionsEncountered; + double oldVar = currentVar; + currentVar = oldVar + (x - oldAvg) * (x - currentAvg); + value() = currentVar/nbSolutionsEncountered; + } + + /** + * @return name of the class + */ + virtual std::string className(void) const { + return "moFitnessVarianceStat"; + } + +protected: + bool reInitSol; + bool firstTime; + double + nbSolutionsEncountered + , currentAvg + , currentVar // actually the var * n + ; + +}; + +#endif // moFitnessVarianceStat_h diff --git a/mo/src/continuator/moStdFitnessNeighborStat.h b/mo/src/continuator/moStdFitnessNeighborStat.h index b9a547954..4c058c8ee 100644 --- a/mo/src/continuator/moStdFitnessNeighborStat.h +++ b/mo/src/continuator/moStdFitnessNeighborStat.h @@ -42,7 +42,7 @@ * From moNeighborhoodStat, to compute the average and the standard deviation of fitness in the neighborhood */ template< class Neighbor > -class moStdFitnessNeighborStat : public moStat +class moStdFitnessNeighborStat : public moStat { public : typedef typename Neighbor::EOT EOT ; diff --git a/mo/src/continuator/moUpdater.h b/mo/src/continuator/moUpdater.h index 0be846d38..37a26a04f 100644 --- a/mo/src/continuator/moUpdater.h +++ b/mo/src/continuator/moUpdater.h @@ -39,9 +39,8 @@ #include /** - * Base class for to update what ever you want - * similar to eoUpdater - * But there is an init method ! + * Base class for updating whatever you want. + * Similar to eoUpdater, but there is an "init" method ! */ class moUpdater : public eoF { diff --git a/mo/src/coolingSchedule/moCoolingSchedule.h b/mo/src/coolingSchedule/moCoolingSchedule.h index 9b65cf1b5..b9863b02f 100644 --- a/mo/src/coolingSchedule/moCoolingSchedule.h +++ b/mo/src/coolingSchedule/moCoolingSchedule.h @@ -55,8 +55,9 @@ class moCoolingSchedule : public eoUF * update the temperature * @param _temp current temperature to update * @param _acceptedMove true when the move is accepted, false otherwise + * @param _currentSolution the current solution */ - virtual void update(double& _temp, bool _acceptedMove) = 0; + virtual void update(double& _temp, bool _acceptedMove, EOT & _currentSolution) = 0; }; diff --git a/mo/src/coolingSchedule/moDynSpanCoolingSchedule.h b/mo/src/coolingSchedule/moDynSpanCoolingSchedule.h index 34b386312..5ec3a886c 100644 --- a/mo/src/coolingSchedule/moDynSpanCoolingSchedule.h +++ b/mo/src/coolingSchedule/moDynSpanCoolingSchedule.h @@ -80,26 +80,27 @@ class moDynSpanCoolingSchedule : public moCoolingSchedule * update the temperature by a factor * @param _temp current temperature to update * @param _acceptedMove true when the move is accepted, false otherwise + * @param _currentSolution the current solution */ - virtual void update(double& _temp, bool _acceptedMove) { - spanTries++; - - if (_acceptedMove) - spanMove++; - - if (spanTries >= spanTriesMax || spanMove >= spanMoveMax) { - _temp *= alpha; - - if (spanMove == 0) // no move during this span ? - nbSpan++; - else - nbSpan = 0; - - spanTries = 0; - spanMove = 0; - } - } - + virtual void update(double& _temp, bool _acceptedMove, EOT & _currentSolution) { + spanTries++; + + if (_acceptedMove) + spanMove++; + + if (spanTries >= spanTriesMax || spanMove >= spanMoveMax) { + _temp *= alpha; + + if (spanMove == 0) // no move during this span ? + nbSpan++; + else + nbSpan = 0; + + spanTries = 0; + spanMove = 0; + } + } + /** * compare the number of span with no move * @param _temp current temperature diff --git a/mo/src/coolingSchedule/moHuangCoolingSchedule.h b/mo/src/coolingSchedule/moHuangCoolingSchedule.h new file mode 100644 index 000000000..47c000692 --- /dev/null +++ b/mo/src/coolingSchedule/moHuangCoolingSchedule.h @@ -0,0 +1,138 @@ +/* + +(c) Thales group, 2010 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +#ifndef _moHuangCoolingSchedule_h +#define _moHuangCoolingSchedule_h + +#include + +#include + +#include +#include +#include +#include + +/** + * Cooling Schedule, adapted from E.Triki, Y.Collette, P.Siarry (2004) + * Fairly simple CS that is supposed to work fairly well. + */ +template< class EOT > +class moHuangCoolingSchedule: public moCoolingSchedule< EOT > +{ +public: + + /** + * Constructor for the cooling schedule + * @param _initTemp the temperature at which the CS begins + * @param _spanSize the number of steps to perform between each decrease of temperature + * @param _lambda determines the decrease factor of the temperature, ie: alpha = e^(-lambda*T/stddev) + * @param _finalTempDecrease + */ + moHuangCoolingSchedule (double _initTemp, int _spanSize, double _lambda = .7, double _finalTempDecrease = .995) + : initTemp(_initTemp) + , spanSize(_spanSize) + , lambda(_lambda) + , finalStdDev(_finalTempDecrease) + { } + + /** + * Initialization + * @param _solution initial solution + */ + double init(EOT & _solution) { + statIsInitialized = terminated = false; + step = 0; + return initTemp; + } + + /** + * update the temperature by a factor + * @param _temp current temperature to update + * @param _acceptedMove true when the move is accepted, false otherwise + */ + void update(double& _temp, bool _acceptedMove, EOT & _solution) { + + if (_acceptedMove) + { + if (statIsInitialized) + momentStat(_solution); + else momentStat.init(_solution), statIsInitialized = true; + + } + + if (step >= spanSize) + { + step = 0; + double alpha = exp( -lambda*_temp / sqrt(momentStat.value().second) ); + _temp *= alpha; + terminated = alpha > finalStdDev; + } + + step++; + } + + /* + * operator() Determines if the cooling schedule shall end or continue + * @param temperature the current temperature + */ + bool operator() (double temperature) + { + return !terminated; + } + + +private: + + // parameters of the algorithm + + const double + initTemp + , lambda + , finalStdDev + ; + const int spanSize; + int step; + + + // variables of the algorithm + + bool statIsInitialized, terminated; + + moFitnessMomentsStat momentStat; + +}; + +#endif + + + + + + + + + + diff --git a/mo/src/coolingSchedule/moSimpleCoolingSchedule.h b/mo/src/coolingSchedule/moSimpleCoolingSchedule.h index 5ff4f4920..aa8f1138f 100644 --- a/mo/src/coolingSchedule/moSimpleCoolingSchedule.h +++ b/mo/src/coolingSchedule/moSimpleCoolingSchedule.h @@ -52,7 +52,8 @@ class moSimpleCoolingSchedule : public moCoolingSchedule * @param _span number of iteration with equal temperature * @param _finalT final temperature, threshold of the stopping criteria */ - moSimpleCoolingSchedule(double _initT, double _alpha, unsigned _span, double _finalT) : initT(_initT), alpha(_alpha), span(_span), finalT(_finalT) {} + moSimpleCoolingSchedule(double _initT, double _alpha, unsigned _span, double _finalT) + : initT(_initT), alpha(_alpha), span(_span), finalT(_finalT) {} /** * Getter on the initial temperature @@ -70,8 +71,9 @@ class moSimpleCoolingSchedule : public moCoolingSchedule * update the temperature by a factor * @param _temp current temperature to update * @param _acceptedMove true when the move is accepted, false otherwise + * @param _currentSolution the current solution */ - virtual void update(double& _temp, bool _acceptedMove) { + virtual void update(double& _temp, bool _acceptedMove, EOT & _currentSolution) { if (step >= span) { _temp *= alpha; step = 0; diff --git a/mo/src/coolingSchedule/moTrikiCoolingSchedule.h b/mo/src/coolingSchedule/moTrikiCoolingSchedule.h new file mode 100644 index 000000000..bbb60ee2b --- /dev/null +++ b/mo/src/coolingSchedule/moTrikiCoolingSchedule.h @@ -0,0 +1,450 @@ +/* + +(c) Thales group, 2010 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +#ifndef _moTrikiCoolingSchedule_h +#define _moTrikiCoolingSchedule_h + +#include + +#include + +#include +#include +#include +#include + +/** + * Cooling Schedule, adapted from E.Triki, Y.Collette, P.Siarry (2004) + * This CS is based on an initial estimation of the standard deviation + * and an expected decrease in cost between each Markov chain, + * possibly re-estimating the prameters + * + * + * A detailed explanation follows: + * + * + * Initialization + * + * A random walk of n steps should be performed to estimate the std dev + * of the fitness. The init temp is set to this value. + * + * + * Algorithm + * + * The CS is based on Markov chains, during which the temp is constant. + * A Markov chain ends when a given number of solutions 'max_accepted' + * has been reached, or when a given number 'max_generated' of solutions + * have been generated. + * + * After each chain, the average cost of the solutions of the chain is + * expected to have decreased of delta (compared to the previous chain) + * with delta initialized to = stddev/mu2. + * If it's the case (ie: avgCost/(prevAvgCost-delta) < xi, where xi == 1+epsilon) + * then we say we're at equilibrium and we apply a normal temperature + * decrease, of ratio + * alpha = 1-_temp*delta/variance + * + * Negative temperatures (when alpha < 0) happen when the initial std + * dev was misestimated or, according to the article, when "the minimum + * cost is greater than the current average cost minus delta"(sic)(??). + * In case of a neg temp, we increment a counter 'negative_temp' and we + * reinitialize the algorithm until the temperature is no more negative, + * unless the counter of neg temp reaches a constant K2, in which case + * the behavior has been chosen to be this of a greedy algorithm (SA + * with nil temperature). + * + * Reinitializing the algo consists in: + * - setting the temperature "decrease" factor alpha to a + * constant lambda1 > 1 in order to in fact increase it + * - setting delta to sigma/mu1 (sigma being the std dev of the + * current Markov chain) + * + * Note that when not reinitializing, the expected decrease in cost + * 'delta' is never supposed to change. + * + * If the eq is not reached after the current chain, we increment a + * counter 'equilibrium_not_reached', and when it reaches K1 we + * reinitialize the algorithm and reset the counter to 0 (resetting + * to 0 was an added behavior and not part of the article; but without + * it the algo got trapped). + * + * + * Termination + * + * Currently, the algo terminates when the current average cost stops + * changing for 'theta' chains, or when the current std dev becomes + * null (added behavior; indeed, when the std dev is null it is no more + * possible to compute alpha), or when there is no accepted solution + * for the current "chain" (added, cf in this case we can't compute a + * std dev or an average). + * In practice, the algorithm never seems to terminate by "freezing" + * (first case), obviously because we need an implementation of + * approximate double comparison instead of exact comparison. + * + * + */ +template< class EOT > +class moTrikiCoolingSchedule: public moCoolingSchedule< EOT > +{ +public: + + /** + * Constructor for the cooling schedule + * @param _initTemp the temperature at which the CS begins; a recommended value is _stdDevEstimation + * @param _stdDevEstimation an estimation of the standard deviation of the fitness. Typically, a random walk of n steps is performed to estimate the std dev of the fitness + * @param _max_accepted maximum number of solutions to accept before ending the Markov chain and reducing the temperature; depends on the pb/neighborhood + * @param _max_generated maximum number of solutions to generate before ending the Markov chain and reducing the temperature; depends on the pb/neighborhood + * @param _mu2 target decrease in cost factor, mu2 typically belongs to [1; 20] + * @param _mu1 target decrease in cost factor when reinitializing, in [2; 20] + * @param _lambda1 the increase in temperature (reheating factor), typically in [1.5; 4] + * @param _lambda2 lambda2 in [0.5; 0.99] + * @param _xi typically belongs to [1; 1.1] + * @param _theta typically set to 10 + * @param _K1 in [1; 4], the number of chains without reaching equilibrium before we raise the temperature + * @param _K2 maximul number of consecutive negative temperatures before switching to a greedy algorithm + */ + moTrikiCoolingSchedule ( + double _initTemp, + double _stdDevEstimation, + int _max_accepted = 50, + int _max_generated = 100, + double _mu2 = 2.5, + double _mu1 = 10, + double _lambda1 = 2, + double _lambda2 = .7, + double _xi = 1.05, + int _theta = 10, + int _K1 = 10, + int _K2 = 5 + ) + : initTemp(_initTemp), + initStdDev(_stdDevEstimation), + mu2(_mu2), + K1(_K1), + K2(_K2), + lambda1(_lambda1), + lambda2(_lambda2), + mu1(_mu1), + xi(_xi), + max_accepted(_max_accepted), + max_generated(_max_generated), + theta(_theta), + statIsInitialized(false) + { + chainStat.temperature = initTemp; + } + + /** + * Initialization + * @param _solution initial solution + */ + double init(EOT & _solution) { + + chainStat.temperature = initTemp; + + accepted = generated = 0; + + negative_temp = equilibrium_not_reached = frozen = 0; + + chainStat.delta = initStdDev/mu2; + + reinitializing = false; + + return initTemp; + } + + /** + * update the temperature by a factor + * @param _temp current temperature to update + * @param _acceptedMove true when the move is accepted, false otherwise + */ + void update(double& _temp, bool _acceptedMove, EOT & _solution) { + + /* + * In the following code, things were added or modified from + * the original (incomplete) version of the algorithm + * described in [2004, Triki et al.] + * Each added/modified behavior is labelled + * with a "// ADDED!" comment. + */ + + chainStat.temperature = _temp; + chainStat.stoppingReason = NULL; + chainStat.chainEndingReason = NULL; + chainStat.equilibriumNotReached = false; + chainStat.negativeTemp = false; + chainStat.generatedSolutions = generated; + chainStat.acceptedSolutions = accepted; + + generated++; + + if (_acceptedMove) + { + accepted++; + if (statIsInitialized) + momentStat(_solution); + else momentStat.init(_solution), statIsInitialized = true; + } + + if (accepted > max_accepted || generated > max_generated) { + + chainStat.chainEndingReason = accepted > max_accepted ? chainEndingReasons[0]: chainEndingReasons[1]; + + double avgFitness = momentStat.value().first; + double prevAvgFitness = chainStat.avgFitness; + + double alpha = 0; + + if (accepted == 0) // ADDED! Otherwise the computed std dev is null; we're probably at equilibrium + { + chainStat.stoppingReason = stoppingReasons[0]; + + // Note: we could also not stop and just become greedy (temperature set to 0) + } + else + { + double avgFitness = momentStat.value().first; + double variance = momentStat.value().second; + chainStat.stdDev = sqrt(variance); + double sigma = chainStat.stdDev; + + accepted = generated = 0; + statIsInitialized = false; + + if (negative_temp < K2) + { + if (!reinitializing) + { + if (avgFitness/(prevAvgFitness-chainStat.delta) > xi) + equilibrium_not_reached++, chainStat.equilibriumNotReached = true; + else equilibrium_not_reached = 0; + } + if (equilibrium_not_reached > K1) + { + reinitializing = true; + + alpha = lambda1; + chainStat.delta = sigma/mu1; + equilibrium_not_reached = 0; // ADDED! Otherwise the algo gets trapped here! + } + else if (_temp*chainStat.delta/(sigma*sigma) >= 1) + { + negative_temp++; + reinitializing = true; + chainStat.negativeTemp = true; + + if (negative_temp < K2) + { + alpha = lambda1; + chainStat.delta = sigma/mu1; + } else + alpha = lambda2; + } + else + { + reinitializing = false; + alpha = 1-_temp*chainStat.delta/variance; + + if (sigma == 0) // ADDED! When std dev is null, the solution is probably at eq, and the algo can't go on anyways + chainStat.stoppingReason = stoppingReasons[1]; + } + } + else + { /* Note: the paper doesn't specify a value for alpha in this case. + We've chosen to let it set to 0, which means the algorithm becomes greedy. */ + alpha = 0; + } + } + + _temp *= alpha; + + chainStat.currentFitness = _solution.fitness(); + chainStat.alpha = alpha; + chainStat.avgFitness = avgFitness; + + + // TODO use a relative-epsilon comparison to approximate equality + if (avgFitness == prevAvgFitness) + frozen++; + else frozen = 0; + + if (frozen >= theta) + chainStat.stoppingReason = stoppingReasons[2]; + + } + + } + + /* + * operator() Determines if the cooling schedule shall end or continue + * @param temperature the current temperature + */ + bool operator() (double temperature) + { + + return frozen < theta + && !chainStat.stoppingReason ; // ADDED! because 'frozen' isn't a sufficient terminating criterion (yet?) + + } + + /* + * Definition of getter functions useful for monitoring the algorithm + * using an eoGetterUpdater. + */ +#define __triki_makeGetter(name, type) type name() { return chainStat.name; } + + __triki_makeGetter(stdDev, double) + __triki_makeGetter(avgFitness, double) + __triki_makeGetter(temperature, double) + __triki_makeGetter(currentFitness, double) + __triki_makeGetter(alpha, double) + __triki_makeGetter(delta, double) + + __triki_makeGetter(generatedSolutions, int) + __triki_makeGetter(acceptedSolutions, int) + + __triki_makeGetter(equilibriumNotReached, bool) + __triki_makeGetter(negativeTemp, bool) + __triki_makeGetter(terminated, bool) + + __triki_makeGetter(stoppingReason, const char *) + __triki_makeGetter(chainEndingReason, const char *) + +#undef __triki_makeGetter + + + const bool markovChainEnded() const + { + return chainStat.chainEndingReason != NULL; + } + + struct MarkovChainStats; + const MarkovChainStats& markovChainStats() const + { + return chainStat; + } + + struct MarkovChainStats { + + MarkovChainStats() + : stdDev(0), avgFitness(0), temperature(-1), currentFitness(-1), alpha(0), delta(0), + equilibriumNotReached(false), negativeTemp(false) + { } + + double + stdDev, + avgFitness, + temperature, + currentFitness, + alpha, + delta + ; + int generatedSolutions, acceptedSolutions; + bool equilibriumNotReached, negativeTemp; + const char * stoppingReason; // if NULL, the algo has not stopped + const char * chainEndingReason; // if NULL, the chain has not ended + + void print(std::ostream& os = std::cout, bool onlyWhenChainEnds = true) const + { + if (chainEndingReason != NULL || !onlyWhenChainEnds) + { + os << "T=" << temperature << " avgFitness=" << avgFitness << " stdDev=" << stdDev + << " currentFitness=" << currentFitness << " expected decrease in cost=" << delta + << std::endl; + if (chainEndingReason) + os << "T*=" << alpha << " chain ended, because " << chainEndingReason; + if (equilibriumNotReached) + os << " /!\\ equilibrium not reached"; + if (negativeTemp) + os << " /!\\ negative temperature"; + os << std::endl; + if (stoppingReason) + os << "Terminated, because " << stoppingReason << std::endl; + } + } + + }; + + +private: + + // parameters of the algorithm + + const double + initTemp, + initStdDev, + mu2, + K1, + K2, + lambda1, + lambda2, + mu1, + xi + ; + const int + max_accepted, + max_generated, + theta + ; + + // Variables of the algorithm + + MarkovChainStats chainStat; + + int + accepted, + generated, + equilibrium_not_reached, + negative_temp, + frozen + ; + + bool statIsInitialized, reinitializing; + + moFitnessMomentsStat momentStat; + + + // Possible reasons why the algorithm has stopped + static const char * stoppingReasons[]; + + // Possible reasons why the previous Markov chain has ended + static const char * chainEndingReasons[]; + +}; + + +/* + * Definition of the static members of the class + */ +template< class Neighbor > +const char * moTrikiCoolingSchedule::stoppingReasons[] = {"no accepted solution", "null std dev" , "frozen >= theta"}; +template< class Neighbor > +const char * moTrikiCoolingSchedule::chainEndingReasons[] = {"MAX ACCepted solutions", "MAX GENerated solutions"}; + + +#endif + + + diff --git a/mo/src/explorer/moMetropolisHastingExplorer.h b/mo/src/explorer/moMetropolisHastingExplorer.h deleted file mode 100644 index 3123c4914..000000000 --- a/mo/src/explorer/moMetropolisHastingExplorer.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - - Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010 - - Sébastien Verel, Arnaud Liefooghe, Jérémie Humeau - - This software is governed by the CeCILL license under French law and - abiding by the rules of distribution of free software. You can use, - modify and/ or redistribute the software under the terms of the CeCILL - license as circulated by CEA, CNRS and INRIA at the following URL - "http://www.cecill.info". - - As a counterpart to the access to the source code and rights to copy, - modify and redistribute granted by the license, users are provided only - with a limited warranty and the software's author, the holder of the - economic rights, and the successive licensors have only limited liability. - - In this respect, the user's attention is drawn to the risks associated - with loading, using, modifying and/or developing or reproducing the - software by the user in light of its specific status of free software, - that may mean that it is complicated to manipulate, and that also - therefore means that it is reserved for developers and experienced - professionals having in-depth computer knowledge. Users are therefore - encouraged to load and test the software's suitability as regards their - requirements in conditions enabling the security of their systems and/or - data to be ensured and, more generally, to use and operate it in the - same conditions as regards security. - The fact that you are presently reading this means that you have had - knowledge of the CeCILL license and that you accept its terms. - - ParadisEO WebSite : http://paradiseo.gforge.inria.fr - Contact: paradiseo-help@lists.gforge.inria.fr -*/ - -#ifndef _moMetropolisHastingExplorer_h -#define _moMetropolisHastingExplorer_h - -#include - -#include -#include -#include -#include - -#include - -/** - * Explorer for the Metropolis-Hasting Sampling. - * Only the symetric case is considered when Q(x,y) = Q(y,x) - * Fitness must be > 0 - */ -template< class Neighbor > -class moMetropolisHastingExplorer : public moNeighborhoodExplorer -{ -public: - typedef typename Neighbor::EOT EOT ; - typedef moNeighborhood Neighborhood ; - - using moNeighborhoodExplorer::neighborhood; - using moNeighborhoodExplorer::eval; - using moNeighborhoodExplorer::selectedNeighbor; - - /** - * Constructor - * @param _neighborhood the neighborhood - * @param _eval the evaluation function - * @param _neighborComparator a neighbor comparator - * @param _solNeighborComparator a solution vs neighbor comparator - * @param _nbStep maximum number of step to do - */ - moMetropolisHastingExplorer(Neighborhood& _neighborhood, moEval& _eval, moNeighborComparator& _neighborComparator, moSolNeighborComparator& _solNeighborComparator, unsigned int _nbStep) : moNeighborhoodExplorer(_neighborhood, _eval), neighborComparator(_neighborComparator), solNeighborComparator(_solNeighborComparator), nbStep(_nbStep) { - isAccept = false; - if (!neighborhood.isRandom()) { - std::cout << "moMetropolisHastingExplorer::Warning -> the neighborhood used is not random" << std::endl; - } - } - - /** - * Destructor - */ - ~moMetropolisHastingExplorer() { - } - - /** - * initialization of the number of step to be done - * @param _solution unused solution - */ - virtual void initParam(EOT & _solution) { - step = 0; - isAccept = true; - }; - - /** - * increase the number of step - * @param _solution unused solution - */ - virtual void updateParam(EOT & _solution) { - step++; - }; - - /** - * terminate: NOTHING TO DO - * @param _solution unused solution - */ - virtual void terminate(EOT & _solution) {}; - - /** - * Explore the neighborhood of a solution - * @param _solution - */ - virtual void operator()(EOT & _solution) { - //Test if _solution has a Neighbor - if (neighborhood.hasNeighbor(_solution)) { - //init the first neighbor - neighborhood.init(_solution, selectedNeighbor); - - //eval the _solution moved with the neighbor and stock the result in the neighbor - eval(_solution, selectedNeighbor); - } - else { - //if _solution hasn't neighbor, - isAccept=false; - } - }; - - /** - * continue if there is a neighbor and it is remainds some steps to do - * @param _solution the solution - * @return true there is some steps to do - */ - virtual bool isContinue(EOT & _solution) { - return (step < nbStep) ; - }; - - /** - * accept test if an ameliorated neighbor was found - * @param _solution the solution - * @return true if the best neighbor ameliorate the fitness - */ - virtual bool accept(EOT & _solution) { - double alpha=0.0; - if (neighborhood.hasNeighbor(_solution)) { - if (solNeighborComparator(_solution, selectedNeighbor)) - isAccept = true; - else { - if (_solution.fitness() != 0) { - if ( (double)selectedNeighbor.fitness() < (double)_solution.fitness()) // maximizing - alpha = (double) selectedNeighbor.fitness() / (double) _solution.fitness(); - else //minimizing - alpha = (double) _solution.fitness() / (double) selectedNeighbor.fitness(); - isAccept = (rng.uniform() < alpha) ; - } - else { - if ( (double) selectedNeighbor.fitness() < (double) _solution.fitness()) // maximizing - isAccept = true; - else - isAccept = false; - } - } - } - return isAccept; - }; - -private: - // comparator betwenn solution and neighbor or between neighbors - moNeighborComparator& neighborComparator; - moSolNeighborComparator& solNeighborComparator; - - // current number of step - unsigned int step; - - // maximum number of steps to do - unsigned int nbStep; - - // true if the move is accepted - bool isAccept ; -}; - - -#endif diff --git a/mo/src/explorer/moMetropolisHastingsExplorer.h b/mo/src/explorer/moMetropolisHastingsExplorer.h new file mode 100644 index 000000000..37bcebbdc --- /dev/null +++ b/mo/src/explorer/moMetropolisHastingsExplorer.h @@ -0,0 +1,154 @@ +/* + + Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010 + + Sébastien Verel, Arnaud Liefooghe, Jérémie Humeau, Lionel Parreaux + + This software is governed by the CeCILL license under French law and + abiding by the rules of distribution of free software. You can use, + modify and/ or redistribute the software under the terms of the CeCILL + license as circulated by CEA, CNRS and INRIA at the following URL + "http://www.cecill.info". + + As a counterpart to the access to the source code and rights to copy, + modify and redistribute granted by the license, users are provided only + with a limited warranty and the software's author, the holder of the + economic rights, and the successive licensors have only limited liability. + + In this respect, the user's attention is drawn to the risks associated + with loading, using, modifying and/or developing or reproducing the + software by the user in light of its specific status of free software, + that may mean that it is complicated to manipulate, and that also + therefore means that it is reserved for developers and experienced + professionals having in-depth computer knowledge. Users are therefore + encouraged to load and test the software's suitability as regards their + requirements in conditions enabling the security of their systems and/or + data to be ensured and, more generally, to use and operate it in the + same conditions as regards security. + The fact that you are presently reading this means that you have had + knowledge of the CeCILL license and that you accept its terms. + + ParadisEO WebSite : http://paradiseo.gforge.inria.fr + Contact: paradiseo-help@lists.gforge.inria.fr +*/ + +#ifndef _moMetropolisHastingsExplorer_h +#define _moMetropolisHastingsExplorer_h + +#include + +#include +#include +#include +#include +#include + +#include +#include + +/** + * Explorer for the Metropolis-Hasting Sampling. + * Only the symetric case is considered when Q(x,y) = Q(y,x) + * Fitness must be > 0 + * + * Class Derived passed in template parameter should define an "alpha" function + * returning a real between 0 and 1 representing the probability of accepting + * a worse solution + */ +template< class Neighbor, class Derived > +class moMetropolisHastingsExplorer : public moNeighborhoodExplorer +{ +public: + typedef typename Neighbor::EOT EOT ; + typedef moNeighborhood Neighborhood ; + + using moNeighborhoodExplorer::neighborhood; + using moNeighborhoodExplorer::eval; + using moNeighborhoodExplorer::selectedNeighbor; + + /** + * Constructor + * @param _neighborhood the neighborhood + * @param _eval the evaluation function + * @param _comp a neighbor comparator + */ + moMetropolisHastingsExplorer( + Neighborhood& _neighborhood, + moEval& _eval, + eoOptional< moSolNeighborComparator > _comp = NULL + ) + : moNeighborhoodExplorer(_neighborhood, _eval) + , defaultSolNeighborComp(NULL) + , solNeighborComparator(_comp.hasValue()? _comp.get(): *(defaultSolNeighborComp = new moSolNeighborComparator())) + { + if (!neighborhood.isRandom()) { + eo::log << eo::warnings << "moMetropolisHastingsExplorer::Warning -> the neighborhood used is not random" << std::endl; + } + } + + /** + * Destructor + */ + ~moMetropolisHastingsExplorer() { + if (defaultSolNeighborComp != NULL) + delete defaultSolNeighborComp; + } + + /** + * Init Search parameters: Nothing to do + * @param _solution the solution to explore + */ + virtual void initParam(EOT & _solution) {}; + + /** + * terminate: Nothing to do + * @param _solution the solution to explore + */ + virtual void terminate(EOT & _solution) {}; + + /** + * Explore the neighborhood of a solution + * @param _solution + */ + virtual void operator()(EOT & _solution) + { + //Test if _solution has a Neighbor + if (neighborhood.hasNeighbor(_solution)) + { + //init the first neighbor + neighborhood.init(_solution, selectedNeighbor); + + //eval the _solution moved with the neighbor and stores the result in the neighbor + eval(_solution, selectedNeighbor); + } + }; + + /** + * accept chooses whether to accept or reject the selected neighbor + * @param _solution the solution + * @return true if the selected neighbor is accepted + */ + virtual bool accept(EOT & _solution) + { + bool isMoveAccepted = false; + if (neighborhood.hasNeighbor(_solution)) { + if (solNeighborComparator(_solution, selectedNeighbor)) + // accept if the current neighbor is better than the solution + isMoveAccepted = true; + else isMoveAccepted = rng.uniform() < static_cast(this)->alpha(_solution); + } + return isMoveAccepted; + }; + +private: + + // default comparator betwenn solution and neighbor + moSolNeighborComparator* defaultSolNeighborComp; + + // comparator betwenn solution and neighbor + moSolNeighborComparator& solNeighborComparator; + +}; + + +#endif diff --git a/mo/src/explorer/moNeighborhoodExplorer.h b/mo/src/explorer/moNeighborhoodExplorer.h index 8b4113b7a..76ee12af7 100644 --- a/mo/src/explorer/moNeighborhoodExplorer.h +++ b/mo/src/explorer/moNeighborhoodExplorer.h @@ -65,15 +65,19 @@ class moNeighborhoodExplorer : public eoUF typedef typename Neighbor::EOT EOT; typedef typename EOT::Fitness Fitness ; - moNeighborhoodExplorer():neighborhood(dummyNeighborhood), eval(dummyEval), isMoved(false) {} + moNeighborhoodExplorer() + : neighborhood(dummyNeighborhood), eval(dummyEval), isMoved(false) + { } /** * Constructor with a Neighborhood and evaluation function * @param _neighborhood the neighborhood * @param _eval the evaluation function */ - moNeighborhoodExplorer(Neighborhood& _neighborhood, moEval& _eval):neighborhood(_neighborhood), eval(_eval), isMoved(false) {} - + moNeighborhoodExplorer(Neighborhood& _neighborhood, moEval& _eval) + : neighborhood(_neighborhood), eval(_eval), isMoved(false) + { } + /** * Init Search parameters * @param _solution the solution to explore diff --git a/mo/src/explorer/moSAexplorer.h b/mo/src/explorer/moSAExplorer.h similarity index 63% rename from mo/src/explorer/moSAexplorer.h rename to mo/src/explorer/moSAExplorer.h index 3d9f477ee..89ae128d0 100644 --- a/mo/src/explorer/moSAexplorer.h +++ b/mo/src/explorer/moSAExplorer.h @@ -1,8 +1,8 @@ /* - + Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010 - Sébastien Verel, Arnaud Liefooghe, Jérémie Humeau + Sébastien Verel, Arnaud Liefooghe, Jérémie Humeau, Lionel Parreaux This software is governed by the CeCILL license under French law and abiding by the rules of distribution of free software. You can use, @@ -32,15 +32,18 @@ Contact: paradiseo-help@lists.gforge.inria.fr */ -#ifndef _moSAexplorer_h -#define _moSAexplorer_h +#ifndef _moSAExplorer_h +#define _moSAExplorer_h #include -#include +//#include +#include #include #include #include +#include +#include #include @@ -51,35 +54,37 @@ * */ template< class Neighbor > -class moSAexplorer : public moNeighborhoodExplorer +class moSAExplorer : public moMetropolisHastingsExplorer< Neighbor, moSAExplorer > { public: typedef typename Neighbor::EOT EOT ; typedef moNeighborhood Neighborhood ; - + using moNeighborhoodExplorer::neighborhood; using moNeighborhoodExplorer::eval; using moNeighborhoodExplorer::selectedNeighbor; /** - * Constructor + * Constructor for the simple MH explorer * @param _neighborhood the neighborhood * @param _eval the evaluation function + * @param _cool the cooling schedule * @param _solNeighborComparator a solution vs neighbor comparator - * @param _coolingSchedule the cooling schedule */ - moSAexplorer(Neighborhood& _neighborhood, moEval& _eval, moSolNeighborComparator& _solNeighborComparator, moCoolingSchedule& _coolingSchedule) : moNeighborhoodExplorer(_neighborhood, _eval), solNeighborComparator(_solNeighborComparator), coolingSchedule(_coolingSchedule) { - isAccept = false; - - if (!neighborhood.isRandom()) { - std::cout << "moSAexplorer::Warning -> the neighborhood used is not random" << std::endl; - } - } - + moSAExplorer ( + Neighborhood& _neighborhood, + moEval& _eval, + moCoolingSchedule& _cool, + eoOptional< moSolNeighborComparator > _comp = NULL + ) + : moMetropolisHastingsExplorer< Neighbor, moSAExplorer >(_neighborhood, _eval, _comp) + , coolingSchedule(_cool) + { } + /** * Destructor */ - ~moSAexplorer() { + ~moSAExplorer() { } /** @@ -88,7 +93,7 @@ class moSAexplorer : public moNeighborhoodExplorer */ virtual void initParam(EOT & _solution) { temperature = coolingSchedule.init(_solution); - isAccept = false; + //isMoveAccepted = false; }; /** @@ -96,11 +101,11 @@ class moSAexplorer : public moNeighborhoodExplorer * @param _solution unused solution */ virtual void updateParam(EOT & _solution) { - coolingSchedule.update(temperature, this->moveApplied()); + coolingSchedule.update(temperature, this->moveApplied(), _solution); }; /** - * terminate: NOTHING TO DO + * terminate: Nothing to do * @param _solution unused solution */ virtual void terminate(EOT & _solution) {}; @@ -111,17 +116,14 @@ class moSAexplorer : public moNeighborhoodExplorer */ virtual void operator()(EOT & _solution) { //Test if _solution has a Neighbor - if (neighborhood.hasNeighbor(_solution)) { + if (neighborhood.hasNeighbor(_solution)) + { //init on the first neighbor: supposed to be random solution in the neighborhood neighborhood.init(_solution, selectedNeighbor); //eval the _solution moved with the neighbor and stock the result in the neighbor eval(_solution, selectedNeighbor); } - else { - //if _solution hasn't neighbor, - isAccept=false; - } }; /** @@ -132,51 +134,35 @@ class moSAexplorer : public moNeighborhoodExplorer virtual bool isContinue(EOT & _solution) { return coolingSchedule(temperature); }; - - /** - * acceptance criterion according to the boltzmann criterion - * @param _solution the solution - * @return true if better neighbor or rnd < exp(delta f / T) - */ - virtual bool accept(EOT & _solution) { - if (neighborhood.hasNeighbor(_solution)) { - if (solNeighborComparator(_solution, selectedNeighbor)) // accept if the current neighbor is better than the solution - isAccept = true; - else { - double alpha=0.0; - double fit1, fit2; - fit1=(double)selectedNeighbor.fitness(); - fit2=(double)_solution.fitness(); - if (fit1 < fit2) // this is a maximization - alpha = exp((fit1 - fit2) / temperature ); - else // this is a minimization - alpha = exp((fit2 - fit1) / temperature ); - isAccept = (rng.uniform() < alpha) ; - } - } - return isAccept; - }; - + /** - * Getter + * getTemperature getter function * @return the temperature */ - double getTemperature() { + double getTemperature() const { return temperature; } - + + /** + * alpha required by moMetropolisHastingsExplorer, using the Boltzman distribution e^(-delta/T) + * @param _solution the solution + * @return a real between 0 and 1 representing the probability of accepting a worse solution + */ + double alpha(EOT & _solution) { + return exp( - fabs((double) selectedNeighbor.fitness() - (double) _solution.fitness()) / temperature ); + } + + private: - // comparator betwenn solution and neighbor - moSolNeighborComparator& solNeighborComparator; - + + // The cooling schedule moCoolingSchedule& coolingSchedule; - - // temperatur of the process + + // current temperatur of the process double temperature; - - // true if the move is accepted - bool isAccept ; + }; #endif + diff --git a/mo/src/explorer/moSimpleMetropolisHastingsExplorer.h b/mo/src/explorer/moSimpleMetropolisHastingsExplorer.h new file mode 100644 index 000000000..341b4e70c --- /dev/null +++ b/mo/src/explorer/moSimpleMetropolisHastingsExplorer.h @@ -0,0 +1,129 @@ +/* + + Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010 + + Sébastien Verel, Arnaud Liefooghe, Jérémie Humeau, Lionel Parreaux + + This software is governed by the CeCILL license under French law and + abiding by the rules of distribution of free software. You can use, + modify and/ or redistribute the software under the terms of the CeCILL + license as circulated by CEA, CNRS and INRIA at the following URL + "http://www.cecill.info". + + As a counterpart to the access to the source code and rights to copy, + modify and redistribute granted by the license, users are provided only + with a limited warranty and the software's author, the holder of the + economic rights, and the successive licensors have only limited liability. + + In this respect, the user's attention is drawn to the risks associated + with loading, using, modifying and/or developing or reproducing the + software by the user in light of its specific status of free software, + that may mean that it is complicated to manipulate, and that also + therefore means that it is reserved for developers and experienced + professionals having in-depth computer knowledge. Users are therefore + encouraged to load and test the software's suitability as regards their + requirements in conditions enabling the security of their systems and/or + data to be ensured and, more generally, to use and operate it in the + same conditions as regards security. + The fact that you are presently reading this means that you have had + knowledge of the CeCILL license and that you accept its terms. + + ParadisEO WebSite : http://paradiseo.gforge.inria.fr + Contact: paradiseo-help@lists.gforge.inria.fr +*/ + +#ifndef _moSimpleMetropolisHastingsExplorer_h +#define _moSimpleMetropolisHastingsExplorer_h +/* +#include + +#include +#include +#include +#include + +#include */ +#include + + +/** + * Explorer for the Metropolis-Hasting Sampling. + * Only the symetric case is considered when Q(x,y) = Q(y,x) + * Fitness must be > 0 + */ +template< class Neighbor > +class moSimpleMetropolisHastingsExplorer +: public moMetropolisHastingsExplorer< Neighbor, moSimpleMetropolisHastingsExplorer > +{ +public: + typedef typename Neighbor::EOT EOT ; + typedef moNeighborhood Neighborhood ; + + using moNeighborhoodExplorer::selectedNeighbor; + + /** + * Constructor for the simple MH explorer + * @param _neighborhood the neighborhood + * @param _eval the evaluation function + * @param _maxSteps maximum number of currentStepNb to do + * @param _solNeighborComparator a solution vs neighbor comparator + */ + moSimpleMetropolisHastingsExplorer ( + Neighborhood& _neighborhood, + moEval& _eval, + unsigned int _maxSteps, + eoOptional< moSolNeighborComparator > _comp = NULL + ) + : moMetropolisHastingsExplorer< Neighbor, moSimpleMetropolisHastingsExplorer >(_neighborhood, _eval, _comp) + , maxSteps(_maxSteps) + { } + + /** + * initialization of currentStepNb to be done here + * @param _solution unused + */ + virtual void initParam(EOT & _solution) { + currentStepNb = 0; + //isAccept = true; + }; + + /** + * increment currentStepNb + * @param _solution unused + */ + virtual void updateParam(EOT & _solution) { + currentStepNb++; + }; + + /** + * continue if there is a neighbor and it is remainds some steps to do + * @param _solution the solution + * @return true if there is still some steps to perform + */ + virtual bool isContinue(EOT & _solution) { + return currentStepNb < maxSteps; + }; + + /** + * alpha required by moMetropolisHastingsExplorer + * @param _solution the solution + * @return a real between 0 and 1 representing the probability of accepting a worse solution + */ + double alpha(EOT & _solution) { + if (selectedNeighbor.fitness() == 0) + return selectedNeighbor.fitness() < (double) _solution.fitness() ? 1: 0; + return (double) _solution.fitness() / (double) selectedNeighbor.fitness(); + } + +private: + + // current number of steps + unsigned int currentStepNb; + + // maximum number of steps to perform + unsigned int maxSteps; + +}; + + +#endif diff --git a/mo/src/mo.h b/mo/src/mo.h index 2a56a86a5..1400a4c9d 100755 --- a/mo/src/mo.h +++ b/mo/src/mo.h @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include #include @@ -100,11 +100,14 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include @@ -116,14 +119,14 @@ #include #include #include -#include +#include #include #include #include #include #include #include -#include +#include #include #include #include @@ -162,6 +165,8 @@ #include #include #include +#include +#include #include #include @@ -207,5 +212,6 @@ #include #include #include +#include #endif diff --git a/mo/src/neighborhood/moRealNeighbor.h b/mo/src/neighborhood/moRealNeighbor.h new file mode 100644 index 000000000..e4a4a18d6 --- /dev/null +++ b/mo/src/neighborhood/moRealNeighbor.h @@ -0,0 +1,112 @@ +/* + +(c) Thales group, 2010 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +#ifndef __moRealNeighbor_h__ +#define __moRealNeighbor_h__ + +#include +#include +#include + +//! A neighbor as produced by a moRealNeighborhood +/*! + * In a real neighborhood, the move is just a translation vector, of the same type than a solution. + */ + +template +class moRealNeighbor : public moNeighbor +{ +protected: + //! The move to be applied + EOT _translation; + + edoBounder * _bounder; + + +public: + + moRealNeighbor() : _bounder( NULL ) { } + + //! Returns the solution attached to this neighbor + EOT translation() { return _translation; } + + //! Set the translation + void translation( EOT translation ) { _translation = translation; } + + + void bounder( edoBounder * bounder ) { _bounder = bounder; } + + /** + * Assignment operator + * @param _neighbor the neighbor to assign + * @return a neighbor equal to the other + */ + virtual moNeighbor& operator=(const moNeighbor& _neighbor) { + fitness( _neighbor.fitness() ); + return (*this); + } + + /*! + * Move a solution to the solution of this neighbor + * @param _solution the related solution + */ + virtual void move(EOT & _solution) + { + assert( _solution.size() == _translation.size() ); + + for( unsigned int i=0, size= _solution.size(); i& _neighbor) { + return _neighbor.translation() == _translation; + } + + /** + * Return the class Name + * @return the class name as a std::string + */ + virtual std::string className() const { + return "moRealNeighbor"; + } +}; + + +#endif // __moRealNeighbor_h__ + diff --git a/mo/src/neighborhood/moRealNeighborhood.h b/mo/src/neighborhood/moRealNeighborhood.h new file mode 100644 index 000000000..a54564868 --- /dev/null +++ b/mo/src/neighborhood/moRealNeighborhood.h @@ -0,0 +1,108 @@ +/* + +(c) Thales group, 2010 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +#ifndef __moRealNeighborhood_h__ +#define __moRealNeighborhood_h__ + +#include +#include + +template +class moRealNeighborhood : public moRndNeighborhood< Neighbor > +{ +public: + typedef typename Distrib::EOType EOT; + +protected: + Distrib & _distrib; + edoSampler & _sampler; + edoBounder & _bounder; + +public: + + moRealNeighborhood( + Distrib& distrib, + edoSampler& sampler, + edoBounder& bounder + ): _distrib(distrib), + _sampler(sampler), + _bounder(bounder) + { } + + /** + * It alway remains at least a solution in an infinite neighborhood + * @param _solution the related solution + * @return true + */ + virtual bool hasNeighbor(EOT &) + { + return true; + } + + /** + * Draw the next neighbor + * @param _solution the solution to explore + * @param _current the next neighbor + */ + virtual void next(EOT &, Neighbor & _current) + { + _current.bounder( &_bounder ); + + // Draw a translation in the distrib, using the sampler + _current.translation( _sampler( _distrib ) ); + } + + + /** + * Initialization of the neighborhood + * @param _solution the solution to explore + * @param _current the first neighbor + */ + virtual void init(EOT & _solution, Neighbor & _current) + { + // there is no difference between an init and a random draw + next( _solution, _current ); + } + /** + * There is always a solution in an infinite neighborhood + * @param _solution the solution to explore + * @return true + */ + virtual bool cont(EOT &) + { + return true; + } + + /** + * Return the class Name + * @return the class name as a std::string + */ + virtual std::string className() const { + return "moRealNeighborhood"; + } + +}; + +#endif // __moRealNeighborhood_h__ diff --git a/mo/src/sampling/moMHBestFitnessCloudSampling.h b/mo/src/sampling/moMHBestFitnessCloudSampling.h index ebba8a3b9..e9c71f35b 100644 --- a/mo/src/sampling/moMHBestFitnessCloudSampling.h +++ b/mo/src/sampling/moMHBestFitnessCloudSampling.h @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include @@ -87,7 +87,7 @@ class moMHBestFitnessCloudSampling : public moFitnessCloudSampling delete localSearch; // Metropolis-Hasting sampling - localSearch = new moMetropolisHasting(_neighborhood, _fullEval, _eval, _nbStep); + localSearch = new moMetropolisHastings(_neighborhood, _fullEval, _eval, _nbStep); // delete the checkpoint with the wrong continuator delete checkpoint; diff --git a/mo/src/sampling/moMHRndFitnessCloudSampling.h b/mo/src/sampling/moMHRndFitnessCloudSampling.h index 292d42344..2a3cca639 100644 --- a/mo/src/sampling/moMHRndFitnessCloudSampling.h +++ b/mo/src/sampling/moMHRndFitnessCloudSampling.h @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include @@ -87,7 +87,7 @@ class moMHRndFitnessCloudSampling : public moFitnessCloudSampling delete localSearch; // Metropolis-Hasting sampling - localSearch = new moMetropolisHasting(_neighborhood, _fullEval, _eval, _nbStep); + localSearch = new moMetropolisHastings(_neighborhood, _fullEval, _eval, _nbStep); // delete the checkpoint with the wrong continuator delete checkpoint; diff --git a/mo/src/sampling/moStdDevEstimator.h b/mo/src/sampling/moStdDevEstimator.h new file mode 100644 index 000000000..4daa9057b --- /dev/null +++ b/mo/src/sampling/moStdDevEstimator.h @@ -0,0 +1,131 @@ +/* + +(c) Thales group, 2010 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +#ifndef __moStdDevEstimator_h__ +#define __moStdDevEstimator_h__ + +#include +#include + +template< class EOT, class Neighbor > +class moStdDevEstimator : public eoUF +{ +public: + + /** + * General constructor for the estimator + * @param continuator a user-defined continuator + * @param neighborhood the neighborhood + * @param fullEval the full evaluation function + * @param eval neighbor's evaluation function + * @param walker a local search algorithm + */ + moStdDevEstimator ( + moContinuator& continuator, + moNeighborhood& neighborhood, + eoEvalFunc& fullEval, + + /* + The following should be read: + moEval& eval = _default_eval + (which is not possible to achieve as is in C++) + */ + const eoOptional< moEval >& eval = eoOptional< moEval >::null, + + const eoOptional< moLocalSearch >& walker = eoOptional< moLocalSearch >::null + ) + : _default_eval ( fullEval ), + _eval(eval.hasValue()? eval.get(): _default_eval), + _default_continuator( 0 ), + _continuator( _continuator ), + _checkpoint( _continuator ), + _default_walker( neighborhood, fullEval, _eval, _checkpoint ), + _walker( walker.hasValue()? walker.get(): _default_walker ) + { + _checkpoint.add( _varStat ); + } + + /** + * Simpler constructor for the estimator + * @param max_iters the number of steps the default moIterContinuator should perform + * @param neighborhood the neighborhood + * @param fullEval the full evaluation function + * @param eval neighbor's evaluation function + * @param walker a local search algorithm + */ + moStdDevEstimator ( + unsigned int max_iters, + moNeighborhood < Neighbor > & neighborhood, + eoEvalFunc& fullEval, + const eoOptional< moEval >& eval = eoOptional< moEval >::null, + const eoOptional< moLocalSearch >& walker = eoOptional< moLocalSearch >::null + ) + : _default_eval ( fullEval ), + _eval(eval.hasValue()? eval.get(): _default_eval), + _default_continuator( max_iters, false ), + _continuator( _default_continuator ), + _checkpoint( _continuator ), + _default_walker( neighborhood, fullEval, _eval, _checkpoint ), + _walker( walker.hasValue()? walker.get(): _default_walker ) + { + _checkpoint.add( _varStat ); + } + + /** + * Evaluates the estimator with the walker algorithm and returns the standard deviation + * @param solution the solution from where to start the walk + */ + double operator()( EOT & solution ) + { + _walker(solution); + return sqrt(_varStat.value()); + } + + /** + * @return the class name + */ + virtual std::string className(void) const { + return "moStdDevEstimator"; + } + +private: + + moFullEvalByCopy _default_eval; + moEval& _eval; + + moIterContinuator _default_continuator; + moContinuator & _continuator; + + moCheckpoint _checkpoint; + + moRandomWalk _default_walker; + moLocalSearch _walker; + + moFitnessVarianceStat _varStat; +}; + +#endif // __moStdDevEstimator_h__ + + diff --git a/mo/test/CMakeLists.txt b/mo/test/CMakeLists.txt index 652b66be3..898e6e22d 100644 --- a/mo/test/CMakeLists.txt +++ b/mo/test/CMakeLists.txt @@ -4,6 +4,7 @@ include_directories(${EO_SRC_DIR}/src) include_directories(${MO_SRC_DIR}/src) +include_directories(${EDO_SRC_DIR}/src) include_directories(${PROBLEMS_SRC_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) @@ -37,7 +38,7 @@ set (TEST_LIST t-moNeutralHCexplorer t-moFirstImprHCexplorer t-moRandomWalkExplorer - t-moMetropolisHastingExplorer + t-moMetropolisHastingsExplorer t-moRandomNeutralWalkExplorer t-moTSexplorer t-moSolComparator @@ -51,7 +52,7 @@ set (TEST_LIST t-moMonOpPerturb t-moRestartPerturb t-moNeighborhoodPerturb - t-moSAexplorer + t-moSAExplorer t-moSA t-moLocalSearch t-moILSexplorer @@ -64,7 +65,7 @@ set (TEST_LIST t-moILS t-moDummyLS t-moRandomSearch - t-moMetropolisHasting + t-moMetropolisHastings t-moNeutralHC t-moRandomWalk t-moRandomNeutralWalk @@ -94,7 +95,11 @@ set (TEST_LIST t-moStatistics t-moIndexedVectorTabuList # t-moRndIndexedVectorTabuList + t-moFitnessVarianceStat + t-moStdDevEstimator t-moDynSpanCoolingSchedule + t-moTriki + t-moTrikiReal ) ###################################################################################### diff --git a/mo/test/t-moCheckpoint.cpp b/mo/test/t-moCheckpoint.cpp index e080b9a7b..75ae10a6e 100644 --- a/mo/test/t-moCheckpoint.cpp +++ b/mo/test/t-moCheckpoint.cpp @@ -78,14 +78,14 @@ int main() { test1.init(s); test1(s); - assert(a==3 && b==16 && c==12 && d==49); + assert(a==3 && b==16 && c==11 && d==48); assert(stat.value()[0]); assert(stat.value()[1]); assert(!stat.value()[2]); assert(stat.value().fitness()==17); test1(s); - assert(a==4 && b==17 && c==13 && d==50); + assert(a==4 && b==17 && c==12 && d==49); assert(stat.value()[0]); assert(stat.value()[1]); assert(!stat.value()[2]); @@ -95,7 +95,7 @@ int main() { test2.init(s); test2(s); - assert(a==5 && b==18 && c==15 && d==52); + assert(a==5 && b==18 && c==13 && d==50); assert(stat.value()[0]); assert(stat.value()[1]); assert(!stat.value()[2]); @@ -110,9 +110,9 @@ int main() { assert(stat.value().fitness()==6); test1.lastCall(s); - assert(a==9 && b==22 && c==19 && d==56); + assert(a==9 && b==22 && c==17 && d==54); test2.lastCall(s); - assert(a==10 && b==23 && c==20 && d==57); + assert(a==10 && b==23 && c==18 && d==55); assert(test1.className()=="moCheckpoint"); std::cout << "[t-moCheckpoint] => OK" << std::endl; diff --git a/mo/test/t-moDynSpanCoolingSchedule.cpp b/mo/test/t-moDynSpanCoolingSchedule.cpp index 7bef4ad59..da67008ea 100755 --- a/mo/test/t-moDynSpanCoolingSchedule.cpp +++ b/mo/test/t-moDynSpanCoolingSchedule.cpp @@ -48,38 +48,38 @@ int main() { assert(temperature == 100); //temperature must not changed 2* - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 100); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 100); assert(test(temperature)); //then temperature must be /10 - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 10); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 10); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 10); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 1); std::cout << "\n"; assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); std::cout << "\n"; assert(temperature == 1); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); std::cout << "\n"; assert(temperature == 1); assert(test(temperature)); - test.update(temperature, 0); + test.update(temperature, 0, sol); assert(temperature == 0.1); assert(!test(temperature)); diff --git a/mo/test/t-moFitnessVarianceStat.cpp b/mo/test/t-moFitnessVarianceStat.cpp new file mode 100644 index 000000000..66c66a015 --- /dev/null +++ b/mo/test/t-moFitnessVarianceStat.cpp @@ -0,0 +1,67 @@ +/* + +(c) Thales group, 2010 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +//----------------------------------------------------------------------------- +// t-moFitnessVarianceStat.cpp +//----------------------------------------------------------------------------- + +#include +#include "es/eoReal.h" +#include "continuator/moFitnessVarianceStat.h" +#include "neighborhood/moRealNeighbor.h" +#include "neighborhood/moRealNeighborhood.h" + +//----------------------------------------------------------------------------- + +typedef eoReal< eoMinimizingFitness > EOT; +typedef moRealNeighbor< EOT > Neighbor; + +double objective_function(const EOT & sol) +{ + double sum = 0; + + for ( size_t i = 0; i < sol.size(); ++i ) + { + sum += sol[i] * sol[i]; + } + + return sum; +} + +int main(int ac, char** av) +{ + moFitnessVarianceStat stat; + eoEvalFuncPtr< EOT, double > eval( objective_function ); + EOT solution(2, 5); + eval(solution); + stat(solution); + solution[0] = solution[1] = 0; + solution.invalidate(); + eval(solution); + stat(solution); + std::cout << "var: " << stat.value() << std::endl; + assert(stat.value() == 625); + std::cout << "[t-moFitnessNeighborStat] => OK" << std::endl; +} diff --git a/mo/test/t-moMetropolisHasting.cpp b/mo/test/t-moMetropolisHastings.cpp similarity index 75% rename from mo/test/t-moMetropolisHasting.cpp rename to mo/test/t-moMetropolisHastings.cpp index 638c64bd8..48585780e 100644 --- a/mo/test/t-moMetropolisHasting.cpp +++ b/mo/test/t-moMetropolisHastings.cpp @@ -1,5 +1,5 @@ /* - + Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010 Sébastien Verel, Arnaud Liefooghe, Jérémie Humeau @@ -27,11 +27,15 @@ ParadisEO WebSite : http://paradiseo.gforge.inria.fr Contact: paradiseo-help@lists.gforge.inria.fr */ +//----------------------------------------------------------------------------- +// t-moMetropolisHastings.cpp +//----------------------------------------------------------------------------- + #include #include #include -#include +#include #include "moTestClass.h" #include #include @@ -40,25 +44,24 @@ Contact: paradiseo-help@lists.gforge.inria.fr int main() { - std::cout << "[t-moMetropolisHasting] => START" << std::endl; + std::cout << "[t-moMetropolisHastings] => START" << std::endl; bitNeighborhood nh(4); oneMaxEval fullEval; evalOneMax eval(4); moTrueContinuator cont; moSolNeighborComparator sncomp; - moNeighborComparator ncomp; //test du 1er constructeur - moMetropolisHasting test1(nh, fullEval, eval, 3); + moMetropolisHastings test1(nh, fullEval, eval, 3); //test du 2eme constructeur - moMetropolisHasting test2(nh, fullEval, eval, 3, cont); + moMetropolisHastings test2(nh, fullEval, eval, 3, cont); //test du 3eme constructeur - moMetropolisHasting test3(nh, fullEval, eval, 3, cont, ncomp, sncomp); + moMetropolisHastings test3(nh, fullEval, eval, 3, cont, sncomp); - std::cout << "[t-moMetropolisHasting] => OK" << std::endl; + std::cout << "[t-moMetropolisHastings] => OK" << std::endl; return EXIT_SUCCESS; } diff --git a/mo/test/t-moMetropolisHastingExplorer.cpp b/mo/test/t-moMetropolisHastingsExplorer.cpp similarity index 84% rename from mo/test/t-moMetropolisHastingExplorer.cpp rename to mo/test/t-moMetropolisHastingsExplorer.cpp index 6214465a1..993106460 100644 --- a/mo/test/t-moMetropolisHastingExplorer.cpp +++ b/mo/test/t-moMetropolisHastingsExplorer.cpp @@ -1,5 +1,5 @@ /* - + Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010 Sébastien Verel, Arnaud Liefooghe, Jérémie Humeau @@ -27,7 +27,11 @@ ParadisEO WebSite : http://paradiseo.gforge.inria.fr Contact: paradiseo-help@lists.gforge.inria.fr */ -#include +//----------------------------------------------------------------------------- +// t-moSimpleMetropolisHastingsExplorer.cpp +//----------------------------------------------------------------------------- + +#include #include "moTestClass.h" #include @@ -36,7 +40,7 @@ Contact: paradiseo-help@lists.gforge.inria.fr int main() { - std::cout << "[t-moMetropolisHastingExplorer] => START" << std::endl; + std::cout << "[t-moMetropolisHastingsExplorer] => START" << std::endl; //Instanciation eoBit sol(4, true); @@ -45,8 +49,8 @@ int main() { evalOneMax eval(4); moNeighborComparator ncomp; moSolNeighborComparator sncomp; - - moMetropolisHastingExplorer test(nh, eval, ncomp, sncomp, 3); + + moSimpleMetropolisHastingsExplorer test(nh, eval, 3, sncomp); //test de l'acceptation d'un voisin améliorant test.initParam(sol); @@ -90,7 +94,7 @@ int main() { test(sol); assert(!test.accept(sol)); - std::cout << "[t-moMetropolisHastingExplorer] => OK" << std::endl; + std::cout << "[t-moMetropolisHastingsExplorer] => OK" << std::endl; return EXIT_SUCCESS; } diff --git a/mo/test/t-moSA.cpp b/mo/test/t-moSA.cpp index b1cdfeb67..3c67865cb 100644 --- a/mo/test/t-moSA.cpp +++ b/mo/test/t-moSA.cpp @@ -51,12 +51,12 @@ int main() { //test second constructor moSimpleCoolingSchedule cool(10, 0.9, 100, 0.01); - moSA test2(nh, fullEval, eval, cool); + moSA test2(nh, fullEval, cool, eval); //test third constructor moTrueContinuator cont; moSolNeighborComparator comp; - moSA test3(nh, fullEval, eval, cool, comp, cont); + moSA test3(nh, fullEval, cool, eval, cont, comp); std::cout << "[t-moSA] => OK" << std::endl; diff --git a/mo/test/t-moSAexplorer.cpp b/mo/test/t-moSAExplorer.cpp similarity index 89% rename from mo/test/t-moSAexplorer.cpp rename to mo/test/t-moSAExplorer.cpp index 4c619ff88..873dbf080 100644 --- a/mo/test/t-moSAexplorer.cpp +++ b/mo/test/t-moSAExplorer.cpp @@ -1,5 +1,5 @@ /* - + Copyright (C) DOLPHIN Project-Team, INRIA Lille - Nord Europe, 2006-2010 Sébastien Verel, Arnaud Liefooghe, Jérémie Humeau @@ -32,12 +32,12 @@ Contact: paradiseo-help@lists.gforge.inria.fr #include #include "moTestClass.h" -#include +#include #include int main() { - std::cout << "[t-moSAexplorer] => START" << std::endl; + std::cout << "[t-moSAExplorer] => START" << std::endl; eoBit sol(4, true); sol.fitness(4); @@ -47,8 +47,8 @@ int main() { moSolNeighborComparator sncomp; moSimpleCoolingSchedule cool(10,0.1,2,0.1); - moSAexplorer test1(emptyNH, eval, sncomp, cool); - moSAexplorer test2(nh, eval, sncomp, cool); + moSAExplorer test1(emptyNH, eval, cool, sncomp); + moSAExplorer test2(nh, eval, cool, sncomp); //test d'un voisinage vide test1.initParam(sol); @@ -80,7 +80,7 @@ int main() { - std::cout << "[t-moSAexplorer] => OK" << std::endl; + std::cout << "[t-moSAExplorer] => OK" << std::endl; return EXIT_SUCCESS; } diff --git a/mo/test/t-moSimpleCoolingSchedule.cpp b/mo/test/t-moSimpleCoolingSchedule.cpp index b2f8cca17..dc78c6870 100644 --- a/mo/test/t-moSimpleCoolingSchedule.cpp +++ b/mo/test/t-moSimpleCoolingSchedule.cpp @@ -48,38 +48,38 @@ int main() { assert(temperature==100); //temperature must not changed 2* - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==100); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==100); assert(test(temperature)); //then temperature must be /10 - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==10); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==10); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==10); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature == 1); std::cout<< "\n"; assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); std::cout<< "\n"; assert(temperature==1); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); std::cout<< "\n"; assert(temperature==1); assert(test(temperature)); - test.update(temperature,0); + test.update(temperature,0,sol); assert(temperature==0.1); assert(!test(temperature)); diff --git a/mo/test/t-moStdDevEstimator.cpp b/mo/test/t-moStdDevEstimator.cpp new file mode 100644 index 000000000..9cfbe0930 --- /dev/null +++ b/mo/test/t-moStdDevEstimator.cpp @@ -0,0 +1,86 @@ +/* + +(c) Thales group, 2010 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +//----------------------------------------------------------------------------- +// t-moStdDevEstimator.cpp +//----------------------------------------------------------------------------- + +#include +#include "es/eoReal.h" +#include "neighborhood/moRealNeighbor.h" + +//Representation and initializer +#include +//#include +#include + +// fitness function +#include + +//Neighbors and Neighborhoods +#include +#include + +//Sampling +#include + + +//----------------------------------------------------------------------------- +// Define types of the representation solution, different neighbors and neighborhoods +//----------------------------------------------------------------------------- +typedef eoInt Queen; //Permutation (Queen's problem representation) + +typedef moShiftNeighbor shiftNeighbor; //shift Neighbor +typedef moRndWithReplNeighborhood rndShiftNeighborhood; //rnd shift Neighborhood (Indexed) + +//----------------------------------------------------------------------------- + +typedef eoReal< eoMinimizingFitness > EOT; +typedef moRealNeighbor< EOT > Neighbor; + +int main(int ac, char** av) +{ + unsigned vecSize = 8; + + queenEval fullEval; + + eoInitPermutation init(vecSize); + + rndShiftNeighborhood rndShiftNH((vecSize-1) * (vecSize-1)); + + Queen solution; + + init(solution); + + fullEval(solution); + + moStdDevEstimator initTemp (500, rndShiftNH, fullEval); + + double temp = initTemp(solution); + + std::cout << "temp: " << temp << std::endl; + + assert(temp >= 0); +} diff --git a/mo/test/t-moTriki.cpp b/mo/test/t-moTriki.cpp new file mode 100644 index 000000000..14f4b0198 --- /dev/null +++ b/mo/test/t-moTriki.cpp @@ -0,0 +1,164 @@ +//============================================================================ +// Name : Trikitest.cpp +// Author : +// Version : +// Copyright : Your copyright notice +// Description : Hello World in C++, Ansi-style +//============================================================================ + +// FIXME proper header + + +//#define HAVE_GNUPLOT + +#include +using namespace std; + +#include +#include + +//Representation and initializer +#include +#include +#include +#include + +/* +// fitness function +#include +#include +#include + +//Neighbors and Neighborhoods +#include +#include + +//Algorithm and its components +#include +#include + +//comparator +#include + +//continuators +#include +#include +#include +#include +#include +*/ + +//----------------------------------------------------------------------------- +// Define types of the representation solution, different neighbors and neighborhoods +//----------------------------------------------------------------------------- +typedef eoInt Queen; //Permutation (Queen's problem representation) + +typedef moShiftNeighbor ShiftNeighbor; //shift Neighbor +typedef moRndWithReplNeighborhood rndShiftNeighborhood; //rnd shift Neighborhood (Indexed) + + + + +int main() { + //cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! + //return 0; + + unsigned vecSize = 8; + + + queenEval fullEval; + + + /* ========================================================= + * + * Initilization of the solution + * + * ========================================================= */ + + eoInitPermutation init(vecSize); + + /* ========================================================= + * + * evaluation of a neighbor solution + * + * ========================================================= */ + + moFullEvalByCopy shiftEval(fullEval); /// by default + + /* ========================================================= + * + * the neighborhood of a solution + * + * ========================================================= */ + + rndShiftNeighborhood rndShiftNH((vecSize-1) * (vecSize-1)); + + /* ========================================================= + * + * the cooling schedule of the process + * + * ========================================================= */ + + /* ========================================================= + * + * the local search algorithm + * + * ========================================================= */ + + /* ========================================================= + * + * execute the local search from random solution + * + * ========================================================= */ + + Queen solution; + + init(solution); + + fullEval(solution); + + //moStdDevEstimator stdDevEst (500, rndShiftNH, fullEval); + double stdDevEst = moStdDevEstimator(500, rndShiftNH, fullEval)(solution); + + moTrueContinuator continuator; + moCheckpoint checkpoint(continuator); + moFitnessStat fitStat; + checkpoint.add(fitStat); + eoFileMonitor monitor("triki.out", ""); + eoGnuplot1DMonitor monitor2("trikignu.out", true); + moCounterMonitorSaver countMon(100, monitor); + checkpoint.add(countMon); + moCounterMonitorSaver gnuMon (10, monitor2); + checkpoint.add(gnuMon); + monitor.add(fitStat); + monitor2.add(fitStat); + //#ifdef HAVE_GNUPLOT + + + //moTrikiCoolingSchedule coolingSchedule(rndShiftNH, shiftEval, initTemp(solution1)); + //moTrikiCoolingSchedule coolingSchedule(initTemp(solution)); + moTrikiCoolingSchedule coolingSchedule(stdDevEst, stdDevEst); + moSA localSearch(rndShiftNH, fullEval, coolingSchedule, shiftEval, checkpoint); + //moSA localSearch(rndShiftNH, fullEval, shiftEval); + //moSA localSearch(rndShiftNH, fullEval, coolingSchedule); + + + std::cout << "#########################################" << std::endl; + std::cout << "initial solution: " << solution << std::endl ; + + localSearch(solution); + + std::cout << "final solution: " << solution << std::endl ; + std::cout << "#########################################" << std::endl; + + + +} + + + + + + + + diff --git a/mo/test/t-moTrikiReal.cpp b/mo/test/t-moTrikiReal.cpp new file mode 100644 index 000000000..a158b3250 --- /dev/null +++ b/mo/test/t-moTrikiReal.cpp @@ -0,0 +1,168 @@ +/* + +(c) Thales group, 2010 + + 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; + version 2 of the License. + + 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: http://eodev.sourceforge.net + +Authors: +Lionel Parreaux + +*/ + +#include +#include +#include +#include + +#include + +#include "neighborhood/moRealNeighbor.h" +#include "neighborhood/moRealNeighborhood.h" + +#include "sampling/moStdDevEstimator.h" + +#include "coolingSchedule/moTrikiCoolingSchedule.h" + + +typedef eoReal< eoMinimizingFitness > EOT; +typedef moRealNeighbor< EOT > Neighbor; + +double objective_function(const EOT & sol) +{ + double sum = 0; + + for ( size_t i = 0; i < sol.size(); ++i ) + { + sum += sol[i] * sol[i]; + } + + return sum; +} + +int main( int ac, char** av ) +{ + eoParser parser( ac, av ); + + eoState state; + + eoEvalFuncPtr< EOT, double > eval( objective_function ); + moFullEvalByCopy< Neighbor > neval( eval ); + + int dimSize = 15; + + //------------------------------------------------------- + // Parameters + //------------------------------------------------------- + + std::string section( "Temperature initialization paramaters" ); + + unsigned int dimension_size = parser.getORcreateParam( (unsigned int)dimSize, "dimension-size", "Dimension size", 'd', section ).value(); + double jump_bound = parser.getORcreateParam( (double)1, "jump-bound", "Bound of jump", '\0', section ).value(); + unsigned int maxiter = parser.getORcreateParam( (unsigned int)10, "max-iter", "Maximum number of iterations", '\0', section ).value(); + + //------------------------------------------------------- + + + //------------------------------------------------------- + // Instanciate needed classes + //------------------------------------------------------- + + edoUniform< EOT > distrib( EOT(dimension_size, -1 * jump_bound), EOT(dimension_size, 1 * jump_bound) ); + + edoBounder< EOT > bounder_search( EOT(dimension_size, -10), EOT(dimension_size, 10) ); + + edoSamplerUniform< EOT > sampler( bounder_search ); + + moRealNeighborhood< edoUniform< EOT >, Neighbor > neighborhood( distrib, sampler, bounder_search ); + + moStdDevEstimator< EOT, Neighbor > init( maxiter, neighborhood, eval ); + + //------------------------------------------------------- + + + + + //------------------------------------------------------- + // Help + Verbose routines + //------------------------------------------------------- + + if (parser.userNeedsHelp()) + { + parser.printHelp(std::cout); + exit(1); + } + + make_help(parser); + + //------------------------------------------------------- + + + EOT solution(dimSize, 5); + + std::cout << "init temp: " + << init( solution ) + << std::endl; + + + + + moTrueContinuator continuator; + moCheckpoint checkpoint(continuator); + + + moFitnessStat fitStat; + checkpoint.add(fitStat); + eoFileMonitor monitor("triki.out", ""); + //eoGnuplot1DMonitor monitor2("trikignu.out", true); + moCounterMonitorSaver countMon(100, monitor); + checkpoint.add(countMon); + //moCounterMonitorSaver gnuMon (1, monitor2); + //checkpoint.add(gnuMon); + monitor.add(fitStat); + //monitor2.add(fitStat); + + + double stdDevEst = init( solution ); + + moTrikiCoolingSchedule coolingSchedule ( + stdDevEst, + stdDevEst, + //50, + 150,//200, //150, + //100 + 250//350 // 250 + ); + //moSA localSearch(neighborhood, eval, neval, coolingSchedule, checkpoint); + //moSA localSearch(neighborhood, eval, neval); + //moSA localSearch(neighborhood, eval, coolingSchedule, neval, checkpoint); + //moSA localSearch(neighborhood, eval, coolingSchedule); + moSA localSearch(neighborhood, eval, coolingSchedule, neval, checkpoint); + + std::cout << "#########################################" << std::endl; + std::cout << "initial solution1: " << solution << std::endl ; + + localSearch(solution); + + std::cout << "final solution1: " << solution << std::endl ; + std::cout << "#########################################" << std::endl; + + + return 0; +} + + + diff --git a/moeo/src/algo/moeoIBEA.h b/moeo/src/algo/moeoIBEA.h index b0c1d0207..b8170a08e 100644 --- a/moeo/src/algo/moeoIBEA.h +++ b/moeo/src/algo/moeoIBEA.h @@ -80,7 +80,20 @@ class moeoIBEA : public moeoEA < MOEOT > * @param _kappa scaling factor kappa */ moeoIBEA (unsigned int _maxGen, eoEvalFunc < MOEOT > & _eval, eoQuadOp < MOEOT > & _crossover, double _pCross, eoMonOp < MOEOT > & _mutation, double _pMut, moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double > & _metric, const double _kappa=0.05) : - defaultGenContinuator(_maxGen), continuator(defaultGenContinuator), eval(_eval), defaultPopEval(_eval), popEval(defaultPopEval), select (2), selectMany(select,0.0), selectTransform(defaultSelect, defaultTransform), defaultSGAGenOp(_crossover, _pCross, _mutation, _pMut), genBreed (select, defaultSGAGenOp), breed (genBreed), fitnessAssignment(_metric, _kappa), replace (fitnessAssignment, diversityAssignment) + defaultGenContinuator(_maxGen), + continuator(defaultGenContinuator), + eval(_eval), + defaultPopEval(_eval), + popEval(defaultPopEval), + select (2), + selectMany(select,0.0), + selectTransform(defaultSelect, defaultTransform), + defaultSGAGenOp(_crossover, _pCross, _mutation, _pMut), + genBreed (select, defaultSGAGenOp), + breed (genBreed), + default_fitnessAssignment( new moeoExpBinaryIndicatorBasedFitnessAssignment(_metric, _kappa) ), + fitnessAssignment(*default_fitnessAssignment), + replace(fitnessAssignment, diversityAssignment) {} @@ -94,7 +107,7 @@ class moeoIBEA : public moeoEA < MOEOT > */ moeoIBEA (eoContinue < MOEOT > & _continuator, eoEvalFunc < MOEOT > & _eval, eoGenOp < MOEOT > & _op, moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double > & _metric, const double _kappa=0.05) : defaultGenContinuator(0), continuator(_continuator), eval(_eval), defaultPopEval(_eval), popEval(defaultPopEval), select(2), - selectMany(select,0.0), selectTransform(defaultSelect, defaultTransform), defaultSGAGenOp(defaultQuadOp, 1.0, defaultMonOp, 1.0), genBreed(select, _op), breed(genBreed), fitnessAssignment(_metric, _kappa), replace (fitnessAssignment, diversityAssignment) + selectMany(select,0.0), selectTransform(defaultSelect, defaultTransform), defaultSGAGenOp(defaultQuadOp, 1.0, defaultMonOp, 1.0), genBreed(select, _op), breed(genBreed), default_fitnessAssignment( new moeoExpBinaryIndicatorBasedFitnessAssignment(_metric, _kappa)), fitnessAssignment(*default_fitnessAssignment), replace (fitnessAssignment, diversityAssignment) {} @@ -108,7 +121,7 @@ class moeoIBEA : public moeoEA < MOEOT > */ moeoIBEA (eoContinue < MOEOT > & _continuator, eoPopEvalFunc < MOEOT > & _popEval, eoGenOp < MOEOT > & _op, moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double > & _metric, const double _kappa=0.05) : defaultGenContinuator(0), continuator(_continuator), eval(defaultEval), defaultPopEval(eval), popEval(_popEval), select(2), - selectMany(select,0.0), selectTransform(defaultSelect, defaultTransform), defaultSGAGenOp(defaultQuadOp, 1.0, defaultMonOp, 1.0), genBreed(select, _op), breed(genBreed), fitnessAssignment(_metric, _kappa), replace (fitnessAssignment, diversityAssignment) + selectMany(select,0.0), selectTransform(defaultSelect, defaultTransform), defaultSGAGenOp(defaultQuadOp, 1.0, defaultMonOp, 1.0), genBreed(select, _op), breed(genBreed), default_fitnessAssignment( new moeoExpBinaryIndicatorBasedFitnessAssignment(_metric, _kappa)), fitnessAssignment(*default_fitnessAssignment), replace (fitnessAssignment, diversityAssignment) {} @@ -122,7 +135,7 @@ class moeoIBEA : public moeoEA < MOEOT > */ moeoIBEA (eoContinue < MOEOT > & _continuator, eoEvalFunc < MOEOT > & _eval, eoTransform < MOEOT > & _transform, moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double > & _metric, const double _kappa=0.05) : defaultGenContinuator(0), continuator(_continuator), eval(_eval), defaultPopEval(_eval), popEval(defaultPopEval), - select(2), selectMany(select, 1.0), selectTransform(selectMany, _transform), defaultSGAGenOp(defaultQuadOp, 0.0, defaultMonOp, 0.0), genBreed(select, defaultSGAGenOp), breed(selectTransform), fitnessAssignment(_metric, _kappa), replace(fitnessAssignment, diversityAssignment) + select(2), selectMany(select, 1.0), selectTransform(selectMany, _transform), defaultSGAGenOp(defaultQuadOp, 0.0, defaultMonOp, 0.0), genBreed(select, defaultSGAGenOp), breed(selectTransform), default_fitnessAssignment( new moeoExpBinaryIndicatorBasedFitnessAssignment(_metric, _kappa)), fitnessAssignment(*default_fitnessAssignment), replace(fitnessAssignment, diversityAssignment) {} @@ -136,15 +149,48 @@ class moeoIBEA : public moeoEA < MOEOT > */ moeoIBEA (eoContinue < MOEOT > & _continuator, eoPopEvalFunc < MOEOT > & _popEval, eoTransform < MOEOT > & _transform, moeoNormalizedSolutionVsSolutionBinaryMetric < ObjectiveVector, double > & _metric, const double _kappa=0.05) : defaultGenContinuator(0), continuator(_continuator), eval(defaultEval), defaultPopEval(eval), popEval(_popEval), - select(2), selectMany(select, 1.0), selectTransform(selectMany, _transform), defaultSGAGenOp(defaultQuadOp, 0.0, defaultMonOp, 0.0), genBreed(select, defaultSGAGenOp), breed(selectTransform), fitnessAssignment(_metric, _kappa), replace(fitnessAssignment, diversityAssignment) + select(2), selectMany(select, 1.0), selectTransform(selectMany, _transform), defaultSGAGenOp(defaultQuadOp, 0.0, defaultMonOp, 0.0), genBreed(select, defaultSGAGenOp), breed(selectTransform), default_fitnessAssignment( new moeoExpBinaryIndicatorBasedFitnessAssignment(_metric, _kappa)), fitnessAssignment(*default_fitnessAssignment), replace(fitnessAssignment, diversityAssignment) {} + /** + * Ctor with a eoContinue, a eoPopEval, a eoGenOp and an explicit fitnessAssignment + * @param _continuator stopping criteria + * @param _popEval population evaluation function + * @param _op variation operators + * @param _fitnessAssignment fitness assignment + */ + moeoIBEA (eoContinue < MOEOT > & _continuator, eoPopEvalFunc < MOEOT > & _popEval, eoGenOp < MOEOT > & _op, moeoBinaryIndicatorBasedFitnessAssignment < MOEOT >& _fitnessAssignment) : + defaultGenContinuator(0), continuator(_continuator), eval(defaultEval), defaultPopEval(eval), popEval(_popEval), select(2), + selectMany(select,0.0), selectTransform(defaultSelect, defaultTransform), defaultSGAGenOp(defaultQuadOp, 1.0, defaultMonOp, 1.0), genBreed(select, _op), breed(genBreed), default_fitnessAssignment(NULL), fitnessAssignment(_fitnessAssignment), replace(fitnessAssignment, diversityAssignment) + {} + + + /** + * Ctor with a eoContinue, a eoGenOp and an explicit fitnessAssignment + * @param _continuator stopping criteria + * @param _eval evaluation function + * @param _op variation operators + * @param _fitnessAssignment fitness assignment + */ + moeoIBEA (eoContinue < MOEOT > & _continuator, eoEvalFunc < MOEOT > & _eval, eoGenOp < MOEOT > & _op, moeoBinaryIndicatorBasedFitnessAssignment < MOEOT >& _fitnessAssignment) : + defaultGenContinuator(0), continuator(_continuator), eval(_eval), defaultPopEval(_eval), popEval(defaultPopEval), select(2), + selectMany(select,0.0), selectTransform(defaultSelect, defaultTransform), defaultSGAGenOp(defaultQuadOp, 1.0, defaultMonOp, 1.0), genBreed(select, _op), breed(genBreed), default_fitnessAssignment(NULL), fitnessAssignment(_fitnessAssignment), replace(fitnessAssignment, diversityAssignment) + {} + + + ~moeoIBEA() + { + if( default_fitnessAssignment != NULL ) { + delete default_fitnessAssignment; + } + } + /** * Apply the algorithm to the population _pop until the stopping criteria is satified. * @param _pop the population */ - virtual void operator () (eoPop < MOEOT > &_pop) + virtual void operator() (eoPop < MOEOT > &_pop) { eoPop < MOEOT > offspring, empty_pop; popEval (empty_pop, _pop); // a first eval of _pop @@ -214,7 +260,8 @@ class moeoIBEA : public moeoEA < MOEOT > /** breeder */ eoBreed < MOEOT > & breed; /** fitness assignment used in IBEA */ - moeoExpBinaryIndicatorBasedFitnessAssignment < MOEOT > fitnessAssignment; + moeoExpBinaryIndicatorBasedFitnessAssignment < MOEOT >* default_fitnessAssignment; + moeoBinaryIndicatorBasedFitnessAssignment < MOEOT >& fitnessAssignment; /** dummy diversity assignment */ moeoDummyDiversityAssignment < MOEOT > diversityAssignment; /** environmental replacement */ diff --git a/moeo/src/continue/moeoDualHypContinue.h b/moeo/src/continue/moeoDualHypContinue.h new file mode 100644 index 000000000..99c33d45f --- /dev/null +++ b/moeo/src/continue/moeoDualHypContinue.h @@ -0,0 +1,121 @@ +/* + +(c) 2013 Thales group + + 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; version 2 + of the License. + + 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: http://eodev.sourceforge.net + +Authors: + Johann Dréo + +*/ + +#ifndef _moeoDualHypContinue_h +#define _moeoDualHypContinue_h + +#include + +/** + Continues until the (feasible or unfeasible) given Pareto set is reached. + + + @ingroup Continuators + */ +template< class MOEOT, class MetricT = moeoDualHyperVolumeDifferenceMetric > +class moeoDualHypContinue: public moeoHypContinue +{ +protected: + bool is_feasible; + + using moeoHypContinue::arch; + using moeoHypContinue::OptimSet; + + using moeoHypContinue::pareto; + using moeoHypContinue::is_null_hypervolume; + +public: + typedef typename MOEOT::ObjectiveVector ObjectiveVector; + typedef typename ObjectiveVector::Type AtomType; + + /** A continuator that stops once a given Pareto front has been reached + * + * You should specify the feasibility of the targeted front. + * NOTE: the MOEOT::ObjectiveVector is supposed to implement the moeoDualRealObjectiveVector interface. + * + */ + moeoDualHypContinue( const std::vector & _OptimVec, bool _is_feasible, moeoArchive < MOEOT > & _archive, bool _normalize=true, double _rho=1.1 ) + : moeoHypContinue( _OptimVec, _archive, _normalize, _rho ), + is_feasible(_is_feasible) + { + assert( _OptimVec.size() > 0); + vectorToParetoSet(_OptimVec); + } + + /** A continuator that stops once a given Pareto front has been reached + * + * You should specify the feasibility of the targeted front. + * NOTE: the MOEOT::ObjectiveVector is supposed to implement the moeoDualRealObjectiveVector interface. + * + */ + moeoDualHypContinue( const std::vector & _OptimVec, bool _is_feasible, moeoArchive < MOEOT > & _archive, bool _normalize=true, ObjectiveVector& _ref_point=NULL ) + : moeoHypContinue( _OptimVec, _archive, _normalize, _ref_point ), + is_feasible(_is_feasible) + { + assert( _OptimVec.size() > 0); + vectorToParetoSet(_OptimVec); + } + + + /** Returns false when a ParetoSet is reached. */ + virtual bool operator() ( const eoPop& /*_pop*/ ) + { + std::vector bestCurrentParetoSet = pareto( arch ); + +#ifndef NDEBUG + assert( bestCurrentParetoSet.size() > 0 ); + for( unsigned int i=1; i & _OptimVec) + { + unsigned dim = (unsigned)(_OptimVec.size()/ObjectiveVector::Traits::nObjectives()); + OptimSet.resize(dim); + + unsigned k=0; + for(size_t i=0; i < dim; i++) { + for (size_t j=0; j < ObjectiveVector::Traits::nObjectives(); j++) { + // Use the feasibility declaration of an eoDualFitness + OptimSet[i][j] = AtomType(_OptimVec[k++], is_feasible); + } + } + } +}; + +#endif diff --git a/moeo/src/continue/moeoHypContinue.h b/moeo/src/continue/moeoHypContinue.h index 4e656bf69..bbc1a799b 100644 --- a/moeo/src/continue/moeoHypContinue.h +++ b/moeo/src/continue/moeoHypContinue.h @@ -36,7 +36,6 @@ //----------------------------------------------------------------------------- - #ifndef _moeoHypContinue_h #define _moeoHypContinue_h @@ -46,40 +45,70 @@ #include /** - Continues until the optimum ParetoSet level is reached. + Continues until the given ParetoSet level is reached. @ingroup Continuators */ -template< class MOEOT> +template< class MOEOT, class MetricT = moeoHyperVolumeDifferenceMetric > class moeoHypContinue: public eoContinue { public: typedef typename MOEOT::ObjectiveVector ObjectiveVector; + typedef typename ObjectiveVector::Type AtomType; /// Ctor - moeoHypContinue( const std::vector & _OptimVec, moeoArchive < MOEOT > & _archive, bool _normalize=true, double _rho=1.1) - : eoContinue(), arch(_archive), metric(_normalize,_rho) + moeoHypContinue( const std::vector & _OptimVec, moeoArchive < MOEOT > & _archive, bool _normalize=true, double _rho=1.1) + : eoContinue(), arch(_archive), default_metric(new MetricT(_normalize,_rho)), metric(*default_metric) + { + vectorToParetoSet(_OptimVec); + } + + moeoHypContinue( const std::vector & _OptimVec, moeoArchive < MOEOT > & _archive, bool _normalize=true, ObjectiveVector& _ref_point=NULL) + : eoContinue(), arch(_archive), default_metric(new MetricT(_normalize,_ref_point)), metric(*default_metric) { vectorToParetoSet(_OptimVec); } - moeoHypContinue( const std::vector & _OptimVec, moeoArchive < MOEOT > & _archive, bool _normalize=true, ObjectiveVector& _ref_point=NULL) - : eoContinue (), arch(_archive), metric(_normalize,_ref_point) + moeoHypContinue( MetricT& _metric, const std::vector & _OptimVec, moeoArchive < MOEOT > & _archive ) + : eoContinue(), arch(_archive), default_metric(NULL), metric(_metric) { vectorToParetoSet(_OptimVec); } + ~moeoHypContinue() + { + if( default_metric != NULL ) { + delete default_metric; + } + } + /** Returns false when a ParetoSet is reached. */ - virtual bool operator() ( const eoPop& _pop ) + virtual bool operator() ( const eoPop& /*_pop*/ ) + { + std::vector bestCurrentParetoSet = pareto( arch ); + + return is_null_hypervolume( bestCurrentParetoSet ); + } + + virtual std::string className(void) const { return "moeoHypContinue"; } + +protected: + + std::vector pareto( moeoArchive & _archive ) { std::vector < ObjectiveVector > bestCurrentParetoSet; - for (size_t i=0; i& bestCurrentParetoSet ) + { + double hypervolume= metric( bestCurrentParetoSet, OptimSet ); if (hypervolume==0) { eo::log << eo::logging << "STOP in moeoHypContinue: Best ParetoSet has been reached " @@ -90,7 +119,7 @@ class moeoHypContinue: public eoContinue } /** Translate a vector given as param to the ParetoSet that should be reached. */ - void vectorToParetoSet(const std::vector & _OptimVec) + virtual void vectorToParetoSet(const std::vector & _OptimVec) { unsigned dim = (unsigned)(_OptimVec.size()/ObjectiveVector::Traits::nObjectives()); OptimSet.resize(dim); @@ -103,12 +132,12 @@ class moeoHypContinue: public eoContinue } } - virtual std::string className(void) const { return "moeoHypContinue"; } - -private: +protected: moeoArchive & arch; - moeoHyperVolumeDifferenceMetric metric; + MetricT* default_metric; + MetricT& metric; std::vector OptimSet; }; + #endif diff --git a/moeo/src/core/moeoDualRealObjectiveVector.h b/moeo/src/core/moeoDualRealObjectiveVector.h new file mode 100644 index 000000000..1ed62a8ff --- /dev/null +++ b/moeo/src/core/moeoDualRealObjectiveVector.h @@ -0,0 +1,151 @@ +/* + +(c) 2010 Thales group + + 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; version 2 + of the License. + + 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: http://eodev.sourceforge.net + +Authors: + Johann Dréo + +*/ + +#ifndef _DUALREALOBJECTIVEVECTOR_H_ +#define _DUALREALOBJECTIVEVECTOR_H_ + +#include +#include + +#include + +#include +#include +#include + +template < class ObjectiveVectorTraits, class T = eoMaximizingDualFitness /* can be an eoMinimizingDualFitness */> +class moeoDualRealObjectiveVector : public moeoScalarObjectiveVector +{ + protected: + bool _is_feasible; + + public: + + using moeoScalarObjectiveVector < ObjectiveVectorTraits, T >::size; + using moeoScalarObjectiveVector < ObjectiveVectorTraits, T >::operator[]; + + moeoDualRealObjectiveVector(double value=0.0, bool feasible = false) + : moeoScalarObjectiveVector + ( T(value, feasible) ) {} + + bool is_feasible() const + { +#ifndef NDEBUG + // if the feasibility is correctly assigned, + // every scalar's feasibility should be equal to the objective vector + for( typename moeoDualRealObjectiveVector::const_iterator it = this->begin(), end = this->end(); it != end; ++it ) { + assert( it->is_feasible() == _is_feasible ); + } +#endif + return _is_feasible; + } + + //! One should ensure that feasabilities of scalars are all the same + void is_feasible( bool value ) + { +#ifndef NDEBUG + for( typename moeoDualRealObjectiveVector::const_iterator it = this->begin(), end = this->end(); it != end; ++it ) { + assert( it->is_feasible() == value ); + } +#endif + _is_feasible = value; + } + + bool dominates(const moeoRealObjectiveVector < ObjectiveVectorTraits > & other) const + { + // am I better than the other ? + + // if I'm feasible and the other is not + if( this->is_feasible() && !other.is_feasible() ) { + // no, the other has a better objective + return true; + + } else if( !this->is_feasible() && other.is_feasible() ) { + // yes, a feasible objective is always better than an unfeasible one + return false; + + } else { + // the two objective are of the same type + // lets rely on the comparator + moeoParetoObjectiveVectorComparator< moeoDualRealObjectiveVector > comparator; + return comparator(other, *this); + } + } + + //! Use when maximizing an + bool operator<(const moeoDualRealObjectiveVector < ObjectiveVectorTraits > & other) const + { + // am I better than the other ? + + // if I'm feasible and the other is not + if( this->is_feasible() && !other.is_feasible() ) { + // no, the other has a better objective + return true; + + } else if( !this->is_feasible() && other.is_feasible() ) { + // yes, a feasible objective is always better than an unfeasible one + return false; + + } else { + moeoObjectiveObjectiveVectorComparator < moeoDualRealObjectiveVector < ObjectiveVectorTraits > > cmp; + return cmp(*this, other); + } + } +}; + + + +/** + * Output for a moeoDualRealObjectiveVector object + * @param _os output stream + * @param _objectiveVector the objective vector to write + */ +template +std::ostream & operator<<( std::ostream & _os, const moeoDualRealObjectiveVector & _objectiveVector ) +{ + for( unsigned int i=0; i<_objectiveVector.size()-1; i++ ) { + _os << _objectiveVector[i] << " "; + } + _os << _objectiveVector[_objectiveVector.size()-1]; + return _os; +} + +/** + * Input for a moeoDualRealObjectiveVector object + * @param _is input stream + * @param _objectiveVector the objective vector to read + */ +template +std::istream & operator>>( std::istream & _is, moeoDualRealObjectiveVector & _objectiveVector ) +{ + _objectiveVector = moeoDualRealObjectiveVector (); + for( unsigned int i=0; i<_objectiveVector.size(); i++ ) { + _is >> _objectiveVector[i]; + } + return _is; +} + + +#endif /*_DUALREALOBJECTIVEVECTOR_H_*/ diff --git a/moeo/src/core/moeoScalarObjectiveVector.h b/moeo/src/core/moeoScalarObjectiveVector.h new file mode 100644 index 000000000..9d1183ad7 --- /dev/null +++ b/moeo/src/core/moeoScalarObjectiveVector.h @@ -0,0 +1,179 @@ +/* + +(c) 2010 Thales group + + 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; version 2 + of the License. + + 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: http://eodev.sourceforge.net + +Authors: + Johann Dréo + +*/ + + +#ifndef MOEOSCALAROBJECTIVEVECTOR_H_ +#define MOEOSCALAROBJECTIVEVECTOR_H_ + +#include +#include +#include +#include +#include + +/** + * This class allows to represent a solution in the objective space (phenotypic representation) by a std::vector of typed values, + * i.e. that an objective value is represented using a T, and this for any objective. + */ +template < class ObjectiveVectorTraits, class T > +class moeoScalarObjectiveVector : public moeoObjectiveVector < ObjectiveVectorTraits, T > +{ + public: + + using moeoObjectiveVector < ObjectiveVectorTraits, T >::size; + using moeoObjectiveVector < ObjectiveVectorTraits, T >::operator[]; + + /** + * Ctor + */ + moeoScalarObjectiveVector(T _value = 0.0) : moeoObjectiveVector < ObjectiveVectorTraits, T > (_value) + {} + + + /** + * Ctor from a vector of Ts + * @param _v the std::vector < T > + */ + moeoScalarObjectiveVector(std::vector < T > & _v) : moeoObjectiveVector < ObjectiveVectorTraits, T > (_v) + {} + + + /** + * Returns true if the current objective vector dominates _other according to the Pareto dominance relation + * (but it's better to use a moeoObjectiveVectorComparator object to compare solutions) + * @param _other the other moeoScalarObjectiveVector object to compare with + */ + bool dominates(const moeoScalarObjectiveVector < ObjectiveVectorTraits, T > & _other) const + { + moeoParetoObjectiveVectorComparator < moeoScalarObjectiveVector > comparator; + return comparator(_other, *this); + } + + + /** + * Returns true if the current objective vector is equal to _other (according to a tolerance value) + * @param _other the other moeoScalarObjectiveVector object to compare with + */ + bool operator==(const moeoScalarObjectiveVector < ObjectiveVectorTraits, T > & _other) const + { + for (unsigned int i=0; i < size(); i++) + { + if ( fabs(operator[](i) - _other[i]) > ObjectiveVectorTraits::tolerance() ) + { + return false; + } + } + return true; + } + + + /** + * Returns true if the current objective vector is different than _other (according to a tolerance value) + * @param _other the other moeoScalarObjectiveVector object to compare with + */ + bool operator!=(const moeoScalarObjectiveVector < ObjectiveVectorTraits, T > & _other) const + { + return ! operator==(_other); + } + + + /** + * Returns true if the current objective vector is smaller than _other on the first objective, then on the second, and so on + * (can be usefull for sorting/printing) + * @param _other the other moeoScalarObjectiveVector object to compare with + */ + bool operator<(const moeoScalarObjectiveVector < ObjectiveVectorTraits, T > & _other) const + { + moeoObjectiveObjectiveVectorComparator < moeoScalarObjectiveVector < ObjectiveVectorTraits, T > > cmp; + return cmp(*this, _other); + } + + + /** + * Returns true if the current objective vector is greater than _other on the first objective, then on the second, and so on + * (can be usefull for sorting/printing) + * @param _other the other moeoScalarObjectiveVector object to compare with + */ + bool operator>(const moeoScalarObjectiveVector < ObjectiveVectorTraits, T > & _other) const + { + return _other < *this; + } + + + /** + * Returns true if the current objective vector is smaller than or equal to _other on the first objective, then on the second, and so on + * (can be usefull for sorting/printing) + * @param _other the other moeoScalarObjectiveVector object to compare with + */ + bool operator<=(const moeoScalarObjectiveVector < ObjectiveVectorTraits, T > & _other) const + { + return operator==(_other) || operator<(_other); + } + + + /** + * Returns true if the current objective vector is greater than or equal to _other on the first objective, then on the second, and so on + * (can be usefull for sorting/printing) + * @param _other the other moeoScalarObjectiveVector object to compare with + */ + bool operator>=(const moeoScalarObjectiveVector < ObjectiveVectorTraits, T > & _other) const + { + return operator==(_other) || operator>(_other); + } + +}; + + +/** + * Output for a moeoScalarObjectiveVector object + * @param _os output stream + * @param _objectiveVector the objective vector to write + */ +template < class ObjectiveVectorTraits, class T > +std::ostream & operator<<(std::ostream & _os, const moeoScalarObjectiveVector < ObjectiveVectorTraits, T > & _objectiveVector) +{ + for (unsigned int i=0; i<_objectiveVector.size()-1; i++) + _os << _objectiveVector[i] << " "; + _os << _objectiveVector[_objectiveVector.size()-1]; + return _os; +} + +/** + * Input for a moeoScalarObjectiveVector object + * @param _is input stream + * @param _objectiveVector the objective vector to read + */ +template < class ObjectiveVectorTraits, class T > +std::istream & operator>>(std::istream & _is, moeoScalarObjectiveVector < ObjectiveVectorTraits, T > & _objectiveVector) +{ + _objectiveVector = moeoScalarObjectiveVector < ObjectiveVectorTraits, T > (); + for (unsigned int i=0; i<_objectiveVector.size(); i++) + { + _is >> _objectiveVector[i]; + } + return _is; +} + +#endif /*MOEOSCALAROBJECTIVEVECTOR_H_*/ diff --git a/moeo/src/diversity/moeoDummyDiversityAssignment.h b/moeo/src/diversity/moeoDummyDiversityAssignment.h index f36a75252..b233f3863 100644 --- a/moeo/src/diversity/moeoDummyDiversityAssignment.h +++ b/moeo/src/diversity/moeoDummyDiversityAssignment.h @@ -74,7 +74,7 @@ class moeoDummyDiversityAssignment : public moeoDiversityAssignment < MOEOT > * @param _pop the population * @param _objVec the objective vector */ - void updateByDeleting(eoPop < MOEOT > & _pop, ObjectiveVector & _objVec) + void updateByDeleting(eoPop < MOEOT > & /*_pop*/, ObjectiveVector & /*_objVec*/) { // nothing to do... ;-) } diff --git a/moeo/src/fitness/moeoDominanceDepthFitnessAssignment.h b/moeo/src/fitness/moeoDominanceDepthFitnessAssignment.h index 345048c2c..b07b6b7a1 100644 --- a/moeo/src/fitness/moeoDominanceDepthFitnessAssignment.h +++ b/moeo/src/fitness/moeoDominanceDepthFitnessAssignment.h @@ -1,38 +1,38 @@ /* -* -* Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2008 -* (C) OPAC Team, LIFL, 2002-2008 -* -* Arnaud Liefooghe -* -* This software is governed by the CeCILL license under French law and -* abiding by the rules of distribution of free software. You can use, -* modify and/ or redistribute the software under the terms of the CeCILL -* license as circulated by CEA, CNRS and INRIA at the following URL -* "http://www.cecill.info". -* -* As a counterpart to the access to the source code and rights to copy, -* modify and redistribute granted by the license, users are provided only -* with a limited warranty and the software's author, the holder of the -* economic rights, and the successive licensors have only limited liability. -* -* In this respect, the user's attention is drawn to the risks associated -* with loading, using, modifying and/or developing or reproducing the -* software by the user in light of its specific status of free software, -* that may mean that it is complicated to manipulate, and that also -* therefore means that it is reserved for developers and experienced -* professionals having in-depth computer knowledge. Users are therefore -* encouraged to load and test the software's suitability as regards their -* requirements in conditions enabling the security of their systems and/or -* data to be ensured and, more generally, to use and operate it in the -* same conditions as regards security. -* The fact that you are presently reading this means that you have had -* knowledge of the CeCILL license and that you accept its terms. -* -* ParadisEO WebSite : http://paradiseo.gforge.inria.fr -* Contact: paradiseo-help@lists.gforge.inria.fr -* -*/ + * + * Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2008 + * (C) OPAC Team, LIFL, 2002-2008 + * + * Arnaud Liefooghe + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + * + * ParadisEO WebSite : http://paradiseo.gforge.inria.fr + * Contact: paradiseo-help@lists.gforge.inria.fr + * + */ //----------------------------------------------------------------------------- #ifndef MOEODOMINANCEDEPTHFITNESSASSIGNMENT_H_ @@ -44,7 +44,7 @@ #include #include #include - +#include /** * Fitness assignment sheme based on Pareto-dominance count proposed in: @@ -55,69 +55,69 @@ */ template < class MOEOT > class moeoDominanceDepthFitnessAssignment : public moeoDominanceBasedFitnessAssignment < MOEOT > - { - public: - +{ +public: + /** the objective vector type of the solutions */ typedef typename MOEOT::ObjectiveVector ObjectiveVector; - - + + /** * Default ctor */ - moeoDominanceDepthFitnessAssignment() : comparator(paretoComparator) + moeoDominanceDepthFitnessAssignment(bool _rm_equiv_flag_in_2D = false) : comparator(paretoComparator), rm_equiv_flag_in_2D(_rm_equiv_flag_in_2D) {} - - + + /** * Ctor where you can choose your own way to compare objective vectors * @param _comparator the functor used to compare objective vectors */ - moeoDominanceDepthFitnessAssignment(moeoObjectiveVectorComparator < ObjectiveVector > & _comparator) : comparator(_comparator) + moeoDominanceDepthFitnessAssignment(moeoObjectiveVectorComparator < ObjectiveVector > & _comparator, bool _rm_equiv_flag_in_2D = true) : comparator(_comparator), rm_equiv_flag_in_2D(_rm_equiv_flag_in_2D) {} - - + + /** * Sets the fitness values for every solution contained in the population _pop * @param _pop the population */ void operator()(eoPop < MOEOT > & _pop) { - // number of objectives for the problem under consideration - unsigned int nObjectives = MOEOT::ObjectiveVector::nObjectives(); - if (nObjectives == 1) + // number of objectives for the problem under consideration + unsigned int nObjectives = MOEOT::ObjectiveVector::nObjectives(); + if (nObjectives == 1) { - // one objective - oneObjective(_pop); + // one objective + oneObjective(_pop); } - else if (nObjectives == 2) + else if (nObjectives == 2) { - // two objectives (the two objectives function is still to implement) - mObjectives(_pop); + // two objectives + twoObjectives(_pop); } - else if (nObjectives > 2) + else if (nObjectives > 2) { - // more than two objectives - mObjectives(_pop); + // more than two objectives + mObjectives(_pop); } - else + else { - // problem with the number of objectives - throw std::runtime_error("Problem with the number of objectives in moeoDominanceDepthFitnessAssignment"); + // problem with the number of objectives + throw std::runtime_error("Problem with the number of objectives in moeoDominanceDepthFitnessAssignment"); } - // a higher fitness is better, so the values need to be inverted - double max = _pop[0].fitness(); - for (unsigned int i=1 ; i<_pop.size() ; i++) + // a higher fitness is better, so the values need to be inverted + double max = _pop[0].fitness(); + for (unsigned int i=1 ; i<_pop.size() ; i++) { - max = std::max(max, _pop[i].fitness()); + max = std::max(max, _pop[i].fitness()); } - for (unsigned int i=0 ; i<_pop.size() ; i++) + for (unsigned int i=0 ; i<_pop.size() ; i++) { - _pop[i].fitness(max - _pop[i].fitness()); + _pop[i].fitness(max - _pop[i].fitness()); } } - - + + /** * Updates the fitness values of the whole population _pop by taking the deletion of the objective vector _objVec into account. * @param _pop the population @@ -125,141 +125,209 @@ class moeoDominanceDepthFitnessAssignment : public moeoDominanceBasedFitnessAssi */ void updateByDeleting(eoPop < MOEOT > & _pop, ObjectiveVector & _objVec) { - for (unsigned int i=0; i<_pop.size(); i++) + for (unsigned int i=0; i<_pop.size(); i++) { - // if _pop[i] is dominated by _objVec - if ( comparator(_pop[i].objectiveVector(), _objVec) ) + // if _pop[i] is dominated by _objVec + if ( comparator(_pop[i].objectiveVector(), _objVec) ) { - _pop[i].fitness(_pop[i].fitness()+1); + _pop[i].fitness(_pop[i].fitness()+1); } } } - - - private: - + + +private: + /** Functor to compare two objective vectors */ moeoObjectiveVectorComparator < ObjectiveVector > & comparator; /** Functor to compare two objective vectors according to Pareto dominance relation */ moeoParetoObjectiveVectorComparator < ObjectiveVector > paretoComparator; + /** flag to remove equivament solutions */ + bool rm_equiv_flag_in_2D; /** Functor allowing to compare two solutions according to their first objective value, then their second, and so on. */ - class ObjectiveComparator : public moeoComparator < MOEOT > - { - public: + class ObjectiveComparator : public moeoComparator < MOEOT > + { + public: /** - * Returns true if _moeo1 < _moeo2 on the first objective, then on the second, and so on + * Returns true if _moeo1 > _moeo2 on the first objective, then on the second, and so on * @param _moeo1 the first solution * @param _moeo2 the second solution */ bool operator()(const MOEOT & _moeo1, const MOEOT & _moeo2) { - return cmp(_moeo1.objectiveVector(), _moeo2.objectiveVector()); + return cmp(_moeo2.objectiveVector(), _moeo1.objectiveVector()); } - private: + private: /** the corresponding comparator for objective vectors */ moeoObjectiveObjectiveVectorComparator < ObjectiveVector > cmp; - } + } objComparator; - - + + /** * Sets the fitness values for mono-objective problems * @param _pop the population */ void oneObjective (eoPop < MOEOT > & _pop) { - // sorts the population in the ascending order - std::sort(_pop.begin(), _pop.end(), objComparator); - // assign fitness values - unsigned int rank = 1; - _pop[_pop.size()-1].fitness(rank); - for (int i=_pop.size()-2; i>=0; i--) + // sorts the population in the ascending order + std::sort(_pop.begin(), _pop.end(), objComparator); + // assign fitness values + unsigned int rank = 1; + _pop[0].fitness(rank); + for (unsigned int i=1; i<_pop.size(); i++) { - if (_pop[i].objectiveVector() != _pop[i+1].objectiveVector()) + if (_pop[i].objectiveVector() != _pop[i-1].objectiveVector()) { - rank++; + rank++; } - _pop[i].fitness(rank); + _pop[i].fitness(rank); } } - - + + /** * Sets the fitness values for bi-objective problems with a complexity of O(n log n), where n stands for the population size * @param _pop the population */ void twoObjectives (eoPop < MOEOT > & _pop) { - //... TO DO ! + double value_obj1; + unsigned int front; + unsigned int last_front = 0; + bool equiv_flag; + + // sort pointers to pop's individuals with respect to the first objective (0) in the reverse order + std::vector sortedptrpop; + sortedptrpop.resize(_pop.size()); + for(unsigned int i=0; i<_pop.size(); i++) + { + sortedptrpop[i] = & (_pop[i]); + } + moeoPtrComparator cmp(objComparator); + std::sort(sortedptrpop.begin(), sortedptrpop.end(), cmp); + + // compute an upper bound on the second objective (1) + double max_obj1 = std::numeric_limits::min(); + for(unsigned int i=0; i<_pop.size(); i++) + { + max_obj1 = std::max(max_obj1, _pop[i].objectiveVector()[1]); + } + max_obj1 += 1.0; + + // initialize a vector with the max_obj1 value everywhere + std::vector d(_pop.size(), max_obj1); + // initialize fronts + std::vector > fronts(_pop.size()); + // compute rank for each individual + for(unsigned int i=0; i0) + { + if ( (rm_equiv_flag_in_2D) && (sortedptrpop[i]->objectiveVector() == sortedptrpop[i-1]->objectiveVector()) ) + { + equiv_flag = true; + fronts.back().push_back(i); + } + } + if (!equiv_flag) + { + // the value of the second objective for the current solutions + value_obj1 = sortedptrpop[i]->objectiveVector()[1]; + // if we maximize, take the opposite value + if (MOEOT::ObjectiveVector::maximizing(1)) + value_obj1 = max_obj1 - value_obj1; + // perform binary search (log n) + std::vector::iterator it = std::upper_bound(d.begin(), d.begin() + last_front, value_obj1); + // retrieve the corresponding front + front = (unsigned int)(it - d.begin()); + if (front == last_front) + last_front++; + // update + *it = value_obj1; + // add the solution to the corresponding front + fronts[front].push_back(i); + } + } + // assign the fitness value (rank) to each individual + for (unsigned int i=0; ifitness(i+1); + } + } } - - + + /** * Sets the fitness values for problems with more than two objectives with a complexity of O(n² log n), where n stands for the population size * @param _pop the population */ void mObjectives (eoPop < MOEOT > & _pop) { - // S[i] = indexes of the individuals dominated by _pop[i] - std::vector < std::vector > S(_pop.size()); - // n[i] = number of individuals that dominate the individual _pop[i] - std::vector < unsigned int > n(_pop.size(), 0); - // fronts: F[i] = indexes of the individuals contained in the ith front - std::vector < std::vector > F(_pop.size()+2); - // used to store the number of the first front - F[1].reserve(_pop.size()); - for (unsigned int p=0; p<_pop.size(); p++) + // S[i] = indexes of the individuals dominated by _pop[i] + std::vector < std::vector > S(_pop.size()); + // n[i] = number of individuals that dominate the individual _pop[i] + std::vector < unsigned int > n(_pop.size(), 0); + // fronts: F[i] = indexes of the individuals contained in the ith front + std::vector < std::vector > F(_pop.size()+2); + // used to store the number of the first front + F[1].reserve(_pop.size()); + for (unsigned int p=0; p<_pop.size(); p++) { - for (unsigned int q=0; q<_pop.size(); q++) + for (unsigned int q=0; q<_pop.size(); q++) { - // if q is dominated by p - if ( comparator(_pop[q].objectiveVector(), _pop[p].objectiveVector()) ) + // if q is dominated by p + if ( comparator(_pop[q].objectiveVector(), _pop[p].objectiveVector()) ) { - // add q to the set of solutions dominated by p - S[p].push_back(q); + // add q to the set of solutions dominated by p + S[p].push_back(q); } - // if p is dominated by q - else if ( comparator(_pop[p].objectiveVector(), _pop[q].objectiveVector()) ) + // if p is dominated by q + else if ( comparator(_pop[p].objectiveVector(), _pop[q].objectiveVector()) ) { - // increment the domination counter of p - n[p]++; + // increment the domination counter of p + n[p]++; } } - // if no individual dominates p - if (n[p] == 0) + // if no individual dominates p + if (n[p] == 0) { - // p belongs to the first front - _pop[p].fitness(1); - F[1].push_back(p); + // p belongs to the first front + _pop[p].fitness(1); + F[1].push_back(p); } } - // front counter - unsigned int counter=1; - unsigned int p,q; - while (! F[counter].empty()) + // front counter + unsigned int counter=1; + unsigned int p,q; + while (! F[counter].empty()) { - // used to store the number of the next front - F[counter+1].reserve(_pop.size()); - for (unsigned int i=0; i + +*/ + + +#ifndef MOEOEXPBINARYINDICATORBASEDDUALFITNESSASSIGNMENT_H_ +#define MOEOEXPBINARYINDICATORBASEDDUALFITNESSASSIGNMENT_H_ + +#include + +template +class moeoExpBinaryIndicatorBasedDualFitnessAssignment : public moeoExpBinaryIndicatorBasedFitnessAssignment +{ +protected: + eoDualPopSplit _pop_split; + +public: + typedef typename MOEOT::ObjectiveVector ObjectiveVector; + typedef typename ObjectiveVector::Type Type; + + using moeoExpBinaryIndicatorBasedFitnessAssignment::values; + + moeoExpBinaryIndicatorBasedDualFitnessAssignment( + moeoNormalizedSolutionVsSolutionBinaryMetric & metric, + const double kappa = 0.05 + ) : moeoExpBinaryIndicatorBasedFitnessAssignment( metric, kappa ) {} + + + /*! If the population is homogeneous (only composed of feasible individuals or unfeasible ones), + * then apply the operators on the whole population. + * But, if there is at least one feasible individual, then apply them only on the feasible individuals. + */ + virtual void operator()( eoPop& pop ) + { + // separate the pop in feasible/unfeasible + _pop_split( pop ); + + eoPop* ppop; + // if there is at least one feasible individual, + // it will supersede all the unfeasible ones + if( _pop_split.feasible().size() == 0 ) { + ppop = & _pop_split.unfeasible(); + } else { + ppop = & _pop_split.feasible(); + } + + this->setup(*ppop); + this->computeValues(*ppop); + this->setFitnesses(*ppop); // NOTE: this alter individuals + + // bring back altered individuals in the pop + pop = _pop_split.merge(); + } + + +protected: + + using moeoExpBinaryIndicatorBasedFitnessAssignment::kappa; + + /** + * Compute every indicator value in values (values[i] = I(_v[i], _o)) + * @param _pop the population + */ + virtual void computeValues(const eoPop < MOEOT > & pop) + { + values.clear(); + values.resize(pop.size()); + for (unsigned int i=0; i & pop) + { + for (unsigned int i=0; icomputeFitness(i), pop[i].fitness().is_feasible() ); + } + } + + virtual Type computeFitness(const unsigned int _idx) + { + Type result( 0.0, values[_idx][_idx].is_feasible() ); + for (unsigned int i=0; i & _pop) + virtual void operator()(eoPop < MOEOT > & _pop) { // 1 - setting of the bounds setup(_pop); @@ -145,7 +146,7 @@ class moeoExpBinaryIndicatorBasedFitnessAssignment : public moeoBinaryIndicatorB /** the scaling factor */ double kappa; /** the computed indicator values */ - std::vector < std::vector > values; + std::vector < std::vector > values; /** @@ -154,7 +155,7 @@ class moeoExpBinaryIndicatorBasedFitnessAssignment : public moeoBinaryIndicatorB */ void setup(const eoPop < MOEOT > & _pop) { - double min, max; + typename MOEOT::ObjectiveVector::Type min, max; for (unsigned int i=0; i & _pop) + virtual void computeValues(const eoPop < MOEOT > & _pop) { values.clear(); values.resize(_pop.size()); for (unsigned int i=0; i<_pop.size(); i++) { values[i].resize(_pop.size()); + // the metric may not be symetric, thus neither is the matrix for (unsigned int j=0; j<_pop.size(); j++) { if (i != j) { - values[i][j] = metric(_pop[i].objectiveVector(), _pop[j].objectiveVector()); + values[i][j] = Type( metric(_pop[i].objectiveVector(), _pop[j].objectiveVector()) ); } } } @@ -193,10 +195,10 @@ class moeoExpBinaryIndicatorBasedFitnessAssignment : public moeoBinaryIndicatorB /** - * Sets the fitness value of the whple population + * Sets the fitness value of the whole population * @param _pop the population */ - void setFitnesses(eoPop < MOEOT > & _pop) + virtual void setFitnesses(eoPop < MOEOT > & _pop) { for (unsigned int i=0; i<_pop.size(); i++) { @@ -209,9 +211,9 @@ class moeoExpBinaryIndicatorBasedFitnessAssignment : public moeoBinaryIndicatorB * Returns the fitness value of the _idx th individual of the population * @param _idx the index */ - double computeFitness(const unsigned int _idx) + virtual Type computeFitness(const unsigned int _idx) { - double result = 0; + Type result(0.0); for (unsigned int i=0; i + +*/ + +#ifndef MOEODUALHYPERVOLUMEDIFFERENCEMETRIC_H_ +#define MOEODUALHYPERVOLUMEDIFFERENCEMETRIC_H_ + +#include + + +template +class moeoDualHyperVolumeDifferenceMetric : public moeoHyperVolumeDifferenceMetric +{ +protected: + using moeoHyperVolumeDifferenceMetric::rho; + using moeoHyperVolumeDifferenceMetric::normalize; + using moeoHyperVolumeDifferenceMetric::ref_point; + using moeoHyperVolumeDifferenceMetric::bounds; + +public: + + typedef typename ObjectiveVector::Type Type; + + moeoDualHyperVolumeDifferenceMetric( bool _normalize=true, double _rho=1.1) + : moeoHyperVolumeDifferenceMetric(_normalize, _rho) + { + + } + + moeoDualHyperVolumeDifferenceMetric( bool _normalize/*=true*/, ObjectiveVector& _ref_point/*=NULL*/ ) + : moeoHyperVolumeDifferenceMetric( _normalize, _ref_point ) + { + + } + + /** + * calculates and returns the HyperVolume value of a pareto front + * @param _set1 the vector contains all objective Vector of the first pareto front + * @param _set2 the vector contains all objective Vector of the second pareto front + */ + virtual double operator()(const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2) + { +#ifndef NDEBUG + // the two sets must be homogeneous in feasibility + assert( _set1.size() > 0 ); + for( unsigned int i=1; i<_set1.size(); ++i ) { + assert( _set1[i].is_feasible() == _set1[0].is_feasible() ); + } + assert( _set2.size() > 0 ); + for( unsigned int i=1; i<_set2.size(); ++i ) { + assert( _set2[i].is_feasible() == _set2[0].is_feasible() ); + } + // and they must have the same feasibility + assert( _set1[0].is_feasible() == _set2[0].is_feasible() ); +#endif + bool feasible = _set1[0].is_feasible(); + + double hypervolume_set1; + double hypervolume_set2; + + if(rho >= 1.0){ + //determine bounds + setup(_set1, _set2); + //determine reference point + for (unsigned int i=0; i unaryMetric(ref_point, bounds); + hypervolume_set1 = unaryMetric(_set1); + hypervolume_set2 = unaryMetric(_set2); + + return hypervolume_set1 - hypervolume_set2; + } +}; + +#endif /*MOEODUALHYPERVOLUMEDIFFERENCEMETRIC_H_*/ diff --git a/moeo/src/metric/moeoHyperVolumeDifferenceMetric.h b/moeo/src/metric/moeoHyperVolumeDifferenceMetric.h index 906923b98..ad3336cd7 100644 --- a/moeo/src/metric/moeoHyperVolumeDifferenceMetric.h +++ b/moeo/src/metric/moeoHyperVolumeDifferenceMetric.h @@ -56,7 +56,7 @@ class moeoHyperVolumeDifferenceMetric : public moeoVectorVsVectorBinaryMetric < * @param _normalize allow to normalize data (default true) * @param _rho coefficient to determine the reference point. */ - moeoHyperVolumeDifferenceMetric(bool _normalize=true, double _rho=1.1): normalize(_normalize), rho(_rho), ref_point(NULL){ + moeoHyperVolumeDifferenceMetric(bool _normalize=true, double _rho=1.1): normalize(_normalize), rho(_rho), ref_point(/*NULL*/){ bounds.resize(ObjectiveVector::Traits::nObjectives()); // initialize bounds in case someone does not want to use them for (unsigned int i=0; i & _set1, const std::vector < ObjectiveVector > & _set2) + virtual double operator()(const std::vector < ObjectiveVector > & _set1, const std::vector < ObjectiveVector > & _set2) { - double hypervolume_set1; - double hypervolume_set2; - - if(rho >= 1.0){ - //determine bounds - setup(_set1, _set2); - //determine reference point - for (unsigned int i=0; i unaryMetric(ref_point, bounds); - hypervolume_set1 = unaryMetric(_set1); - hypervolume_set2 = unaryMetric(_set2); - - return hypervolume_set1 - hypervolume_set2; + + double hypervolume_set1; + double hypervolume_set2; + + if(rho >= 1.0){ + //determine bounds + setup(_set1, _set2); + //determine reference point + for (unsigned int i=0; i unaryMetric(ref_point, bounds); + hypervolume_set1 = unaryMetric(_set1); + hypervolume_set2 = unaryMetric(_set2); + + return hypervolume_set1 - hypervolume_set2; } /** @@ -132,7 +133,7 @@ class moeoHyperVolumeDifferenceMetric : public moeoVectorVsVectorBinaryMetric < } /** - * method caclulate bounds for the normalization + * method calculate bounds for the normalization * @param _set1 the vector contains all objective Vector of the first pareto front * @param _set2 the vector contains all objective Vector of the second pareto front */ @@ -149,7 +150,7 @@ class moeoHyperVolumeDifferenceMetric : public moeoVectorVsVectorBinaryMetric < } #endif - double min, max; + typename ObjectiveVector::Type min, max; unsigned int nbObj=ObjectiveVector::Traits::nObjectives(); bounds.resize(nbObj); for (unsigned int i=0; i argument1: vector size must be greater than 0"); else{ - double min, max; + typename ObjectiveVector::Type min, max; unsigned int nbObj=ObjectiveVector::Traits::nObjectives(); bounds.resize(nbObj); for (unsigned int i=0; i & _set1, const std::vector < ObjectiveVector > & _set2){ - double min, max; + typename ObjectiveVector::Type min, max; unsigned int nbObj=ObjectiveVector::Traits::nObjectives(); bounds.resize(nbObj); for (unsigned int i=0; i #include #include +#include #include +#include #include #include @@ -125,6 +127,7 @@ #include #include #include +#include #include #include #include @@ -141,6 +144,7 @@ #include #include #include +#include #include #include #include @@ -214,5 +218,6 @@ #include #include +#include #endif /*MOEO_*/ diff --git a/moeo/src/utils/moeoBinaryMetricStat.h b/moeo/src/utils/moeoBinaryMetricStat.h index f60d20c29..42b34ff11 100644 --- a/moeo/src/utils/moeoBinaryMetricStat.h +++ b/moeo/src/utils/moeoBinaryMetricStat.h @@ -1,5 +1,38 @@ +/* +(c) 2013 Thales group + 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; version 2 + of the License. + + 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: http://eodev.sourceforge.net + +Authors: + Johann Dréo + +*/ + +#ifndef _MOEOBINARYMETRICSTAT_H_ +#define _MOEOBINARYMETRICSTAT_H_ + +#include + +/** A wrapper to save a moeoMetric in an eoStat + * + * This wrap a MOEO binary metric into an eoStat + * This is useful if you want to use it in a checkpoint, for instance. + */ template class moeoBinaryMetricStat : public eoStat { @@ -57,3 +90,5 @@ class moeoBinaryMetricStat : public eoStat bool _first_gen; }; + +#endif // _MOEOBINARYMETRICSTAT_H_ diff --git a/problems/eval/queenEval.h b/problems/eval/queenEval.h index da8dd9ee3..154261b4c 100644 --- a/problems/eval/queenEval.h +++ b/problems/eval/queenEval.h @@ -40,17 +40,18 @@ class queenEval : public eoEvalFunc { public: - /** - * Count number of threat - * @param _queen a solution - */ - void operator()(EOT& _queen){ - unsigned int fit=0; - for(unsigned int i=0; i<_queen.size()-1; i++) - for(unsigned int j=i+1; j< _queen.size(); j++) - if(((unsigned int)_queen[i]+j-i == (unsigned int)_queen[j]) || ((unsigned int)_queen[i]+i-j == (unsigned int)_queen[j])) - fit++; - _queen.fitness(fit); + /** + * Count number of threat + * @param _queen a solution + */ + void operator()(EOT& _queen) + { + unsigned int fit = 0; + for(unsigned int i = 0; i < _queen.size()-1; i++) + for(unsigned int j = i+1; j < _queen.size(); j++) + if(((unsigned int)_queen[i]+j-i == (unsigned int)_queen[j]) || ((unsigned int)_queen[i]+i-j == (unsigned int)_queen[j])) + fit++; + _queen.fitness(fit); } }; diff --git a/smp/src/island.h b/smp/src/island.h index 9e8e30edd..752b671ef 100644 --- a/smp/src/island.h +++ b/smp/src/island.h @@ -132,7 +132,7 @@ class Island : private ContWrapper, public AIsland */ virtual void receive(void); - AIsland clone() const; + //AIsland clone() const; protected: