Cleaning, doc & fixes for trikiSA
This commit is contained in:
parent
25823ba327
commit
7ae7468428
1 changed files with 419 additions and 332 deletions
|
|
@ -1,363 +1,450 @@
|
||||||
/*
|
/*
|
||||||
<moTrikiCoolingSchedule.h>
|
|
||||||
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)
|
(c) Thales group, 2010
|
||||||
|
|
||||||
This software is governed by the CeCILL license under French law and
|
This library is free software; you can redistribute it and/or
|
||||||
abiding by the rules of distribution of free software. You can use,
|
modify it under the terms of the GNU Lesser General Public
|
||||||
modify and/ or redistribute the software under the terms of the CeCILL
|
License as published by the Free Software Foundation;
|
||||||
license as circulated by CEA, CNRS and INRIA at the following URL
|
version 2 of the License.
|
||||||
"http://www.cecill.info".
|
|
||||||
|
|
||||||
As a counterpart to the access to the source code and rights to copy,
|
This library is distributed in the hope that it will be useful,
|
||||||
modify and redistribute granted by the license, users are provided only
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
with a limited warranty and the software's author, the holder of the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
economic rights, and the successive licensors have only limited liability.
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
In this respect, the user's attention is drawn to the risks associated
|
You should have received a copy of the GNU Lesser General Public
|
||||||
with loading, using, modifying and/or developing or reproducing the
|
License along with this library; if not, write to the Free Software
|
||||||
software by the user in light of its specific status of free software,
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
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: http://eodev.sourceforge.net
|
||||||
Contact: paradiseo-help@lists.gforge.inria.fr
|
|
||||||
*/
|
Authors:
|
||||||
|
Lionel Parreaux <lionel.parreaux@gmail.com>
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef _moTrikiCoolingSchedule_h
|
#ifndef _moTrikiCoolingSchedule_h
|
||||||
#define _moTrikiCoolingSchedule_h
|
#define _moTrikiCoolingSchedule_h
|
||||||
|
|
||||||
#include <coolingSchedule/moCoolingSchedule.h>
|
#include <coolingSchedule/moCoolingSchedule.h>
|
||||||
|
|
||||||
|
#include <neighborhood/moNeighborhood.h>
|
||||||
|
|
||||||
#include <continuator/moNeighborhoodStat.h>
|
#include <continuator/moNeighborhoodStat.h>
|
||||||
#include <continuator/moStdFitnessNeighborStat.h>
|
#include <continuator/moStdFitnessNeighborStat.h>
|
||||||
#include <neighborhood/moNeighborhood.h>
|
|
||||||
#include <continuator/moStat.h>
|
#include <continuator/moStat.h>
|
||||||
#include <moFitnessMomentsStat.h>
|
#include <continuator/moFitnessMomentsStat.h>
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
* Cooling Schedule, adapted from E.Triki, Y.Collette, P.Siarry (2004)
|
||||||
#include <continuator/moStat.h>
|
* This CS is based on an initial estimation of the standard deviation
|
||||||
|
* and an expected decrease in cost between each Markov chain,
|
||||||
#include <explorer/moNeighborhoodExplorer.h>
|
* possibly re-estimating the prameters
|
||||||
#include <comparator/moNeighborComparator.h>
|
*
|
||||||
#include <comparator/moSolNeighborComparator.h>
|
*
|
||||||
#include <neighborhood/moNeighborhood.h>
|
* 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 >
|
||||||
#include <iostream>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
|
|
||||||
//!
|
|
||||||
/*!
|
|
||||||
*/
|
|
||||||
template< class EOT, class Neighbor > //, class Neighborhood >
|
|
||||||
class moTrikiCoolingSchedule: public moCoolingSchedule< EOT >
|
class moTrikiCoolingSchedule: public moCoolingSchedule< EOT >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//typedef typename Neighbor::EOT EOT ;
|
|
||||||
typedef moNeighborhood<Neighbor> Neighborhood ;
|
|
||||||
|
|
||||||
//! Constructor
|
/**
|
||||||
/*!
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
moTrikiCoolingSchedule (Neighborhood& _neighborhood, moEval<Neighbor>& _eval, double _initTemp)
|
/**
|
||||||
: initTemp(_initTemp),
|
* Initialization
|
||||||
mu2(10), // mu2 typically belongs to [1; 20]
|
* @param _solution initial solution
|
||||||
K1(2), // K1 in [1; 4], the number of chains without reaching equilibrium before we raise the temperature
|
*/
|
||||||
K2(5), // ???
|
double init(EOT & _solution) {
|
||||||
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 (
|
chainStat.temperature = initTemp;
|
||||||
Neighborhood& _neighborhood, moEval<Neighbor>& _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")
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/**
|
accepted = generated = 0;
|
||||||
* Initial temperature
|
|
||||||
* @param _solution initial solution
|
|
||||||
*/
|
|
||||||
double init(EOT & _solution) {
|
|
||||||
|
|
||||||
accepted = generated = costs_sum = 0;
|
negative_temp = equilibrium_not_reached = frozen = 0;
|
||||||
|
|
||||||
negative_temp = equilibrium_not_reached = frozen = 0;
|
chainStat.delta = initStdDev/mu2;
|
||||||
|
|
||||||
reinitializing = false;
|
reinitializing = false;
|
||||||
terminated = false;
|
|
||||||
statIsInitialized = false;
|
|
||||||
|
|
||||||
///
|
return initTemp;
|
||||||
cout << "INIT T=" << initTemp << endl;
|
}
|
||||||
///
|
|
||||||
|
|
||||||
//outf.open("out");
|
/**
|
||||||
//outf << "ok";
|
* update the temperature by a factor
|
||||||
//outf.close();
|
* @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;
|
||||||
|
|
||||||
|
|
||||||
return initTemp;
|
// TODO use a relative-epsilon comparison to approximate equality
|
||||||
}
|
if (avgFitness == prevAvgFitness)
|
||||||
|
frozen++;
|
||||||
|
else frozen = 0;
|
||||||
|
|
||||||
/**
|
if (frozen >= theta)
|
||||||
* update the temperature by a factor
|
chainStat.stoppingReason = stoppingReasons[2];
|
||||||
* @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)
|
/*
|
||||||
{
|
* operator() Determines if the cooling schedule shall end or continue
|
||||||
accepted++;
|
* @param temperature the current temperature
|
||||||
//costs_sum += _solution.fitness();
|
*/
|
||||||
//varStat(_solution);
|
bool operator() (double temperature)
|
||||||
if (statIsInitialized)
|
{
|
||||||
momStat(_solution);
|
|
||||||
else momStat.init(_solution), statIsInitialized = true;
|
|
||||||
|
|
||||||
//cout << _solution.fitness() << " avgCost=" << momStat.value().first << endl;
|
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
|
||||||
|
|
||||||
|
|
||||||
if (accepted > max_accepted || generated > max_generated) {
|
const bool markovChainEnded() const
|
||||||
|
{
|
||||||
|
return chainStat.chainEndingReason != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (accepted == 0) // ADDED! Otherwise the computed std dev is null; we're probably at equilibrium
|
struct MarkovChainStats;
|
||||||
{
|
const MarkovChainStats& markovChainStats() const
|
||||||
///
|
{
|
||||||
cout << "Stopping: no accepted solution" << endl;
|
return chainStat;
|
||||||
///
|
}
|
||||||
|
|
||||||
terminated = true;
|
struct MarkovChainStats {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
MarkovChainStats()
|
||||||
cout << (accepted > max_accepted? "MAXACC ": "MAXGEN ");
|
: stdDev(0), avgFitness(0), temperature(-1), currentFitness(-1), alpha(0), delta(0),
|
||||||
///
|
equilibriumNotReached(false), negativeTemp(false)
|
||||||
|
{ }
|
||||||
|
|
||||||
//double avgCost = costs_sum/(double)accepted;
|
double
|
||||||
//double stdDev = sqrt(varStat.value()); // WARNING: IT'S NO MORE THE AVG COST, NOW IT'S THE STD DEV!
|
stdDev,
|
||||||
//double variance = varStat.value();
|
avgFitness,
|
||||||
double avgCost = momStat.value().first;
|
temperature,
|
||||||
double variance = momStat.value().second;
|
currentFitness,
|
||||||
double stdDev = sqrt(variance);
|
alpha,
|
||||||
double sigma = stdDev;
|
delta
|
||||||
double delta = sigma/mu2;
|
;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//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:
|
private:
|
||||||
//moNeighborhoodStat<Neighbor> nhStat;
|
|
||||||
//moStdFitnessNeighborStat<Neighbor> 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<EOT> varStat;
|
// parameters of the algorithm
|
||||||
moFitnessMomentsStat<EOT> momStat;
|
|
||||||
bool statIsInitialized;
|
|
||||||
|
|
||||||
ofstream outf;
|
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<EOT> 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<Neighbor>::stoppingReasons[] = {"no accepted solution", "null std dev" , "frozen >= theta"};
|
||||||
|
template< class Neighbor >
|
||||||
|
const char * moTrikiCoolingSchedule<Neighbor>::chainEndingReasons[] = {"MAX ACCepted solutions", "MAX GENerated solutions"};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue