Migration from SVN

This commit is contained in:
quemy 2012-08-30 11:30:11 +02:00
commit 8cd56f37db
45 changed files with 0 additions and 4096888 deletions

233
eo/src/es/CMAParams.cpp Normal file
View file

@ -0,0 +1,233 @@
/*
* C++ification of Nikolaus Hansen's original C-source code for the
* CMA-ES
*
* C++-ificiation performed by Maarten Keijzer (C) 2005. Licensed under
* the LGPL. Original copyright of Nikolaus Hansen can be found below
*
*
*
*/
/* --------------------------------------------------------- */
/* --------------------------------------------------------- */
/* --- File: cmaes.c -------- Author: Nikolaus Hansen --- */
/* --------------------------------------------------------- */
/*
* CMA-ES for non-linear function minimization.
*
* Copyright (C) 1996, 2003 Nikolaus Hansen.
* e-mail: hansen@bionik.tu-berlin.de
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later
* version (see http://www.gnu.org/copyleft/lesser.html).
*
* 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.
*
* */
/* --- Changes : ---
* 03/03/21: argument const double *rgFunVal of
* cmaes_ReestimateDistribution() was treated incorrectly.
* 03/03/29: restart via cmaes_resume_distribution() implemented.
* 03/03/30: Always max std dev / largest axis is printed first.
* 03/08/30: Damping is adjusted for large mueff.
* 03/10/30: Damping is adjusted for large mueff always.
* 04/04/22: Cumulation time and damping for step size adjusted.
* No iniphase but conditional update of pc.
* Version 2.23.
* */
#include <es/CMAParams.h>
#include <utils/eoParser.h>
#include <string>
using namespace std;
namespace eo {
CMAParams::CMAParams(eoParser& parser, unsigned dimensionality) {
string section = "CMA parameters";
n = parser.createParam(dimensionality, "dimensionality", "Dimensionality (N) of the problem", 'N', section, dimensionality == 0).value();
maxgen = parser.createParam(
1000,
"max-gen",
"Maximum number of generations that the system will run (needed for damping)",
'M',
section).value();
if (n == 0) {
return;
}
defaults(n, maxgen);
/* handle lambda */
lambda = parser.createParam(
lambda,
"lambda",
"Number of offspring",
'l',
section).value();
if (lambda < 2) {
lambda = 4+(int)(3*log((double) n));
cerr << "Too small lambda specified, setting it to " << lambda << endl;
}
/* handle mu */
mu = parser.createParam(
mu,
"mu",
"Population size",
'm',
section).value();
if (mu >= lambda) {
mu = lambda/2;
cerr << "Mu set larger/equal to lambda, setting it to " << mu << endl;
}
/* handle selection weights */
int weight_type = parser.createParam(
0,
"weighting",
"Weighting scheme (for 'selection'): 0 = logarithmic, 1 = equal, 2 = linear",
'w',
section).value();
switch (weight_type) {
case 1:
{
for (unsigned i = 0; i < weights.size(); ++i) {
weights[i] = mu - i;
}
}
case 2:
{
weights = 1.;
}
default :
{
for (unsigned i = 0; i < weights.size(); ++i) {
weights[i] = log(mu+1.)-log(i+1.);
}
}
}
/* Normalize weights and set mu_eff */
double sumw = weights.sum();
mueff = sumw * sumw / (weights * weights).sum();
weights /= sumw;
/* most of the rest depends on mu_eff, so needs to be set again */
/* set the others using Nikolaus logic. If you want to tweak, you can parameterize over these defaults */
mucov = mueff;
ccumsig = (mueff + 2.) / (n + mueff + 3.);
ccumcov = 4. / (n + 4);
double t1 = 2. / ((n+1.4142)*(n+1.4142));
double t2 = (2.*mucov-1.) / ((n+2.)*(n+2.)+mucov);
t2 = (t2 > 1) ? 1 : t2;
t2 = (1./mucov) * t1 + (1.-1./mucov) * t2;
ccov = t2;
damp = 1 + std::max(0.3,(1.-(double)n/(double)maxgen))
* (1+2*std::max(0.,sqrt((mueff-1.)/(n+1.))-1)) /* limit sigma increase */
/ ccumsig;
vector<double> mins(1,0.0);
mins = parser.createParam(
mins,
"min-stdev",
"Array of minimum stdevs, last one will apply for all remaining axes",
0,
section).value();
if (mins.size() > n) mins.resize(n);
if (mins.size()) {
minStdevs = mins.back();
for (unsigned i = 0; i < mins.size(); ++i) {
minStdevs[i] = mins[i];
}
}
vector<double> inits(1,0.3);
inits = parser.createParam(
inits,
"init-stdev",
"Array of initial stdevs, last one will apply for all remaining axes",
0,
section).value();
if (inits.size() > n) inits.resize(n);
if (inits.size()) {
initialStdevs = inits.back();
for (unsigned i = 0; i < inits.size(); ++i) {
initialStdevs[i] = inits[i];
}
}
}
void CMAParams::defaults(unsigned n_, unsigned maxgen_) {
n = n_;
maxgen = maxgen_;
lambda = 4+(int)(3*log((double) n));
mu = lambda / 2;
weights.resize(mu);
for (unsigned i = 0; i < weights.size(); ++i) {
weights[i] = log(mu+1.)-log(i+1.);
}
/* Normalize weights and set mu_eff */
double sumw = weights.sum();
mueff = sumw * sumw / (weights * weights).sum();
weights /= sumw;
mucov = mueff;
ccumsig *= (mueff + 2.) / (n + mueff + 3.);
ccumcov = 4. / (n + 4);
double t1 = 2. / ((n+1.4142)*(n+1.4142));
double t2 = (2.*mucov-1.) / ((n+2.)*(n+2.)+mucov);
t2 = (t2 > 1) ? 1 : t2;
t2 = (1./mucov) * t1 + (1.-1./mucov) * t2;
ccov = t2;
damp = 1 + std::max(0.3,(1.-(double)n/maxgen))
* (1+2*std::max(0.,sqrt((mueff-1.)/(n+1.))-1)) /* limit sigma increase */
/ ccumsig;
minStdevs.resize(n);
minStdevs = 0.0;
initialStdevs.resize(n);
initialStdevs = 0.3;
}
}// namespace eo

51
eo/src/es/CMAParams.h Normal file
View file

@ -0,0 +1,51 @@
/*
* C++ification of Nikolaus Hansen's original C-source code for the
* CMA-ES.
*
* Copyright (C) 1996, 2003, Nikolaus Hansen
* (C) 2005, Maarten Keijzer
*
* License: LGPL
*
*/
#ifndef CMAPARAMS_H__
#define CMAPARAMS_H__
#include <valarray>
class eoParser;
namespace eo {
class CMAParams {
public:
CMAParams() { /* Call this and all values need to be set by hand */ }
CMAParams(eoParser& parser, unsigned dimensionality = 0); // 0 dimensionality -> user needs to set it
void defaults(unsigned n_, unsigned maxgen_); /* apply all defaults using n and maxgen */
unsigned n;
unsigned maxgen;
unsigned lambda; /* -> mu */
unsigned mu; /* -> weights, lambda */
std::valarray<double> weights; /* <- mu, -> mueff -> mucov -> ccov */
double mueff; /* <- weights */
double mucov;
double damp; /* <- ccumsig, maxeval, lambda */
double ccumsig; /* -> damp, <- N */
double ccumcov;
double ccov; /* <- mucov, N */
std::valarray<double> minStdevs; /* Minimum standard deviations per coordinate (default = 0.0) */
std::valarray<double> initialStdevs; /* Initial standard deviations per coordinate (default = 0.3) */
};
} // namespace eo
#endif

364
eo/src/es/CMAState.cpp Normal file
View file

