From 23a7482f1c3fc7a6700e253da5ea35116e563e3c Mon Sep 17 00:00:00 2001 From: LPTK Date: Wed, 12 Jun 2013 15:19:32 +0200 Subject: [PATCH] files for trikisa --- mo/src/continuator/moFitnessMomentsStat.h | 119 ++++++ mo/src/continuator/moStdDevEstimator.h | 143 +++++++ .../coolingSchedule/moTrikiCoolingSchedule.h | 363 ++++++++++++++++++ mo/src/neighborhood/moRealNeighbor.h | 87 +++++ mo/src/neighborhood/moRealNeighborhood.h | 78 ++++ mo/src/trikisa | 22 ++ mo/test/t-moTriki.cpp | 0 mo/test/t-moTrikiReal.cpp | 0 8 files changed, 812 insertions(+) create mode 100644 mo/src/continuator/moFitnessMomentsStat.h create mode 100644 mo/src/continuator/moStdDevEstimator.h create mode 100644 mo/src/coolingSchedule/moTrikiCoolingSchedule.h create mode 100644 mo/src/neighborhood/moRealNeighbor.h create mode 100644 mo/src/neighborhood/moRealNeighborhood.h create mode 100644 mo/src/trikisa create mode 100644 mo/test/t-moTriki.cpp create mode 100644 mo/test/t-moTrikiReal.cpp 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/moStdDevEstimator.h b/mo/src/continuator/moStdDevEstimator.h new file mode 100644 index 000000000..4d8902055 --- /dev/null +++ b/mo/src/continuator/moStdDevEstimator.h @@ -0,0 +1,143 @@ +#ifndef __moStdDevEstimator_h__ +#define __moStdDevEstimator_h__ + +#include +#include + +#include // TODO rm +#include // TODO rm + // TODO make tests + + +template< class T > +class eoOptional { +public: + static const eoOptional null; // = eoOptional(); + + 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"); + return *_val; + } + +protected: + eoOptional () + : _val(NULL) + { } + +private: + T* _val; +}; + +template< class T > +const eoOptional eoOptional::null = eoOptional(); + + +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 < Neighbor > & 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/coolingSchedule/moTrikiCoolingSchedule.h b/mo/src/coolingSchedule/moTrikiCoolingSchedule.h new file mode 100644 index 000000000..259f1747c --- /dev/null +++ b/mo/src/coolingSchedule/moTrikiCoolingSchedule.h @@ -0,0 +1,363 @@ +/* + + Copyright (C) DOLPHIN Project-Team, INRIA Futurs, 2006-2008 + (C) OPAC Team, LIFL, 2002-2008 + + Sébastien Cahon, Jean-Charles Boisson (Jean-Charles.Boisson@lifl.fr) + + 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 _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/neighborhood/moRealNeighbor.h b/mo/src/neighborhood/moRealNeighbor.h new file mode 100644 index 000000000..4af8924f2 --- /dev/null +++ b/mo/src/neighborhood/moRealNeighbor.h @@ -0,0 +1,87 @@ +#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..7e0a4a738 --- /dev/null +++ b/mo/src/neighborhood/moRealNeighborhood.h @@ -0,0 +1,78 @@ + +#ifndef __moRealNeighborhood_h__ +#define __moRealNeighborhood_h__ + +#include +#include // FIXME: Why don't we use eoFunctorBase on the mother classes +#include "moRealNeighbor.h" + +template +class moRealNeighborhood : public moRndNeighborhood< Neighbor >, public eoFunctorBase +{ +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/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/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..e69de29bb