CMAParams.cpp

00001 
00002 /*
00003  * C++ification of Nikolaus Hansen's original C-source code for the
00004  * CMA-ES
00005  *
00006  * C++-ificiation performed by Maarten Keijzer (C) 2005. Licensed under
00007  * the LGPL. Original copyright of Nikolaus Hansen can be found below
00008  *
00009  *
00010  * 
00011  */
00012 
00013 /* --------------------------------------------------------- */
00014 /* --------------------------------------------------------- */
00015 /* --- File: cmaes.c  -------- Author: Nikolaus Hansen   --- */
00016 /* --------------------------------------------------------- */
00017 /*
00018  *      CMA-ES for non-linear function minimization.
00019  *
00020  *           Copyright (C) 1996, 2003  Nikolaus Hansen.
00021  *           e-mail: hansen@bionik.tu-berlin.de
00022  *
00023  *           This library is free software; you can redistribute it and/or
00024  *           modify it under the terms of the GNU Lesser General Public
00025  *           License as published by the Free Software Foundation; either
00026  *           version 2.1 of the License, or (at your option) any later
00027  *           version (see http://www.gnu.org/copyleft/lesser.html).
00028  *
00029  *           This library is distributed in the hope that it will be useful,
00030  *           but WITHOUT ANY WARRANTY; without even the implied warranty of
00031  *           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00032  *           Lesser General Public License for more details.
00033  * 
00034  *                                                             */
00035 /* --- Changes : ---
00036  *   03/03/21: argument const double *rgFunVal of
00037  *   cmaes_ReestimateDistribution() was treated incorrectly.
00038  *   03/03/29: restart via cmaes_resume_distribution() implemented.
00039  *   03/03/30: Always max std dev / largest axis is printed first.
00040  *   03/08/30: Damping is adjusted for large mueff.
00041  *   03/10/30: Damping is adjusted for large mueff always.
00042  *   04/04/22: Cumulation time and damping for step size adjusted.
00043  *   No iniphase but conditional update of pc.
00044  *   Version 2.23.
00045  *                               */
00046 
00047 #include <es/CMAParams.h>
00048 #include <utils/eoParser.h>
00049 
00050 #include <string>
00051 
00052 using namespace std;
00053 
00054 namespace eo {
00055 
00056 CMAParams::CMAParams(eoParser& parser, unsigned dimensionality) {
00057     
00058     string section = "CMA parameters";
00059     
00060     n = parser.createParam(dimensionality, "dimensionality", "Dimensionality (N) of the problem", 'N', section, dimensionality == 0).value();
00061     
00062     maxgen = parser.createParam(
00063             1000,
00064             "max-gen",
00065             "Maximum number of generations that the system will run (needed for damping)",
00066             'M',
00067             section).value();
00068     
00069     
00070     if (n == 0) {
00071         return;
00072     }
00073     
00074     defaults(n, maxgen);
00075     
00076     /* handle lambda */
00077     lambda = parser.createParam(
00078             lambda,
00079             "lambda",
00080             "Number of offspring",
00081             'l',
00082             section).value();
00083 
00084     if (lambda < 2) {
00085         lambda = 4+(int)(3*log((double) n));
00086         cerr << "Too small lambda specified, setting it to " << lambda << endl;
00087     }
00088     
00089     /* handle mu */
00090     mu = parser.createParam(
00091             mu,
00092             "mu",
00093             "Population size",
00094             'm',
00095             section).value();
00096 
00097     if (mu >= lambda) {
00098         mu = lambda/2;
00099         cerr << "Mu set larger/equal to lambda, setting it to " << mu << endl;
00100     }
00101     
00102     /* handle selection weights */
00103     
00104     int weight_type = parser.createParam(
00105             0,
00106             "weighting",
00107             "Weighting scheme (for 'selection'): 0 = logarithmic, 1 = equal, 2 = linear",
00108             'w',
00109             section).value();
00110 
00111     switch (weight_type) {
00112         case 1: 
00113             {
00114                 for (unsigned i = 0; i < weights.size(); ++i) {
00115                     weights[i] = mu - i;
00116                 }
00117             }
00118         case 2:
00119             {
00120                 weights = 1.;
00121             }
00122         default : 
00123             {
00124                 for (unsigned i = 0; i < weights.size(); ++i) {
00125                     weights[i] = log(mu+1.)-log(i+1.);
00126                 }
00127             }
00128         
00129     }
00130 
00131     /* Normalize weights and set mu_eff */
00132     double sumw = weights.sum();
00133     mueff =  sumw * sumw / (weights * weights).sum();
00134     weights /= sumw;
00135     
00136 
00137     /* most of the rest depends on mu_eff, so needs to be set again */
00138     
00139     /* set the others using Nikolaus logic. If you want to tweak, you can parameterize over these defaults */
00140     mucov = mueff;
00141     ccumsig = (mueff + 2.) / (n + mueff + 3.);
00142     ccumcov = 4. / (n + 4);
00143     
00144     double t1 = 2. / ((n+1.4142)*(n+1.4142));
00145     double t2 = (2.*mucov-1.) / ((n+2.)*(n+2.)+mucov);
00146     t2 = (t2 > 1) ? 1 : t2;
00147     t2 = (1./mucov) * t1 + (1.-1./mucov) * t2;
00148     
00149     ccov = t2;
00150 
00151     damp = 1 + std::max(0.3,(1.-(double)n/(double)maxgen))
00152               * (1+2*std::max(0.,sqrt((mueff-1.)/(n+1.))-1)) /* limit sigma increase */
00153                     / ccumsig;
00154   
00155     vector<double> mins(1,0.0);
00156     mins = parser.createParam(
00157             mins,
00158             "min-stdev",
00159             "Array of minimum stdevs, last one will apply for all remaining axes",
00160             0,
00161             section).value();
00162     
00163     if (mins.size() > n) mins.resize(n);
00164 
00165     if (mins.size()) {
00166         minStdevs = mins.back();
00167         for (unsigned i = 0; i < mins.size(); ++i) {
00168             minStdevs[i] = mins[i];
00169         }
00170     }
00171     
00172     vector<double> inits(1,0.3);
00173     inits = parser.createParam(
00174             inits,
00175             "init-stdev",
00176             "Array of initial stdevs, last one will apply for all remaining axes",
00177             0,
00178             section).value();
00179     
00180     if (inits.size() > n) inits.resize(n);
00181 
00182     if (inits.size()) {
00183         initialStdevs = inits.back();
00184         for (unsigned i = 0; i < inits.size(); ++i) {
00185             initialStdevs[i] = inits[i];
00186         }
00187     }
00188     
00189 }
00190 
00191 void CMAParams::defaults(unsigned n_, unsigned maxgen_) {
00192     n = n_;
00193     maxgen = maxgen_;
00194 
00195     lambda = 4+(int)(3*log((double) n));
00196     mu = lambda / 2;
00197     
00198     weights.resize(mu);
00199     
00200     for (unsigned i = 0; i < weights.size(); ++i) {
00201         weights[i] = log(mu+1.)-log(i+1.);
00202     }
00203     
00204     /* Normalize weights and set mu_eff */
00205     double sumw = weights.sum();
00206     mueff =  sumw * sumw / (weights * weights).sum();
00207     weights /= sumw;
00208     
00209     mucov = mueff;
00210     ccumsig *= (mueff + 2.) / (n + mueff + 3.);
00211     ccumcov = 4. / (n + 4);
00212     
00213     double t1 = 2. / ((n+1.4142)*(n+1.4142));
00214     double t2 = (2.*mucov-1.) / ((n+2.)*(n+2.)+mucov);
00215     t2 = (t2 > 1) ? 1 : t2;
00216     t2 = (1./mucov) * t1 + (1.-1./mucov) * t2;
00217     
00218     ccov = t2;
00219 
00220     damp = 1 + std::max(0.3,(1.-(double)n/maxgen))
00221               * (1+2*std::max(0.,sqrt((mueff-1.)/(n+1.))-1)) /* limit sigma increase */
00222                     / ccumsig;
00223 
00224     minStdevs.resize(n);
00225     minStdevs = 0.0;
00226     
00227     initialStdevs.resize(n);
00228     initialStdevs = 0.3;
00229     
00230 
00231 }
00232 
00233 
00234 }// namespace eo

Generated on Thu Apr 19 11:02:26 2007 for EO by  doxygen 1.4.7