@ -0,0 +1,364 @@
/*
* C++ification of Nikolaus Hansen's original C-source code for the
* CMA-ES
*
* C++-ificiation performed by Maarten Keijzer (C) 2005. Licensed under
* the LGPL. Original copyright of Nikolaus Hansen can be found below
*
*
* Some changes have been made to the original flow and logic of the
* algorithm:
*
* - Numerical issues are now treated 'before' going into the eigenvector decomposition
* (this was done out of convenience)
* - dMaxSignifiKond (smallest x such that x == x + 1.0) replaced by
* numeric_limits<double>::epsilon() (smallest x such that 1.0 != 1.0 + x)
*
*
*/
/* --------------------------------------------------------- */
/* --------------------------------------------------------- */
/* --- File: cmaes.c -------- Author: Nikolaus Hansen --- */
/* --------------------------------------------------------- */
/*
* CMA-ES for non-linear function minimization.
*
* Copyright (C) 1996, 2003 Nikolaus Hansen.
* e-mail: hansen@bionik.tu-berlin.de
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later
* version (see http://www.gnu.org/copyleft/lesser.html).
*
* 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.
*
* */
/* --- Changes : ---
* 03/03/21: argument const double *rgFunVal of
* cmaes_ReestimateDistribution() was treated incorrectly.
* 03/03/29: restart via cmaes_resume_distribution() implemented.
* 03/03/30: Always max std dev / largest axis is printed first.
* 03/08/30: Damping is adjusted for large mueff.
* 03/10/30: Damping is adjusted for large mueff always.
* 04/04/22: Cumulation time and damping for step size adjusted.
* No iniphase but conditional update of pc.
* Version 2.23.
* */
#include <valarray>
#include <limits>
#include <iostream>
#include <cassert>
#include <utils/eoRNG.h>
#include <es/CMAState.h>
#include <es/CMAParams.h>
#include <es/matrices.h>
#include <es/eig.h>
using namespace std;
namespace eo {
struct CMAStateImpl {
CMAParams p;
lower_triangular_matrix C; // Covariance matrix
square_matrix B; // Eigen vectors (in columns)
valarray<double> d; // eigen values (diagonal matrix)
valarray<double> pc; // Evolution path
valarray<double> ps; // Evolution path for stepsize;
vector<double> mean; // current mean to sample around
double sigma; // global step size
unsigned gen;
vector<double> fitnessHistory;
CMAStateImpl(const CMAParams& params_, const vector<double>& m, double sigma_) :
p(params_),
C(p.n), B(p.n), d(p.n), pc(p.n), ps(p.n), mean(m), sigma(sigma_),
gen(0), fitnessHistory(3)
{
double trace = (p.initialStdevs * p.initialStdevs).sum();
/* Initialize covariance structure */
for (unsigned i = 0; i < p.n; ++i)
{
B[i][i] = 1.;
d[i] = p.initialStdevs[i] * sqrt(p.n / trace);
C[i][i] = d[i] * d[i];
pc[i] = 0.;
ps[i] = 0.;
}
}
void sample(vector<double>& v) {
unsigned n = p.n;
v.resize(n);
vector<double> tmp(n);
for (unsigned i = 0; i < n; ++i)
tmp[i] = d[i] * rng.normal();
/* add mutation (sigma * B * (D*z)) */
for (unsigned i = 0; i < n; ++i) {
double sum = 0;
for (unsigned j = 0; j < n; ++j) {
sum += B[i][j] * tmp[j];
}
v[i] = mean[i] + sigma * sum;
}
}
void reestimate(const vector<const vector<double>* >& pop, double muBest, double muWorst) {
assert(pop.size() == p.mu);
unsigned n = p.n;
fitnessHistory[gen % fitnessHistory.size()] = muBest; // needed for divergence check
vector<double> oldmean = mean;
valarray<double> BDz(n);
/* calculate xmean and rgBDz~N(0,C) */
for (unsigned i = 0; i < n; ++i) {
mean[i] = 0.;
for (unsigned j = 0; j < pop.size(); ++j) {
mean[i] += p.weights[j] * (*pop[j])[i];
}
BDz[i] = sqrt(p.mueff)*(mean[i] - oldmean[i])/sigma;
}
vector<double> tmp(n);
/* calculate z := D^(-1) * B^(-1) * rgBDz into rgdTmp */
for (unsigned i = 0; i < n; ++i) {
double sum = 0.0;
for (unsigned j = 0; j < n; ++j) {
sum += B[j][i] * BDz[j];
}
tmp[i] = sum / d[i];
}
/* cumulation for sigma (ps) using B*z */
for (unsigned i = 0; i < n; ++i) {
double sum = 0.0;
for (unsigned j = 0; j < n; ++j)
sum += B[i][j] * tmp[j];
ps[i] = (1. - p.ccumsig) * ps[i] + sqrt(p.ccumsig * (2. - p.ccumsig)) * sum;
}
/* calculate norm(ps)^2 */
double psxps = (ps * ps).sum();
double chiN = sqrt((double) p.n) * (1. - 1./(4.*p.n) + 1./(21.*p.n*p.n));
/* cumulation for covariance matrix (pc) using B*D*z~N(0,C) */
double hsig = sqrt(psxps) / sqrt(1. - pow(1.-p.ccumsig, 2.*gen)) / chiN < 1.5 + 1./(p.n-0.5);
pc = (1. - p.ccumcov) * pc + hsig * sqrt(p.ccumcov * (2. - p.ccumcov)) * BDz;
/* stop initial phase (MK, this was not reachable in the org code, deleted) */
/* remove momentum in ps, if ps is large and fitness is getting worse */
if (gen >= fitnessHistory.size()) {
// find direction from muBest and muWorst (muBest == muWorst handled seperately
double direction = muBest < muWorst? -1.0 : 1.0;
unsigned now = gen % fitnessHistory.size();
unsigned prev = (gen-1) % fitnessHistory.size();
unsigned prevprev = (gen-2) % fitnessHistory.size();
bool fitnessWorsens = (muBest == muWorst) || // <- increase norm also when population has converged (this deviates from Hansen's scheme)
( (direction * fitnessHistory[now] < direction * fitnessHistory[prev])
&&
(direction * fitnessHistory[now] < direction * fitnessHistory[prevprev]));
if(psxps/p.n > 1.5 + 10.*sqrt(2./p.n) && fitnessWorsens) {
double tfac = sqrt((1 + std::max(0., log(psxps/p.n))) * p.n / psxps);
ps *= tfac;
psxps *= tfac*tfac;
}
}
/* update of C */
/* Adapt_C(t); not used anymore */
if (p.ccov != 0.) {
//flgEigensysIsUptodate = 0;
/* update covariance matrix */
for (unsigned i = 0; i < n; ++i) {
vector<double>::iterator c_row = C[i];
for (unsigned j = 0; j <= i; ++j) {
c_row[j] =
(1 - p.ccov) * c_row[j]
+
p.ccov * (1./p.mucov) * pc[i] * pc[j]
+
(1-hsig) * p.ccumcov * (2. - p.ccumcov) * c_row[j];
/*C[i][j] = (1 - p.ccov) * C[i][j]
+ sp.ccov * (1./sp.mucov)
* (rgpc[i] * rgpc[j]
+ (1-hsig)*sp.ccumcov*(2.-sp.ccumcov) * C[i][j]); */
for (unsigned k = 0; k < p.mu; ++k) { /* additional rank mu update */
c_row[j] += p.ccov * (1-1./p.mucov) * p.weights[k]
* ( (*pop[k])[i] - oldmean[i])
* ( (*pop[k])[j] - oldmean[j])
/ sigma / sigma;
// * (rgrgx[index[k]][i] - rgxold[i])
// * (rgrgx[index[k]][j] - rgxold[j])
// / sigma / sigma;
}
}
}
}
/* update of sigma */
sigma *= exp(((sqrt(psxps)/chiN)-1.)/p.damp);
/* calculate eigensystem, must be done by caller */
//cmaes_UpdateEigensystem(0);
/* treat minimal standard deviations and numeric problems
* Note that in contrast with the original code, some numerical issues are treated *before* we
* go into the eigenvalue calculation */
treatNumericalIssues(muBest, muWorst);
gen++; // increase generation
}
void treatNumericalIssues(double best, double worst) {
/* treat stdevs */
for (unsigned i = 0; i < p.n; ++i) {
if (sigma * sqrt(C[i][i]) < p.minStdevs[i]) {
// increase stdev
sigma *= exp(0.05+1./p.damp);
break;
}
}
/* treat convergence */
if (best == worst) {
sigma *= exp(0.2 + 1./p.damp);
}
/* Jede Hauptachse i testen, ob x == x + 0.1 * sigma * rgD[i] * B[i] */
/* Test if all the means are not numerically out of whack with our coordinate system*/
for (unsigned axis = 0; axis < p.n; ++axis) {
double fac = 0.1 * sigma * d[axis];
unsigned coord;
for (coord = 0; coord < p.n; ++coord) {
if (mean[coord] != mean[coord] + fac * B[coord][axis]) {
break;
}
}
if (coord == p.n) { // means are way too big (little) for numerical accuraccy. Start rocking the craddle a bit more
sigma *= exp(0.2+1./p.damp);
}
}
/* Testen ob eine Komponente des Objektparameters festhaengt */
/* Correct issues with scale between objective values and covariances */
bool theresAnIssue = false;
for (unsigned i = 0; i < p.n; ++i) {
if (mean[i] == mean[i] + 0.2 * sigma * sqrt(C[i][i])) {
C[i][i] *= (1. + p.ccov);
theresAnIssue = true;
}
}
if (theresAnIssue) {
sigma *= exp(0.05 + 1./p.damp);
}
}
bool updateEigenSystem(unsigned max_tries, unsigned max_iters) {
if (max_iters==0) max_iters = 30 * p.n;
static double lastGoodMinimumEigenValue = 1.0;
/* Try to get a valid calculation */
for (unsigned tries = 0; tries < max_tries; ++tries) {
unsigned iters = eig( p.n, C, d, B, max_iters);
if (iters < max_iters)
{ // all is well
/* find largest/smallest eigenvalues */
double minEV = d.min();
double maxEV = d.max();
/* (MK Original comment was) :Limit Condition of C to dMaxSignifKond+1
* replaced dMaxSignifKond with 1./numeric_limits<double>::epsilon()
* */
if (maxEV * numeric_limits<double>::epsilon() > minEV) {
double tmp = maxEV * numeric_limits<double>::epsilon() - minEV;
minEV += tmp;
for (unsigned i=0;i<p.n;++i) {
C[i][i] += tmp;
d[i] += tmp;
}
} /* if */
lastGoodMinimumEigenValue = minEV;
d = sqrt(d);
//flgEigensysIsUptodate = 1;
//genOfEigensysUpdate = gen;
//clockeigensum += clock() - clockeigenbegin;
return true;
} /* if cIterEig < ... */
// numerical problems, ignore them and try again
/* Addition des letzten minEW auf die Diagonale von C */
/* Add the last known good eigen value to the diagonal of C */
double summand = lastGoodMinimumEigenValue * exp((double) tries);
for (unsigned i = 0; i < p.n; ++i)
C[i][i] += summand;
} /* for iEigenCalcVers */
return false;
}
};
CMAState::CMAState(const CMAParams& params, const std::vector<double>& initial_point, const double initial_sigma)
: pimpl(new CMAStateImpl(params, initial_point, initial_sigma)) {}
CMAState::~CMAState() { delete pimpl; }
CMAState::CMAState(const CMAState& that) : pimpl(new CMAStateImpl(*that.pimpl )) {}
CMAState& CMAState::operator=(const CMAState& that) { *pimpl = *that.pimpl; return *this; }
void CMAState::sample(vector<double>& v) const { pimpl->sample(v); }
void CMAState::reestimate(const vector<const vector<double>* >& population, double muBest, double muWorst) { pimpl->reestimate(population, muBest, muWorst); }
bool CMAState::updateEigenSystem(unsigned max_tries, unsigned max_iters) { return pimpl->updateEigenSystem(max_tries, max_iters); }
} // namespace eo

