diff --git a/eo/NEWS b/eo/NEWS index 6657f36b8..4161ff613 100644 --- a/eo/NEWS +++ b/eo/NEWS @@ -1,4 +1,5 @@ * current release: + - added an EOT& parameter to the moCoolingSchedule::update interface because some cooling schedules need it * 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/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/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,10 +61,11 @@ void eoLogger::_init() addLevel("logging", eo::logging); addLevel("debug", eo::debug); addLevel("xdebug", eo::xdebug); + } eoLogger::eoLogger() : - std::ostream(NULL), + std::ostream(NULL), _verbose("quiet", "verbose", "Set the verbose level", 'v'), _printVerboseLevels(false, "print-verbose-levels", "Print verbose levels", 'l'), @@ -66,33 +73,17 @@ eoLogger::eoLogger() : _selectedLevel(eo::progress), _contextLevel(eo::quiet), - _fd(2), - _obuf(_fd, _contextLevel, _selectedLevel) + _obuf(_contextLevel, _selectedLevel) { - std::ostream::init(&_obuf); + std::ostream::init(&_obuf); _init(); } -eoLogger::eoLogger(eo::file file) : - 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(); - *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 @@ public: 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 @@ private: //! 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 @@ private: 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 @@ public: //! 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 @@ public: 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 @@ private: 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/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..bee58957c --- /dev/null +++ b/eo/test/t-eoOptional.cpp @@ -0,0 +1,29 @@ +//----------------------------------------------------------------------------- +// 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/continuator/moFitnessMomentsStat.h b/mo/src/continuator/moFitnessMomentsStat.h new file mode 100644 index 000000000..794d113b8 --- /dev/null +++ b/mo/src/continuator/moFitnessMomentsStat.h @@ -0,0 +1,119 @@ +/* + + 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 moFitnessMomentsStat_h +#define moFitnessMomentsStat_h + +#include +#include + +/** + * Statistic that saves the standard deviation 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; + } + /*else if (firstTime) + { + value() = 0.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..3415ab3ea --- /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/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 @@ public: * 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..4e6216ad5 100644 --- a/mo/src/coolingSchedule/moDynSpanCoolingSchedule.h +++ b/mo/src/coolingSchedule/moDynSpanCoolingSchedule.h @@ -80,26 +80,27 @@ public: * 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/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 @@ public: * @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 @@ public: * 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..e120f9440 --- /dev/null +++ b/mo/src/coolingSchedule/moTrikiCoolingSchedule.h @@ -0,0 +1,353 @@ +/* + +(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 + + +/* +#include + +#include +#include +#include +#include + */ + +#include +using namespace std; + + +//! +/*! + */ +template< class EOT, class Neighbor > //, class Neighborhood > +class moTrikiCoolingSchedule: public moCoolingSchedule< EOT > +{ +public: + //typedef typename Neighbor::EOT EOT ; + typedef moNeighborhood Neighborhood ; + + //! Constructor + /*! + */ + + moTrikiCoolingSchedule (Neighborhood& _neighborhood, moEval& _eval, double _initTemp) + : initTemp(_initTemp), + mu2(10), // mu2 typically belongs to [1; 20] + K1(2), // K1 in [1; 4], the number of chains without reaching equilibrium before we raise the temperature + K2(5), // ??? + lambda1(2), // the increase in temperature, typically in [1.5; 4] + lambda2(.7), // lambda2 in [0.5; 0.99] + mu1(10), // target decrease in cost factor, in [2; 20] + xi(1.05), // xi typically belongs to [1; 1.1] + max_accepted(50), // depends on pb/neighborhood + max_generated(100), // depends on pb/neighborhood + theta(10), // theta is typically set to 10 + statIsInitialized(false), + outf("out.data") + { } + + moTrikiCoolingSchedule ( + Neighborhood& _neighborhood, moEval& _eval, double _initTemp, + double _max_accepted, + double _max_generated + ) + : initTemp(_initTemp), + mu2(10), // mu2 typically belongs to [1; 20] + K1(2), // K1 in [1; 4], the number of chains without reaching equilibrium before we raise the temperature + K2(5), // ??? + lambda1(2), // the increase in temperature, typically in [1.5; 4] + lambda2(.7), // lambda2 in [0.5; 0.99] + mu1(10), // target decrease in cost factor, in [2; 20] + xi(1.05), // xi typically belongs to [1; 1.1] + max_accepted(_max_accepted), // depends on pb/neighborhood + max_generated(_max_generated), // depends on pb/neighborhood + theta(10), // theta is typically set to 10 + statIsInitialized(false), + outf("out.data") + { } + + /** + * Initial temperature + * @param _solution initial solution + */ + double init(EOT & _solution) { + + accepted = generated = costs_sum = 0; + + negative_temp = equilibrium_not_reached = frozen = 0; + + reinitializing = false; + terminated = false; + statIsInitialized = false; + + /// + cout << "INIT T=" << initTemp << endl; + /// + + //outf.open("out"); + //outf << "ok"; + //outf.close(); + + + 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) { + + //cout << _temp << " g " << generated << endl; + + generated++; + + if (_acceptedMove) + { + accepted++; + //costs_sum += _solution.fitness(); + //varStat(_solution); + if (statIsInitialized) + momStat(_solution); + else momStat.init(_solution), statIsInitialized = true; + + //cout << _solution.fitness() << " avgCost=" << momStat.value().first << endl; + } + + + if (accepted > max_accepted || generated > max_generated) { + + if (accepted == 0) // ADDED! Otherwise the computed std dev is null; we're probably at equilibrium + { + /// + cout << "Stopping: no accepted solution" << endl; + /// + + terminated = true; + return; + } + + /// + cout << (accepted > max_accepted? "MAXACC ": "MAXGEN "); + /// + + //double avgCost = costs_sum/(double)accepted; + //double stdDev = sqrt(varStat.value()); // WARNING: IT'S NO MORE THE AVG COST, NOW IT'S THE STD DEV! + //double variance = varStat.value(); + double avgCost = momStat.value().first; + double variance = momStat.value().second; + double stdDev = sqrt(variance); + double sigma = stdDev; + double delta = sigma/mu2; + + + //outf << avgCost << endl; + //outf << _temp << endl; + outf << prevAvgCost-delta << endl; + + + accepted = generated = costs_sum = 0; + //varStat.init(_solution);//TODON use next chain's first sol + //momStat.init(_solution);//TODONE use next chain's first sol + statIsInitialized = false; + + /// + cout << "T=" << _temp << " avgCost=" << avgCost << " stdDev=" << stdDev << " currCost=" << _solution.fitness() << endl; + /// + + double alpha; + double oldprevAvgCost = prevAvgCost; + + /// + cout << "negTemp: " << negative_temp << " / " << K2 << endl; + /// + + if (negative_temp < K2) + { + if (!reinitializing) + { + /// + if (avgCost/(prevAvgCost-delta) > xi) cout << "/!\\ eq not reached!" << endl; + /// + + if (avgCost/(prevAvgCost-delta) > xi) + equilibrium_not_reached++; + else equilibrium_not_reached = 0; + } + if (equilibrium_not_reached > K1) + { + /// + cout << "/!\\ Reinitializing (eq not reached)" << endl; + /// + + reinitializing = true; + alpha = lambda1; + delta = sigma/mu1; + equilibrium_not_reached = 0; // ADDED! Otherwise the algo gets trapped here! + } + else if (_temp*delta/(sigma*sigma) >= 1) + { + /// + cout << "/!\\ neg temp!" << endl; + /// + + negative_temp++; + reinitializing = true; + if (negative_temp < K2) + { + alpha = lambda1; + delta = sigma/mu1; + } else + alpha = lambda2; + } + + // First interpretation of the pseudocode indentation: (seems obviously false because it makes the above code unreachable) + /* + } + else + { + cout << "ccc" << endl; + reinitializing = false; + prevAvgCost = avgCost; + alpha = 1-_temp*delta/(sigma*sigma); + } + */ + + // Second interpretation of the pseudocode indentation: + else + { + /// + cout << "[normal decrease]" << endl; + /// + + reinitializing = false; + prevAvgCost = avgCost; + //alpha = 1-_temp*delta/(sigma*sigma); + alpha = 1-_temp*delta/variance; + + //alpha = (sigma==0? 1: 1-_temp*delta/(sigma*sigma)); // ADDED! but removed + + if (sigma == 0) // ADDED! When std dev is null, the solution is probably at eq, and the algo can't go on anyways + terminated = true, cout << "Stopping: null std dev" << endl; + } + } + // FIXME: else what? alpha=? + + + + /// + cout << "*=" << alpha << endl; + /// + + _temp *= alpha; + + + // Never seems to be used + if (avgCost == oldprevAvgCost) // use a neighborhood to approximate double equality? + frozen++; + else frozen = 0; + + + + //exit(0); + //cin.get(); + + + } + + } + + //! Function which proceeds to the cooling + /*! + */ + bool operator() (double temperature) + { + /// + if (terminated) cout << "TERMINATED" << endl; + /// + + return frozen < theta + && !terminated ; // ADDED! because 'frozen' doesn't terminate anything + } + +private: + //moNeighborhoodStat nhStat; + //moStdFitnessNeighborStat stdDevStat; + const double + // parameters of the algorithm + //currentTemp, + initTemp, + //ratio, + //threshold, + mu2, // mu2 typically belongs to [1; 20] + K1, // K1 in [1; 4], the number of chains without reaching equilibrium before we raise the temperature + K2, + lambda1, // the increase in temperature, typically in [1.5; 4] + lambda2, // lambda2 in [0.5; 0.99] + mu1, // target decrease in cost factor, in [2; 20] + xi // xi typically belongs to [1; 1.1] + // private variables + ; + double + stdDev, + prevAvgCost, + expectedDecreaseInCost, // delta + costs_sum + ; + const int + max_accepted, + max_generated, + theta // theta is typically set to 10 + ; + int + accepted, + generated, + equilibrium_not_reached, + negative_temp, + frozen + ; + bool reinitializing, terminated; + + //moFitnessVarianceStat varStat; + moFitnessMomentsStat momStat; + bool statIsInitialized; + + ofstream outf; + +}; + +#endif + diff --git a/mo/src/explorer/moMetropolisHastingExplorer.h b/mo/src/explorer/moMetropolisHastingExplorer.h index 3123c4914..ee6169d99 100644 --- a/mo/src/explorer/moMetropolisHastingExplorer.h +++ b/mo/src/explorer/moMetropolisHastingExplorer.h @@ -68,7 +68,17 @@ public: * @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) { + 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; @@ -140,7 +150,7 @@ public: virtual bool accept(EOT & _solution) { double alpha=0.0; if (neighborhood.hasNeighbor(_solution)) { - if (solNeighborComparator(_solution, selectedNeighbor)) + if (solNeighborComparator(_solution, selectedNeighbor)) isAccept = true; else { if (_solution.fitness() != 0) { diff --git a/mo/src/explorer/moSAexplorer.h b/mo/src/explorer/moSAexplorer.h index 3d9f477ee..37fa57955 100644 --- a/mo/src/explorer/moSAexplorer.h +++ b/mo/src/explorer/moSAexplorer.h @@ -96,7 +96,7 @@ public: * @param _solution unused solution */ virtual void updateParam(EOT & _solution) { - coolingSchedule.update(temperature, this->moveApplied()); + coolingSchedule.update(temperature, this->moveApplied(), _solution); }; /** 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..e839d16fa --- /dev/null +++ b/mo/src/neighborhood/moRealNeighborhood.h @@ -0,0 +1,109 @@ +/* + +(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 // FIXME: Why don't we use eoFunctorBase on the mother classes +#include "neighborhood/moRealNeighbor.h" + +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/moStdDevEstimator.h b/mo/src/sampling/moStdDevEstimator.h new file mode 100644 index 000000000..63afb6d24 --- /dev/null +++ b/mo/src/sampling/moStdDevEstimator.h @@ -0,0 +1,134 @@ +/* + +(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 + +#include // TODO rm +#include // TODO rm + // TODO make tests + + +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/src/trikisa b/mo/src/trikisa new file mode 100644 index 000000000..63f59ff9a --- /dev/null +++ b/mo/src/trikisa @@ -0,0 +1,22 @@ +// (c) Thales group, 2010 +/* + Authors: + Johann Dreo + Caner Candan +*/ + +#ifndef _trikisa_ +#define _trikisa_ + +#include "moRealNeighbor.h" +#include "moRealNeighborhood.h" +#include "moStdDevEstimator.h" +#include "moTrikiCoolingSchedule.h" +#include "moFitnessVarianceStat.h" // TODO rm +#include "moFitnessMomentsStat.h" + +#endif // !_trikisa_ + +// Local Variables: +// mode: C++ +// End: diff --git a/mo/test/CMakeLists.txt b/mo/test/CMakeLists.txt index 652b66be3..319ffb0c9 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}) @@ -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-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..a1510a831 --- /dev/null +++ b/mo/test/t-moFitnessVarianceStat.cpp @@ -0,0 +1,66 @@ +/* + +(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-moFitnessNeighborStat.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); +} 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..6473ffceb --- /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..e69de29bb diff --git a/mo/test/t-moTrikiReal.cpp b/mo/test/t-moTrikiReal.cpp new file mode 100644 index 000000000..9b8038ba7 --- /dev/null +++ b/mo/test/t-moTrikiReal.cpp @@ -0,0 +1,188 @@ +/* + +(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 + +#include "neighborhood/moRealNeighbor.h" +#include "neighborhood/moRealNeighborhood.h" + +#include "sampling/moStdDevEstimator.h" + +#include "coolingSchedule/moTrikiCoolingSchedule.h" + + +//#include "moRealInitTemperature.h" + +//#include "do/make_real_init_temperature.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 > fullEval( eval ); + + //moNeighborhood< Neighbor >* neighborhood; + + int dimSize = 20; + + //moRealInitTemperature< EOT >& real_init = do_make_real_init_temperature( parser, state, eval ); + //moInitTemperature< EOT, Neighbor >& real_init = do_make_real_init_temperature( parser, state, eval, neval ); + //moInitTemperature< EOT, Neighbor >& real_init = do_make_init_temperature( parser, state, eval, neval, neighborhood ); + //moStdDevEstimator< EOT, Neighbor >& real_init = do_make_init_temperature( parser, state, eval, neval, neighborhood, dimSize ); + + + //------------------------------------------------------- + // 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(); + //unsigned int ratio = parser.getORcreateParam( (unsigned int)1, "ratio", "Bounder ratio", '\0', section ).value(); // not used + + //------------------------------------------------------- + + + //------------------------------------------------------- + // 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 = new moRealNeighborhood< edoUniform< EOT >, Neighbor >( *distrib, *sampler, *bounder_search ); + moRealNeighborhood< edoUniform< EOT >, Neighbor > neighborhood( distrib, sampler, bounder_search ); + //state.storeFunctor(neighborhood);state.storeFunctor(neighborhood); + + //moStdDevEstimator< EOT, Neighbor >* init = new moStdDevEstimator< EOT, Neighbor >( *neighborhood, fullEval, eval, maxiter ); + //moStdDevEstimator< EOT, Neighbor > init( maxiter, neighborhood, fullEval, eval ); + moStdDevEstimator< EOT, Neighbor > init( maxiter, neighborhood, fullEval ); + + //------------------------------------------------------- + + + + + //------------------------------------------------------- + // Help + Verbose routines + //------------------------------------------------------- + + if (parser.userNeedsHelp()) + { + parser.printHelp(std::cout); + exit(1); + } + + make_help(parser); + + //------------------------------------------------------- + + + //EOT solution(2, 5); + EOT solution(dimSize, 5); + /* + real_init( solution ); + + std::cout << "do_make_real_init_temperature( parser, eval ): " + << real_init.value() + << std::endl; + */ + + std::cout << "do_make_real_init_temperature( parser, eval ): " + << 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(1, monitor); + checkpoint.add(countMon); + //moCounterMonitorSaver gnuMon (1, monitor2); + //checkpoint.add(gnuMon); + monitor.add(fitStat); + //monitor2.add(fitStat); + + + + moTrikiCoolingSchedule coolingSchedule ( + neighborhood, neval, init( solution ), + //50, + 200, //150, + //100 + 350 // 250 + ); + moSA localSearch(*neighborhood, eval, fullEval, coolingSchedule, 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; + + //delete neighborhood; + + return 0; +} + + +