00001
00020 #include "cmaeshan.h"
00021 #include "origcmaes.h"
00022 #include "cmaes_interface.h"
00023 #include <realea/common/distance.h>
00024 #include <algorithm>
00025 #include <cassert>
00026 #include <cstdio>
00027
00028 using namespace realea;
00029 using namespace realea::internal;
00030
00031 typedef vector<tGen> DistVector;
00032
00033 class ProblemCMAESHansenEvalReal {
00034 public:
00035 ProblemCMAESHansenEvalReal(IEval* eval) : m_eval(eval) {
00036 }
00037
00038 tFitness eval(const double *sol, unsigned n) {
00039 tChromosomeReal solv(n);
00040
00041 for (unsigned i = 0; i < n; i++) {
00042 solv[i] = sol[i];
00043 }
00044 return m_eval->eval(solv);
00045 }
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 private:
00059 IEval *m_eval;
00060 };
00061
00062
00063
00064
00065 class CMAESHansenParams : public ILSParameters {
00066 public:
00067 cmaes_t evo;
00068 double *xinit, *stddev;
00069 double *fitvals;
00070 bool init;
00071
00072 CMAESHansenParams(unsigned dim) {
00073 xinit = new double[dim];
00074 stddev = new double[dim];
00075 fitvals = NULL;
00076 init = false;
00077 }
00078
00079 ~CMAESHansenParams(void) {
00080 delete[] xinit;
00081 delete[] stddev;
00082 cmaes_exit(&evo);
00083 }
00084 };
00085
00086 CMAESHansen::CMAESHansen(string fconfig) : m_debug(false) {
00087 m_rfactor = 0;
00088 m_nfactor = 0;
00089 m_fconfig = fconfig;
00090 }
00091
00099 static void getRange(DomainRealPtr domain, vector<tGen> *range) {
00100 tReal min, max;
00101 unsigned ndim = domain->getDimension();
00102
00103 for (unsigned i = 0; i < ndim; i++) {
00104 domain->getValues(0, &min, &max);
00105 (*range)[i] = max-min;
00106 }
00107 }
00108
00109
00110 void CMAESHansen::searchRange(double factor) {
00111 assert(factor > 0 && factor <= 1);
00112 m_rfactor = factor;
00113 }
00114
00115 void CMAESHansen::searchNeighborhood(double factor) {
00116 assert(factor > 0 && factor <= 1);
00117 m_nfactor = factor;
00118 }
00119
00120 ILSParameters *CMAESHansen::getInitOptions(tChromosomeReal &sol) {
00121 int i, dim = sol.size();
00122 CMAESHansenParams *param;
00123 DistVector dist(dim);
00124
00125 param = new CMAESHansenParams(dim);
00126
00127 for (i = 0; i < dim; i++) {
00128 param->xinit[i] = sol[i];
00129 }
00130
00131 if (m_nfactor) {
00132 if (m_pop == NULL) {
00133 delete param;
00134 throw ConfigException("CMAESHansen::Population");
00135 }
00136
00137 min_vector_distance(sol, m_pop, dist);
00138
00139 for (i = 0; i < dim; i++) {
00140 param->stddev[i] = dist[i]*m_nfactor+0.001;
00141 }
00142
00143 }
00144 else if (m_rfactor) {
00145 DomainRealPtr domain = m_problem->getDomain();
00146 vector<tGen> range(dim);
00147 getRange(domain, &range);
00148
00149 for (i = 0; i < dim; i++) {
00150 param->stddev[i] = range[i]*m_rfactor;
00151 }
00152 }
00153
00154 return param;
00155 }
00156
00157
00158 unsigned CMAESHansen::apply(ILSParameters *opt, tChromosomeReal &sol, tFitness &fitness, unsigned itera) {
00159 CMAESHansenParams *params = (CMAESHansenParams *) opt;
00160 double *const*pop;
00161 unsigned dim;
00162 tFitness bestfit,oldbestfit;
00163 int lambda = 0, counteval = 0;
00164 tFitness fbestever=0;
00165 double *xbestever=NULL;
00166 double fmean;
00167 const double *xmean;
00168
00169 char const * stop=NULL;
00170 int maxeval = itera-lambda;
00171 DomainRealPtr domain = m_problem->getDomain();
00172
00173
00174 ProblemCMAESHansenEvalReal *eval = new ProblemCMAESHansenEvalReal(m_eval);
00175 dim = sol.size();
00176
00177 if (!params->init) {
00178 params->fitvals = cmaes_init(¶ms->evo, dim, params->xinit, params->stddev, 0, 0, m_fconfig.c_str());
00179 params->init = true;
00180 }
00181
00182 lambda = cmaes_Get(¶ms->evo, "lambda");
00183 maxeval = itera-lambda;
00184
00185 bestfit = 0;
00186 params->evo.countevals = 0;
00187
00188 while(!(stop=cmaes_TestForTermination(¶ms->evo)) && counteval < maxeval && !m_running->isFinish()) {
00189
00190 pop = cmaes_SamplePopulation(¶ms->evo);
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 oldbestfit = bestfit;
00201
00202
00203 for (int i = 0; i < cmaes_Get(¶ms->evo, "popsize") && !m_running->isFinish(); ++i) {
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 params->fitvals[i] = eval->eval(pop[i], dim);
00217 counteval++;
00218
00219 if (params->fitvals[i] < bestfit || counteval == 1) {
00220 bestfit = params->fitvals[i];
00221 }
00222 }
00223
00224
00225 cmaes_UpdateDistribution(¶ms->evo, params->fitvals);
00226
00227
00228
00229
00230 fflush(stdout);
00231 params->evo.countevals = counteval;
00232 }
00233
00234 fbestever = cmaes_Get(¶ms->evo, "fbestever");
00235
00236 xbestever = cmaes_GetInto(¶ms->evo, "xbestever", xbestever);
00237
00238
00239 xmean = cmaes_GetPtr(¶ms->evo, "xmean");
00240
00241 if (counteval == 0) {
00242 if (stop != NULL) {
00243 printf("%s", stop);
00244 }
00245
00246 if (fbestever) {
00247 copy(xbestever, xbestever+dim, sol.begin());
00248 fitness = fbestever;
00249 }
00250 delete eval;
00251 return counteval;
00252 }
00253
00254
00255 if (!m_running->isFinish() && (fmean = eval->eval(xmean, dim)) < fbestever) {
00256 fbestever = fmean;
00257 xbestever = cmaes_GetInto(¶ms->evo, "xmean", xbestever);
00258 }
00259
00260 if (fbestever < fitness) {
00261 copy(xbestever, xbestever+dim, sol.begin());
00262 fitness = fbestever;
00263 }
00264
00265 delete eval;
00266 return counteval;
00267 }