78
eo/src/es/CMAState.h Normal file
View file

@ -0,0 +1,78 @@
/*
* C++ification of Nikolaus Hansen's original C-source code for the
* CMA-ES.
*
* Copyright (C) 1996, 2003, Nikolaus Hansen
* (C) 2005, Maarten Keijzer
*
* License: LGPL (see source file)
*
*/
#ifndef CMASTATE_H_
#define CMASTATE_H_
#include <vector>
#include <valarray>
namespace eo {
class CMAStateImpl;
class CMAParams;
class CMAState {
CMAStateImpl* pimpl; /* pointer to implementation, hidden in source file */
public:
CMAState(const CMAParams&, const std::vector<double>& initial_point, const double initial_sigma = 1.0);
~CMAState();
CMAState(const CMAState&);
CMAState& operator=(const CMAState&);
/**
* sample a vector from the distribution
*
* If the sample is not to your liking (i.e., not within bounds)
* you can do one of two things:
*
* a) Call sample again
* b) multiply the entire vector with a number between -1 and 1
*
* Do not modify the sample in any other way as this will invalidate the
* internal consistency of the system.
*
* A final approach is to copy the sample and modify the copy externally (in the evaluation function)
* and possibly add a penalty depending on the size of the modification.
*
*/
void sample(std::vector<double>& v) const;
/**
* Reestimate covariance matrix and other internal parameters
* Does NOT update the eigen system (call that seperately)
*
* Needs a population of mu individuals, sorted on fitness, plus
*
* muBest: the best fitness in the population
* muWorst: the worst fitness in the population
*/
void reestimate(const std::vector<const std::vector<double>* >& sorted_population, double muBest, double muWorst);
/**
* call this function after reestimate in order to update the eigen system
* It is a seperate call to allow the user to periodically skip this expensive step
*
* max_iters = 0 implies 30 * N iterations
*
* If after max_tries still no numerically sound eigen system is constructed,
* the function returns false
*/
bool updateEigenSystem(unsigned max_tries = 1, unsigned max_iters = 0);
};
} // namespace eo
#endif

56
eo/src/es/CMakeLists.txt Normal file
View file

@ -0,0 +1,56 @@
######################################################################################
### 1) Include the sources
######################################################################################
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
######################################################################################
### 2) Define the es and cma targets
######################################################################################
SET(ES_LIB_OUTPUT_PATH ${EO_BINARY_DIR}/lib)
SET(CMA_LIB_OUTPUT_PATH ${EO_BINARY_DIR}/lib)
SET(LIBRARY_OUTPUT_PATH ${ES_LIB_OUTPUT_PATH}) # the same output for the two libs
SET(ES_SOURCES
make_algo_scalar_es.cpp
make_algo_scalar_real.cpp
make_checkpoint_es.cpp
make_checkpoint_real.cpp
make_continue_es.cpp
make_continue_real.cpp
make_genotype_es.cpp
make_genotype_real.cpp
make_op_es.cpp
make_op_real.cpp
make_pop_es.cpp
make_pop_real.cpp
make_run_es.cpp
make_run_real.cpp
)
SET(CMA_SOURCES
eig.cpp
CMAState.cpp
CMAParams.cpp
)
ADD_LIBRARY(es STATIC ${ES_SOURCES})
INSTALL(TARGETS es ARCHIVE DESTINATION local/${LIB} COMPONENT libraries)
ADD_LIBRARY(cma STATIC ${CMA_SOURCES})
INSTALL(TARGETS cma ARCHIVE DESTINATION local/${LIB} COMPONENT libraries)
######################################################################################
### 3) Optionnal
######################################################################################
SET(ES_VERSION ${GLOBAL_VERSION})
SET_TARGET_PROPERTIES(es PROPERTIES VERSION "${ES_VERSION}")
SET(CMA_VERSION ${GLOBAL_VERSION})
SET_TARGET_PROPERTIES(cma PROPERTIES VERSION "${CMA_VERSION}")
######################################################################################

18
eo/src/es/ChangeLog Normal file
View file

@ -0,0 +1,18 @@
2006-12-01 Jochen Küpper <jochen@fhi-berlin.mpg.de>
* Makefile.am: Add missing CMA header for distribution.
2006-11-16 Jochen Küpper <jochen@fhi-berlin.mpg.de>
* make_genotype_real.h (eoEsChromInit): Rewrite vecSigmaInit-handling:
If sigmaInit is relative (%), do not read vecSigmaInit. Otherwise
always use vecSigmaInit with default all values of sigmaInit.
* eoEsChromInit.h (class eoEsChromInit): Take const-reference to sigma-vector.
include <cassert>
* Local Variables:
* coding: iso-8859-1
* mode: flyspell
* fill-column: 80
* End:

258
eo/src/es/eig.cpp Normal file
View file

@ -0,0 +1,258 @@
/*
* C++ification of Nikolaus Hansen's original C-source code for the
* CMA-ES. These are the eigenvector calculations
*
* C++-ificiation performed by Maarten Keijzer (C) 2005. Licensed under
* the LGPL. Original copyright of Nikolaus Hansen can be found below
*
* This algorithm is held almost completely intact. Some other datatypes are used,
* but hardly any code has changed
*
*/
/* --------------------------------------------------------- */
/* --------------------------------------------------------- */
/* --- File: cmaes.c -------- Author: Nikolaus Hansen --- */
/* --------------------------------------------------------- */
/*
* CMA-ES for non-linear function minimization.
*
* Copyright (C) 1996, 2003 Nikolaus Hansen.
* e-mail: hansen@bionik.tu-berlin.de
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later
* version (see http://www.gnu.org/copyleft/lesser.html).
*
* 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.
*
* */
/* --- Changes : ---
* 03/03/21: argument const double *rgFunVal of
* cmaes_ReestimateDistribution() was treated incorrectly.
* 03/03/29: restart via cmaes_resume_distribution() implemented.
* 03/03/30: Always max std dev / largest axis is printed first.
* 03/08/30: Damping is adjusted for large mueff.
* 03/10/30: Damping is adjusted for large mueff always.
* 04/04/22: Cumulation time and damping for step size adjusted.
* No iniphase but conditional update of pc.
* Version 2.23.
* */
#include "eig.h"
using namespace std;
/* ========================================================= */
/*
Householder Transformation einer symmetrischen Matrix
auf tridiagonale Form.
-> n : Dimension
-> ma : symmetrische nxn-Matrix
<- ma : Transformationsmatrix (ist orthogonal):
Tridiag.-Matrix == <-ma * ->ma * (<-ma)^t
<- diag : Diagonale der resultierenden Tridiagonalmatrix
<- neben[0..n-1] : Nebendiagonale (==1..n-1) der res. Tridiagonalmatrix
*/
static void
Householder( int N, square_matrix& ma, valarray<double>& diag, double* neben)
{
double epsilon;
int i, j, k;
double h, sum, tmp, tmp2;
for (i = N-1; i > 0; --i)
{
h = 0.0;
if (i == 1)
neben[i] = ma[i][i-1];
else
{
for (k = i-1, epsilon = 0.0; k >= 0; --k)
epsilon += fabs(ma[i][k]);
if (epsilon == 0.0)
neben[i] = ma[i][i-1];
else
{
for(k = i-1, sum = 0.0; k >= 0; --k)
{ /* i-te Zeile von i-1 bis links normieren */
ma[i][k] /= epsilon;
sum += ma[i][k]*ma[i][k];
}
tmp = (ma[i][i-1] > 0) ? -sqrt(sum) : sqrt(sum);
neben[i] = epsilon*tmp;
h = sum - ma[i][i-1]*tmp;
ma[i][i-1] -= tmp;
for (j = 0, sum = 0.0; j < i; ++j)
{
ma[j][i] = ma[i][j]/h;
tmp = 0.0;
for (k = j; k >= 0; --k)
tmp += ma[j][k]*ma[i][k];
for (k = j+1; k < i; ++k)
tmp += ma[k][j]*ma[i][k];
neben[j] = tmp/h;
sum += neben[j] * ma[i][j];
} /* for j */
sum /= 2.*h;
for (j = 0; j < i; ++j)
{
neben[j] -= ma[i][j]*sum;
tmp = ma[i][j];
tmp2 = neben[j];
for (k = j; k >= 0; --k)
ma[j][k] -= (tmp*neben[k] + tmp2*ma[i][k]);
} /* for j */
} /* else epsilon */
} /* else i == 1 */
diag[i] = h;
} /* for i */
diag[0] = 0.0;
neben[0] = 0.0;
for (i = 0; i < N; ++i)
{
if(diag[i] != 0.0)
for (j = 0; j < i; ++j)
{
for (k = i-1, tmp = 0.0; k >= 0; --k)
tmp += ma[i][k] * ma[k][j];
for (k = i-1; k >= 0; --k)
ma[k][j] -= tmp*ma[k][i];
} /* for j */
diag[i] = ma[i][i];
ma[i][i] = 1.0;
for (k = i-1; k >= 0; --k)
ma[k][i] = ma[i][k] = 0.0;
} /* for i */
}
/*
QL-Algorithmus mit implizitem Shift, zur Berechnung von Eigenwerten
und -vektoren einer symmetrischen Tridiagonalmatrix.
-> n : Dimension.
-> diag : Diagonale der Tridiagonalmatrix.
-> neben[0..n-1] : Nebendiagonale (==0..n-2), n-1. Eintrag beliebig
-> mq : Matrix output von Householder()
-> maxIt : maximale Zahl der Iterationen
<- diag : Eigenwerte
<- neben : Garbage
<- mq : k-te Spalte ist normalisierter Eigenvektor zu diag[k]
*/
static int
QLalgo( int N, valarray<double>& diag, square_matrix& mq,
int maxIter, double* neben)
{
int i, j, k, kp1, l;
double tmp, diff, cneben, c1, c2, p;
int iter;
neben[N-1] = 0.0;
for (i = 0, iter = 0; i < N && iter < maxIter; ++i)
do /* while j != i */
{
for (j = i; j < N-1; ++j)
{
tmp = fabs(diag[j]) + fabs(diag[j+1]);
if (fabs(neben[j]) + tmp == tmp)
break;
}
if (j != i)
{
if (++iter > maxIter) return maxIter-1;
diff = (diag[i+1]-diag[i])/neben[i]/2.0;
if (diff >= 0)
diff = diag[j] - diag[i] +
neben[i] / (diff + sqrt(diff * diff + 1.0));
else
diff = diag[j] - diag[i] +
neben[i] / (diff - sqrt(diff * diff + 1.0));
c2 = c1 = 1.0;
p = 0.0;
for (k = j-1; k >= i; --k)
{
kp1 = k + 1;
tmp = c2 * neben[k];
cneben = c1 * neben[k];
if (fabs(tmp) >= fabs(diff))
{
c1 = diff / tmp;
c2 = 1. / sqrt(c1*c1 + 1.0);
neben[kp1] = tmp / c2;
c1 *= c2;
}
else
{
c2 = tmp / diff;
c1 = 1. / sqrt(c2*c2 + 1.0);
neben[kp1] = diff / c1;
c2 *= c1;
} /* else */
tmp = (diag[k] - diag[kp1] + p) * c2 + 2.0 * c1 * cneben;
diag[kp1] += tmp * c2 - p;
p = tmp * c2;
diff = tmp * c1 - cneben;
for (l = N-1; l >= 0; --l) /* TF-Matrix Q */
{
tmp = mq[l][kp1];
mq[l][kp1] = c2 * mq[l][k] + c1 * tmp;
mq[l][k] = c1 * mq[l][k] - c2 * tmp;
} /* for l */
} /* for k */
diag[i] -= p;
neben[i] = diff;
neben[j] = 0.0;
} /* if */
} while (j != i);
return iter;
} /* QLalgo() */
/* ========================================================= */
/*
Calculating eigenvalues and vectors.
Input:
N: dimension.
C: lower_triangular NxN-matrix.
niter: number of maximal iterations for QL-Algorithm.
rgtmp: N+1-dimensional vector for temporal use.
Output:
diag: N eigenvalues.
Q: Columns are normalized eigenvectors.
return: number of iterations in QL-Algorithm.
*/
namespace eo {
int
eig( int N, const lower_triangular_matrix& C, valarray<double>& diag, square_matrix& Q,
int niter)
{
int ret;
int i, j;
if (niter == 0) niter = 30*N;
for (i=0; i < N; ++i)
{
vector<double>::const_iterator row = C[i];
for (j = 0; j <= i; ++j)
Q[i][j] = Q[j][i] = row[j];
}
double* rgtmp = new double[N+1];
Householder( N, Q, diag, rgtmp);
ret = QLalgo( N, diag, Q, niter, rgtmp+1);
delete [] rgtmp;
return ret;
}
} // namespace eo

25
eo/src/es/eig.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef EIG_H__
#define EIG_H__
#include <matrices.h>
#include <valarray>
namespace eo {
/* ========================================================= */
/*
Calculating eigenvalues and vectors.
Input:
N: dimension.
C: lower_triangular NxN-matrix.
niter: number of maximal iterations for QL-Algorithm.
Output:
diag: N eigenvalues.
Q: Columns are normalized eigenvectors.
return: number of iterations in QL-Algorithm.
*/
extern int eig( int N, const lower_triangular_matrix& C, std::valarray<double>& diag, square_matrix& Q,
int niter = 0);
} // namespace eo
#endif

78
eo/src/es/eoCMABreed.h Normal file
View file

@ -0,0 +1,78 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; fill-column: 80; -*-
//-----------------------------------------------------------------------------
// eoCMABreed
// (c) Maarten Keijzer 2005
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//-----------------------------------------------------------------------------
#ifndef _EOCMABREED_H
#define _EOCMABREED_H
#include <eoBreed.h>
#include <eoVector.h>
#include <es/CMAState.h>
#include <algorithm>
/// @todo handle bounds
template <class FitT>
class eoCMABreed : public eoBreed< eoVector<FitT, double> > {
eo::CMAState& state;
unsigned lambda;
typedef eoVector<FitT, double> EOT;
public:
eoCMABreed(eo::CMAState& state_, unsigned lambda_) : state(state_), lambda(lambda_) {}
void operator()(const eoPop<EOT>& parents, eoPop<EOT>& offspring) {
// two temporary arrays of pointers to store the sorted population
std::vector<const EOT*> sorted(parents.size());
// mu stores population as vector (instead of eoPop)
std::vector<const std::vector<double>* > mu(parents.size());
parents.sort(sorted);
for (unsigned i = 0; i < sorted.size(); ++i) {
mu[i] = static_cast< const std::vector<double>* >( sorted[i] );
}
// learn
state.reestimate(mu, sorted[0]->fitness(), sorted.back()->fitness());
if (!state.updateEigenSystem(10)) {
std::cerr << "No good eigensystem found" << std::endl;
}
// generate
offspring.resize(lambda);
for (unsigned i = 0; i < lambda; ++i) {
state.sample( static_cast< std::vector<double>& >( offspring[i] ));
offspring[i].invalidate();
}
}
};
#endif

54
eo/src/es/eoCMAInit.h Normal file
View file

@ -0,0 +1,54 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; fill-column: 80; -*-
//-----------------------------------------------------------------------------
// eoCMAInit
// (c) Maarten Keijzer 2005
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
marc.schoenauer@polytechnique.fr
http://eeaax.cmap.polytchnique.fr/
*/
//-----------------------------------------------------------------------------
#ifndef _EOCMAINIT_H
#define _EOCMAINIT_H
#include <eoInit.h>
#include <eoVector.h>
#include <es/CMAState.h>
/// @todo handle bounds
template <class FitT>
class eoCMAInit : public eoInit< eoVector<FitT, double> > {
const eo::CMAState& state;
typedef eoVector<FitT, double> EOT;
public:
eoCMAInit(const eo::CMAState& state_) : state(state_) {}
void operator()(EOT& v) {
state.sample(static_cast<std::vector<double>& >(v));
v.invalidate();
}
};
#endif

208
eo/src/es/eoEsChromInit.h Normal file
View file

@ -0,0 +1,208 @@
//
/* (c) Maarten Keijzer 2000, GeNeura Team, 1998 - EEAAX 1999
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this library; if not, write to the Free Software Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: http://eodev.sourceforge.net
todos@geneura.ugr.es, http://geneura.ugr.es
Marc.Schoenauer@polytechnique.fr
mak@dhi.dk
*/
#ifndef _eoEsChromInit_H
#define _eoEsChromInit_H
#include <algorithm>
#include <cassert>
#include <cmath>
#include <vector>
#include <es/eoRealInitBounded.h>
#include <es/eoEsSimple.h>
#include <es/eoEsStdev.h>
#include <es/eoEsFull.h>
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif
/** Random Es-chromosome initializer (therefore derived from eoInit)
@ingroup Real
@ingroup Initializators
This class can initialize four types of real-valued genotypes thanks
to tempate specialization of private method create:
- eoReal just an eoVector<double>
- eoEsSimple + one self-adapting single sigma for all variables
- eoEsStdev a whole std::vector of self-adapting sigmas
- eoEsFull a full self-adapting correlation matrix
@see eoReal eoEsSimple eoEsStdev eoEsFull eoInit
*/
template <class EOT>
class eoEsChromInit : public eoRealInitBounded<EOT>
{
public:
using eoRealInitBounded<EOT>::size;
using eoRealInitBounded<EOT>::theBounds;
typedef typename EOT::Fitness FitT;
/** Constructor
@param _bounds bounds for uniform initialization
@param _sigma initial value for the stddev
@param _to_scale wether sigma should be multiplied by the range of each variable
added December 2004 - MS (together with the whole comment :-)
*/
eoEsChromInit(eoRealVectorBounds& _bounds, double _sigma = 0.3, bool _to_scale=false)
: eoRealInitBounded<EOT>(_bounds)
{
// a bit of pre-computations, to save time later (even if some are useless)
//
// first, in the case of one unique sigma
// sigma is scaled by the average range (if that means anything!)
if (_to_scale)
{
double scaleUnique = 0;
for (unsigned i=0; i<size(); i++)
scaleUnique += theBounds().range(i);
scaleUnique /= size();
uniqueSigma = _sigma * scaleUnique;
}
else
uniqueSigma = _sigma;
// now the case of a vector of sigmas first allocate space according
// to the size of the bounds (see eoRealInitBounded)
vecSigma.resize(size());
// each sigma is scaled by the range of the corresponding variable
for(unsigned i=0; i<size(); i++)
if(_to_scale)
vecSigma[i] = _sigma * theBounds().range(i);
else
vecSigma[i] = _sigma;
}
/** Constructor
@overload
Specify individual initial sigmas for each variable.
@param _bounds bounds for uniform initialization
@param _vecSigma initial value for the stddev
*/
eoEsChromInit(eoRealVectorBounds& _bounds, const std::vector<double>& _vecSigma)
: eoRealInitBounded<EOT>(_bounds), uniqueSigma(_vecSigma[0]), vecSigma(_vecSigma)
{
assert(_bounds.size() == size());
assert(_vecSigma.size() == size());
}
void operator()(EOT& _eo)
{
eoRealInitBounded<EOT>::operator()(_eo);
create_self_adapt(_eo);
_eo.invalidate();
}
private:
/** Create intializer
No adaptive mutation at all
*/
void create_self_adapt(eoReal<FitT>&)
{}
/** Create intializer
@overload
Adaptive mutation through a unique sigma
*/
void create_self_adapt(eoEsSimple<FitT>& result)
{
// pre-computed in the Ctor
result.stdev = uniqueSigma;
}
/** Create intializer
@overload
Adaptive mutation through a std::vector of sigmas
@todo Should we scale sigmas to the corresponding object variable range?
*/
void create_self_adapt(eoEsStdev<FitT>& result)
{
// pre-computed in the constructor
result.stdevs = vecSigma;
}
/** Create intializer
@overload
Adaptive mutation through a whole correlation matrix
*/
void create_self_adapt(eoEsFull<FitT>& result)
{
// first the stdevs (pre-computed in the Ctor)
result.stdevs = vecSigma;
unsigned int theSize = size();
// nb of rotation angles: N*(N-1)/2 (in general!)
result.correlations.resize(theSize*(theSize - 1) / 2);
for (unsigned i=0; i<result.correlations.size(); ++i)
{
// uniform in [-PI, PI)
result.correlations[i] = rng.uniform(2 * M_PI) - M_PI;
}
}
/** Initial value in case of a unique sigma */
double uniqueSigma;
/** Initial values in case of a vector of sigmas */
std::vector<double> vecSigma;
};
#endif
// Local Variables:
// coding: iso-8859-1
// mode:C++
// c-file-style: "Stroustrup"
// comment-column: 35
// fill-column: 80
// End:

85
eo/src/es/eoEsFull.h Normal file
View file

@ -0,0 +1,85 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoEsFull.h
// (c) GeNeura Team, 2000 - EEAAX 1999 - Maarten Keijzer 2000
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
Marc.Schoenauer@polytechnique.fr
mak@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef _eoEsFull_h
#define _eoEsFull_h
#include <eoVector.h>
/**
\ingroup Real
The most complex evolutionary strategy representation. Co-evolving mutation
rates and correlated mutations.
*/
template <class Fit>
class eoEsFull : public eoVector<Fit, double>
{
public:
using eoVector<Fit, double>::size;
typedef double Type;
eoEsFull(void) : eoVector<Fit, double>() {}
virtual std::string className(void) const { return "eoEsFull"; }
void printOn(std::ostream& os) const
{
eoVector<Fit,double>::printOn(os);
os << ' ';
std::copy(stdevs.begin(), stdevs.end(), std::ostream_iterator<double>(os, " "));
os << ' ';
std::copy(correlations.begin(), correlations.end(), std::ostream_iterator<double>(os, " "));
os << ' ';
}
void readFrom(std::istream& is)
{
eoVector<Fit,double>::readFrom(is);
stdevs.resize(size());
unsigned i;
for (i = 0; i < size(); ++i)
is >> stdevs[i];
correlations.resize(size()*(size() - 1) / 2);
for (i = 0; i < correlations.size(); ++i)
is >> correlations[i];
}
std::vector<double> stdevs;
std::vector<double> correlations;
};
#endif

152
eo/src/es/eoEsGlobalXover.h Normal file
View file

@ -0,0 +1,152 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoEsGlobalXover.h : ES global crossover
// (c) Marc Schoenauer 2001
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: marc.schoenauer@polytechnique.fr http://eeaax.cmap.polytchnique.fr/
*/
//-----------------------------------------------------------------------------
#ifndef _eoEsGlobalXover_H
#define _eoEsGlobalXover_H
#include <utils/eoRNG.h>
#include <es/eoEsSimple.h>
#include <es/eoEsStdev.h>
#include <es/eoEsFull.h>
#include <eoGenOp.h>
// needs a selector - here random
#include <eoRandomSelect.h>
/** Global crossover operator for ES genotypes.
* Uses some Atom crossovers to handle both the object variables
* and the mutation strategy parameters
*
* @ingroup Real
* @ingroup Variators
*/
template<class EOT>
class eoEsGlobalXover: public eoGenOp<EOT>
{
public:
typedef typename EOT::Fitness FitT;
/**
* (Default) Constructor.
*/
eoEsGlobalXover(eoBinOp<double> & _crossObj, eoBinOp<double> & _crossMut) :
crossObj(_crossObj), crossMut(_crossMut) {}
/// The class name. Used to display statistics
virtual std::string className() const { return "eoEsGlobalXover"; }
/// The TOTAL number of offspring (here = nb of parents modified in place)
unsigned max_production(void) { return 1; }
/**
* modifies one parents in the populator
* using 2 new parents for each component!
*
* @param _plop a POPULATOR (not a simple population)
*/
void apply(eoPopulator<EOT>& _plop)
{
// First, select as many parents as you will have offspring
EOT& parent = *_plop; // select the first parent
// first, the object variables
for (unsigned i=0; i<parent.size(); i++)
{
// get extra parents - use private selector
// _plop.source() is the eoPop<EOT> used by _plop to get parents
const EOT& realParent1 = sel(_plop.source());
const EOT& realParent2 = sel(_plop.source());
parent[i] = realParent1[i];
crossObj(parent[i], realParent2[i]); // apply eoBinOp
}
// then the self-adaptation parameters
cross_self_adapt(parent, _plop.source());
// dont' forget to invalidate
parent.invalidate();
}
private:
/** Method for cross self-adaptation parameters
Specialization for eoEsSimple.
*/
void cross_self_adapt(eoEsSimple<FitT> & _parent, const eoPop<eoEsSimple<FitT> >& _pop)
{
const EOT& realParent1 = sel(_pop);
const EOT& realParent2 = sel(_pop);
_parent.stdev = realParent1.stdev;
crossMut(_parent.stdev, realParent2.stdev); // apply eoBinOp
}
/** Method for cross self-adaptation parameters
Specialization for eoEsStdev.
*/
void cross_self_adapt(eoEsStdev<FitT> & _parent, const eoPop<eoEsStdev<FitT> >& _pop)
{
for (unsigned i=0; i<_parent.size(); i++)
{
const EOT& realParent1 = sel(_pop);
const EOT& realParent2 = sel(_pop);
_parent.stdevs[i] = realParent1.stdevs[i];
crossMut(_parent.stdevs[i], realParent2.stdevs[i]); // apply eoBinOp
}
}
/** Method for cross self-adaptation parameters
Specialization for eoEsFull.
*/
void cross_self_adapt(eoEsFull<FitT> & _parent, const eoPop<eoEsFull<FitT> >& _pop)
{
unsigned i;
// the StDev
for (i=0; i<_parent.size(); i++)
{
const EOT& realParent1 = sel(_pop);
const EOT& realParent2 = sel(_pop);
_parent.stdevs[i] = realParent1.stdevs[i];
crossMut(_parent.stdevs[i], realParent2.stdevs[i]); // apply eoBinOp
}
// the roataion angles
for (i=0; i<_parent.correlations.size(); i++)
{
const EOT& realParent1 = sel(_pop);
const EOT& realParent2 = sel(_pop);
_parent.correlations[i] = realParent1.correlations[i];
crossMut(_parent.correlations[i], realParent2.correlations[i]); // apply eoBinOp
}
}
// the data
eoRandomSelect<EOT> sel;
eoBinOp<double> & crossObj;
eoBinOp<double> & crossMut;
};
#endif

287
eo/src/es/eoEsMutate.h Normal file
View file

@ -0,0 +1,287 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; fill-column: 80; -*-
//-----------------------------------------------------------------------------
// eoESMute.h : ES mutation
// (c) Maarten Keijzer 2000 & GeNeura Team, 1998 for the EO part
// Th. Baeck 1994 and EEAAX 1999 for the ES part
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
marc.schoenauer@polytechnique.fr
http://eeaax.cmap.polytchnique.fr/
*/
//-----------------------------------------------------------------------------
#ifndef _EOESMUTATE_H
#define _EOESMUTATE_H
#include <cmath>
#include <eoInit.h>
#include <eoOp.h>
#include <es/eoEsMutationInit.h>
#include <es/eoEsSimple.h>
#include <es/eoEsStdev.h>
#include <es/eoEsFull.h>
#include <utils/eoRealBounds.h>
#include <utils/eoRNG.h>
#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795
#endif
/** ES-style mutation in the large
@ingroup Real
@ingroup Variators
Obviously, valid only for eoES*. It is currently valid for three types
of ES chromosomes:
- eoEsSimple: Exactly one stdandard-deviation
- eoEsStdev: As many standard deviations as object variables
- eoEsFull: The whole guacemole: correlations, stdevs and object variables
Each of these three variant has it's own operator() in eoEsMutate and
intialization is also split into three cases (that share some commonalities)
*/
template <class EOT>
class eoEsMutate : public eoMonOp< EOT >
{
public:
/** Fitness-type */
typedef typename EOT::Fitness FitT;
/** Initialization.
@param _init Proxy class for initializating the three parameters
eoEsMutate needs
@param _bounds Bounds for the objective variables
*/
eoEsMutate(eoEsMutationInit& _init, eoRealVectorBounds& _bounds) : bounds(_bounds)
{
init(EOT(), _init); // initialize on actual type used
}
/** @brief Virtual Destructor */
virtual ~eoEsMutate() {};
/** Classname.
Inherited from eoObject @see eoObject
@return Name of class.
*/
virtual std::string className() const {return "eoESMutate";};
/** Mutate eoEsSimple
@param _eo Individual to mutate.
*/
virtual bool operator()( eoEsSimple<FitT>& _eo)
{
_eo.stdev *= exp(TauLcl * rng.normal());
if (_eo.stdev < stdev_eps)
_eo.stdev = stdev_eps;
// now apply to all
for (unsigned i = 0; i < _eo.size(); ++i)
{
_eo[i] += _eo.stdev * rng.normal();
}
bounds.foldsInBounds(_eo);
return true;
}
/** Standard mutation in ES
@overload
Standard mutation of object variables and standard deviations in ESs.
If there are fewer different standard deviations available than the
dimension of the objective function requires, the last standard deviation is
responsible for ALL remaining object variables.
@param _eo Individual to mutate.
@see
Schwefel 1977: Numerische Optimierung von Computer-Modellen mittels der
Evolutionsstrategie, pp. 165 ff.
*/
virtual bool operator()( eoEsStdev<FitT>& _eo )
{
double global = TauGlb * rng.normal();
for (unsigned i = 0; i < _eo.size(); i++)
{
double stdev = _eo.stdevs[i];
stdev *= exp( global + TauLcl * rng.normal() );
if (stdev < stdev_eps)
stdev = stdev_eps;
_eo.stdevs[i] = stdev;
_eo[i] += stdev * rng.normal();
}
bounds.foldsInBounds(_eo);
return true;
}
/** Correlated mutations in ES
@overload
Mutation of object variables, standard deviations, and their correlations in
ESs.
@param _eo Individual to mutate.
@see
- H.-P. Schwefel: Internal Report of KFA Juelich, KFA-STE-IB-3/80, p. 43, 1980.
- G. Rudolph: Globale Optimierung mit parallelen Evolutionsstrategien,
Diploma Thesis, University of Dortmund, 1990.
*/
virtual bool operator()( eoEsFull<FitT> & _eo )
// Code originally from Thomas Bäck
{
// First: mutate standard deviations (as for eoEsStdev<FitT>).
double global = TauGlb * rng.normal();
unsigned i;
for (i = 0; i < _eo.size(); i++)
{
double stdev = _eo.stdevs[i];
stdev *= exp( global + TauLcl*rng.normal() );
if (stdev < stdev_eps)
stdev = stdev_eps;
_eo.stdevs[i] = stdev;
}
// Mutate rotation angles.
for (i = 0; i < _eo.correlations.size(); i++)
{
_eo.correlations[i] += TauBeta * rng.normal();
if ( fabs(_eo.correlations[i]) > M_PI )
{
_eo.correlations[i] -= M_PI * (int) (_eo.correlations[i]/M_PI) ;
}
}
// Perform correlated mutations.
unsigned k, n1, n2;
double d1,d2, S, C;
std::vector<double> VarStp(_eo.size());
for (i = 0; i < _eo.size(); i++)
VarStp[i] = _eo.stdevs[i] * rng.normal();
unsigned nq = _eo.correlations.size() - 1;
for (k = 0; k < _eo.size()-1; k++)
{
n1 = _eo.size() - k - 1;
n2 = _eo.size() - 1;
for (i = 0; i < k; i++)
{
d1 = VarStp[n1];
d2 = VarStp[n2];
S = sin( _eo.correlations[nq] );
C = cos( _eo.correlations[nq] );
VarStp[n2] = d1 * S + d2 * C;
VarStp[n1] = d1 * C - d2 * S;
n2--;
nq--;
}
}
for (i = 0; i < _eo.size(); i++)
_eo[i] += VarStp[i];
bounds.foldsInBounds(_eo);
return true;
}
private :
/** Initialization of simple ES */
void init(eoEsSimple<FitT>, eoEsMutationInit& _init)
{
unsigned size = bounds.size();
TauLcl = _init.TauLcl();
TauLcl /= sqrt(2*(double) size);
std::cout << "Init<eoEsSimple>: tau local " << TauLcl << std::endl;
}
/** Initialization of standard ES
@overload
*/
void init(eoEsStdev<FitT>, eoEsMutationInit& _init)
{
unsigned size = bounds.size();
TauLcl = _init.TauLcl();
TauGlb = _init.TauGlb();
// renormalization
TauLcl /= sqrt( 2.0 * sqrt(double(size)) );
TauGlb /= sqrt( 2.0 * double(size) );
std::cout << "Init<eoStDev>: tau local " << TauLcl << " et global " << TauGlb << std::endl;
}
/** Initialization of full ES
@overload
*/
void init(eoEsFull<FitT>, eoEsMutationInit& _init)
{
init(eoEsStdev<FitT>(), _init);
TauBeta = _init.TauBeta();
std::cout << "Init<eoEsFull>: tau local " << TauLcl << " et global " << TauGlb << std::endl;
}
/** Local factor for mutation of std deviations */
double TauLcl;
/** Global factor for mutation of std deviations */
double TauGlb;
/** Factor for mutation of correlation parameters */
double TauBeta;
/** Bounds of parameters */
eoRealVectorBounds& bounds;
/** Minimum stdev.
If you let the step-size go to 0, self-adaptation stops, therefore we give a
lower bound. The actual value used is somewhat arbitrary and the is no
theoretical reasoning known for it (Sep 2005).
The code that we have in EO is a port from a C code that Thomas Bäck kindly
donated to the community some years ago. It has been modified by Marc
Schoenauer for inclusion in EvolC, than by Maarten Keijzer into EO. The
exact value was adjusted based on practice.
Removing this doesn't work well, but it was never tried to figure out what
the best value would be.
*/
static const double stdev_eps;
};
// Minimum value of stdevs, see declaration for details.
template <class EOT>
const double eoEsMutate<EOT>::stdev_eps = 1.0e-40;
#endif

View file

@ -0,0 +1,122 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; fill-column: 80 -*-
//-----------------------------------------------------------------------------
// eoEsMutationInit.h
// (c) GeNeura Team, 1998 - EEAAX 1999 - Maarten Keijzer 2000
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
Marc.Schoenauer@polytechnique.fr
mak@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef _eoEsMutationInit_h
#define _eoEsMutationInit_h
#include <utils/eoParser.h>
/** Initialize Mutation operator
@ingroup Real
@ingroup Variators
Proxy class that is used for initializing the mutation operator. It provides an
interface between eoEsMutate and the abstract parameterLoader. It also provides
the names for the parameters in this class as virtual protected member
functions.
If you have more than a single ES in a project that need different names in the
configuration files, you might consider overriding this class to change the
names.
@see eoEsMutate
*/
class eoEsMutationInit
{
public :
/** Constructor
@param _parser Parser to read parameters from.
@param _section Parser section for \f$\tau\f$-parameters.
*/
eoEsMutationInit(eoParser& _parser,
std::string _section="ES mutation parameters" ) :
parser(_parser), repSection(_section),
TauLclParam(0), TauGlbParam(0), TauBetaParam(0) {}
/** Virtual destructor */
virtual ~eoEsMutationInit() {}
/** local tau */
double TauLcl(void)
{
if (TauLclParam == 0)
{
TauLclParam = &parser.getORcreateParam(1.0, TauLclName(),
"Local Tau (before normalization)",
TauLclShort(), section());
}
return TauLclParam->value();
}
/** global tau */
double TauGlb(void)
{
if (TauGlbParam == 0)
{
TauGlbParam = &parser.getORcreateParam(1.0, TauGlbName(),
"Global Tau (before normalization)",
TauGlbShort(), section());
}
return TauGlbParam->value();
}
/** correlation's tau */
double TauBeta(void)
{
if (TauBetaParam == 0)
{
TauBetaParam = &parser.getORcreateParam(0.0873, TauBetaName(),
"Beta", TauBetaShort(), section());
}
return TauBetaParam->value();
}
protected :
virtual std::string section(void) { return repSection; }
virtual std::string TauLclName(void) const { return "TauLoc"; }
virtual char TauLclShort(void) const { return 'l'; }
virtual std::string TauGlbName(void) const { return "TauGlob"; }
virtual char TauGlbShort(void) const { return 'g'; }
virtual std::string TauBetaName(void) const { return "Beta"; }
virtual char TauBetaShort(void) const { return 'b'; }
private:
eoParser& parser;
std::string repSection;
eoValueParam<double>* TauLclParam;
eoValueParam<double>* TauGlbParam;
eoValueParam<double>* TauBetaParam;
};
#endif

77
eo/src/es/eoEsSimple.h Normal file
View file

@ -0,0 +1,77 @@
/* (c) GeNeura Team, 2000 - EEAAX 1999, Maarten Keijzer 2000
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this library; if not, write to the Free Software Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: http://eodev.sourceforge.net
todos@geneura.ugr.es, http://geneura.ugr.es
Marc.Schoenauer@polytechnique.fr
mak@dhi.dk
*/
#ifndef _eoEsSimple_h
#define _eoEsSimple_h
#include <EO.h>
#include <vector>
#include <eoVector.h>
/** Simple Evolution Strategy
@ingroup Real
One of the more simple evolution strategies, sporting just a single stdeviation
for the entire chromosome. For more advanced versions see also eoEsStdev
eoEsFull
@see eoEsStdev eoEsFull
*/
template <class Fit>
class eoEsSimple : public eoVector<Fit, double>
{
public :
typedef double Type;
eoEsSimple() : eoVector<Fit, double>() {}
virtual std::string className() const { return "eoEsSimple"; }
void printOn(std::ostream& os) const
{
eoVector<Fit,double>::printOn(os);
os << ' ' << stdev << ' ';
}
void readFrom(std::istream& is)
{
eoVector<Fit,double>::readFrom(is);
is >> stdev;
}
double stdev;
};
#endif
// Local Variables:
// coding: iso-8859-1
// mode:C++
// c-file-style: "Stroustrup"
// comment-column: 35
// fill-column: 80
// End:

View file

@ -0,0 +1,123 @@
/** -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoEsLocalXover.h : ES global crossover
// (c) Marc Schoenauer 2001
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: marc.schoenauer@polytechnique.fr http://eeaax.cmap.polytchnique.fr/
*/
//-----------------------------------------------------------------------------
#ifndef _eoEsLocalXover_H
#define _eoEsLocalXover_H
#include <utils/eoRNG.h>
#include <es/eoEsSimple.h>
#include <es/eoEsStdev.h>
#include <es/eoEsFull.h>
#include <eoGenOp.h>
// needs a selector - here random
#include <eoRandomSelect.h>
/** Standard (i.e. eoBinOp) crossover operator for ES genotypes.
* Uses some Atom crossovers to handle both the object variables
* and the mutation strategy parameters
* It is an eoBinOp and has to be wrapped into an eoGenOp before being used
* like the global version
*
* @ingroup Real
* @ingroup Variators
*/
template<class EOT>
class eoEsStandardXover: public eoBinOp<EOT>
{
public:
typedef typename EOT::Fitness FitT;
/**
* (Default) Constructor.
*/
eoEsStandardXover(eoBinOp<double> & _crossObj, eoBinOp<double> & _crossMut) :
crossObj(_crossObj), crossMut(_crossMut) {}
/// The class name. Used to display statistics
virtual std::string className() const { return "eoEsStandardXover"; }
/**
* modifies one parents in the populator
* using a second parent
*/
bool operator()(EOT& _eo1, const EOT& _eo2)
{
bool bLoc=false;
// first, the object variables
for (unsigned i=0; i<_eo1.size(); i++)
{
bLoc |= crossObj(_eo1[i], _eo2[i]); // apply eoBinOp
}
// then the self-adaptation parameters
bLoc |= cross_self_adapt(_eo1, _eo2);
return bLoc;
}
private:
// the method to cross slef-adaptation parameters: need to specialize
bool cross_self_adapt(eoEsSimple<FitT> & _parent1, const eoEsSimple<FitT> & _parent2)
{
return crossMut(_parent1.stdev, _parent2.stdev); // apply eoBinOp
}
bool cross_self_adapt(eoEsStdev<FitT> & _parent1, const eoEsStdev<FitT> & _parent2)
{
bool bLoc=false;
for (unsigned i=0; i<_parent1.size(); i++)
{
bLoc |= crossMut(_parent1.stdevs[i], _parent2.stdevs[i]); // apply eoBinOp
}
return bLoc;
}
bool cross_self_adapt(eoEsFull<FitT> & _parent1, const eoEsFull<FitT> & _parent2)
{
bool bLoc=false;
unsigned i;
// the StDev
for (i=0; i<_parent1.size(); i++)
{
bLoc |= crossMut(_parent1.stdevs[i], _parent2.stdevs[i]); // apply eoBinOp
}
// the roataion angles
for (i=0; i<_parent1.correlations.size(); i++)
{
bLoc |= crossMut(_parent1.correlations[i], _parent2.correlations[i]); // apply eoBinOp
}
return bLoc;
}
// the data
eoRandomSelect<EOT> sel;
eoBinOp<double> & crossObj;
eoBinOp<double> & crossMut;
};
#endif

80
eo/src/es/eoEsStdev.h Normal file
View file

@ -0,0 +1,80 @@
/* (c) GeNeura Team, 2000 - EEAAX 1999 - Maarten Keijzer 2000
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along
with this library; if not, write to the Free Software Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: http://eodev.sourceforge.net
todos@geneura.ugr.es, http://geneura.ugr.es
Marc.Schoenauer@polytechnique.fr
mak@dhi.dk
*/
#ifndef _eoEsStdev_h
#define _eoEsStdev_h
#include <eoVector.h>
/** Evolutionary Strategy with a standard deviation per parameter
Evolutionary strategie style representation, supporting co-evolving
standard deviations.
@ingroup Real
*/
template <class Fit>
class eoEsStdev : public eoVector<Fit, double>
{
public:
using eoVector<Fit, double>::size;
typedef double Type;
eoEsStdev(void) : eoVector<Fit, double>() {}
virtual std::string className(void) const { return "eoEsStdev"; }
void printOn(std::ostream& os) const
{
eoVector<Fit,double>::printOn(os);
os << ' ';
std::copy(stdevs.begin(), stdevs.end(), std::ostream_iterator<double>(os, " "));
os << ' ';
}
void readFrom(std::istream& is)
{
eoVector<Fit,double>::readFrom(is);
stdevs.resize(size());
unsigned i;
for (i = 0; i < size(); ++i)
is >> stdevs[i];
}
std::vector<double> stdevs;
};
#endif
// Local Variables:
// coding: iso-8859-1
// mode:C++
// c-file-style: "Stroustrup"
// comment-column: 35
// fill-column: 80
// End:

View file

@ -0,0 +1,281 @@
// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
//-----------------------------------------------------------------------------
// eoNormalMutation.h
// (c) EEAAX 2001 - Maarten Keijzer 2000
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: Marc.Schoenauer@polytechnique.fr
mak@dhi.dk
*/
//-----------------------------------------------------------------------------
#ifndef eoNormalMutation_h
#define eoNormalMutation_h
//-----------------------------------------------------------------------------
#include <algorithm> // swap_ranges
#include <utils/eoRNG.h>
#include <utils/eoUpdatable.h>
#include <eoEvalFunc.h>
#include <es/eoReal.h>
#include <utils/eoRealBounds.h>
//-----------------------------------------------------------------------------
/** Simple normal mutation of a std::vector of real values.
* The stDev is fixed - but it is passed ans stored as a reference,
* to enable dynamic mutations (see eoOenFithMutation below).
*
* As for the bounds, the values are here folded back into the bounds.
* The other possiblity would be to iterate until we fall inside the bounds -
* but this sometimes takes a long time!!!
*
* @ingroup Real
* @ingroup Variators
*/
template<class EOT> class eoNormalVecMutation: public eoMonOp<EOT>
{
public:
/**
* (Default) Constructor.
* The bounds are initialized with the global object that says: no bounds.
*
* @param _sigma the range for uniform nutation
* @param _p_change the probability to change a given coordinate
*/
eoNormalVecMutation(double _sigma, const double& _p_change = 1.0):
sigma(_sigma), bounds(eoDummyVectorNoBounds), p_change(_p_change) {}
/**
* Constructor with bounds
* @param _bounds an eoRealVectorBounds that contains the bounds
* @param _sigma the range for uniform nutation
* @param _p_change the probability to change a given coordinate
*
* for each component, the sigma is scaled to the range of the bound, if bounded
*/
eoNormalVecMutation(eoRealVectorBounds & _bounds,
double _sigma, const double& _p_change = 1.0):
sigma(_bounds.size(), _sigma), bounds(_bounds), p_change(_p_change)
{
// scale to the range - if any
for (unsigned i=0; i<bounds.size(); i++)
if (bounds.isBounded(i))
sigma[i] *= _sigma*bounds.range(i);
}
/** The class name */
virtual std::string className() const { return "eoNormalVecMutation"; }
/**
* Do it!
* @param _eo The cromosome undergoing the mutation
*/
bool operator()(EOT& _eo)
{
bool hasChanged=false;
for (unsigned lieu=0; lieu<_eo.size(); lieu++)
{
if (rng.flip(p_change))
{
_eo[lieu] += sigma[lieu]*rng.normal();
bounds.foldsInBounds(lieu, _eo[lieu]);
hasChanged = true;
}
}
return hasChanged;
}
private:
std::vector<double> sigma;
eoRealVectorBounds & bounds;
double p_change;
};
/** Simple normal mutation of a std::vector of real values.
* The stDev is fixed - but it is passed ans stored as a reference,
* to enable dynamic mutations (see eoOenFithMutation below).
*
* As for the bounds, the values are here folded back into the bounds.
* The other possiblity would be to iterate until we fall inside the bounds -
* but this sometimes takes a long time!!!
*
* @ingroup Real
* @ingroup Variators
*/
template<class EOT> class eoNormalMutation
: public eoMonOp<EOT>
{
public:
/**
* (Default) Constructor.
* The bounds are initialized with the global object that says: no bounds.
*
* @param _sigma the range for uniform nutation
* @param _p_change the probability to change a given coordinate
*/
eoNormalMutation(double & _sigma, const double& _p_change = 1.0):
sigma(_sigma), bounds(eoDummyVectorNoBounds), p_change(_p_change) {}
/**
* Constructor with bounds
* @param _bounds an eoRealVectorBounds that contains the bounds
* @param _sigma the range for uniform nutation
* @param _p_change the probability to change a given coordinate
*/
eoNormalMutation(eoRealVectorBounds & _bounds,
double _sigma, const double& _p_change = 1.0):
sigma(_sigma), bounds(_bounds), p_change(_p_change) {}
/** The class name */
virtual std::string className() const { return "eoNormalMutation"; }
/**
* Do it!
* @param _eo The cromosome undergoing the mutation
*/
bool operator()(EOT& _eo)
{
bool hasChanged=false;
for (unsigned lieu=0; lieu<_eo.size(); lieu++)
{
if (rng.flip(p_change))
{
_eo[lieu] += sigma*rng.normal();
bounds.foldsInBounds(lieu, _eo[lieu]);
hasChanged = true;
}
}
return hasChanged;
}
/** Accessor to ref to sigma - for update and monitor */
double & Sigma() {return sigma;}
private:
double & sigma;
eoRealVectorBounds & bounds;
double p_change;
};
/** the dynamic version: just say it is updatable -
* and write the update() method!
* here the 1 fifth rule: count the proportion of successful mutations, and
* increase sigma if more than threshold (1/5 !)
*
* @ingroup Real
* @ingroup Variators
*/
template<class EOT> class eoOneFifthMutation :
public eoNormalMutation<EOT>, public eoUpdatable
{
public:
using eoNormalMutation< EOT >::Sigma;
typedef typename EOT::Fitness Fitness;
/**
* (Default) Constructor.
*
* @param _eval the evaluation function, needed to recompute the fitmess
* @param _sigmaInit the initial value for uniform mutation
* @param _windowSize the size of the window for statistics
* @param _updateFactor multiplicative update factor for sigma
* @param _threshold the threshold (the 1/5 - 0.2)
*/
eoOneFifthMutation(eoEvalFunc<EOT> & _eval, double & _sigmaInit,
unsigned _windowSize = 10, double _updateFactor=0.83,
double _threshold=0.2):
eoNormalMutation<EOT>(_sigmaInit), eval(_eval),
threshold(_threshold), updateFactor(_updateFactor),
nbMut(_windowSize, 0), nbSuccess(_windowSize, 0), genIndex(0)
{
// minimal check
if (updateFactor>=1)
throw std::runtime_error("Update factor must be < 1 in eoOneFifthMutation");
}
/** The class name */
virtual std::string className() const { return "eoOneFifthMutation"; }
/**
* Do it!
* calls the standard mutation, then checks for success and updates stats
*
* @param _eo The chromosome undergoing the mutation
*/
bool operator()(EOT & _eo)
{
if (_eo.invalid()) // due to some crossover???
eval(_eo);
Fitness oldFitness = _eo.fitness(); // save old fitness
// call standard operator - then count the successes
if (eoNormalMutation<EOT>::operator()(_eo)) // _eo has been modified
{
_eo.invalidate(); // don't forget!!!
nbMut[genIndex]++;
eval(_eo); // compute fitness of offspring
if (_eo.fitness() > oldFitness)
nbSuccess[genIndex]++; // update counter
}
return false; // because eval has reset the validity flag
}
/** the method that will be called every generation
* if the object is added to the checkpoint
*/
void update()
{
unsigned totalMut = 0;
unsigned totalSuccess = 0;
// compute the average stats over the time window
for ( unsigned i=0; i<nbMut.size(); i++)
{
totalMut += nbMut[i];
totalSuccess += nbSuccess[i];
}
// update sigma accordingly
double prop = double(totalSuccess) / totalMut;
if (prop > threshold) {
Sigma() /= updateFactor; // increase sigma
}
else
{
Sigma() *= updateFactor; // decrease sigma
}
genIndex = (genIndex+1) % nbMut.size() ;
nbMut[genIndex] = nbSuccess[genIndex] = 0;
}
private:
eoEvalFunc<EOT> & eval;
double threshold; // 1/5 !
double updateFactor ; // the multiplicative factor
std::vector<unsigned> nbMut; // total number of mutations per gen
std::vector<unsigned> nbSuccess; // number of successful mutations per gen
unsigned genIndex ; // current index in std::vectors (circular)
};
//-----------------------------------------------------------------------------
//@}
#endif

63
eo/src/es/eoReal.h Normal file
View file

@ -0,0 +1,63 @@
/*
eoReal.h
// (c) Marc Schoenauer, Maarten Keijzer and GeNeura Team, 2000
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: Marc.Schoenauer@polytechnique.fr
todos@geneura.ugr.es, http://geneura.ugr.es
mkeijzer@dhi.dk
*/
#ifndef eoReal_h
#define eoReal_h
//-----------------------------------------------------------------------------
#include <iostream> // std::ostream, std::istream
#include <string> // std::string
#include <eoVector.h>
/** eoReal: implementation of simple real-valued chromosome.
* based on eoVector class
*
* @ingroup Real
*/
template <class FitT> class eoReal: public eoVector<FitT, double>
{
public:
/**
* (Default) Constructor.
* @param size Size of the std::vector
* @param value fill the vector with this value
*/
eoReal(unsigned size = 0, double value = 0.0):
eoVector<FitT, double>(size, value) {}
/// My class name.
virtual std::string className() const
{
return "eoReal";
}
};
/** @example t-eoReal.cpp
*/
//-----------------------------------------------------------------------------
#endif

Some files were not shown because too many files have changed in this diff Show more