00001
00020 #include "ma2lsia.h"
00021 #include "selectlsimp.h"
00022 #include <cassert>
00023 #include <cmath>
00024 #include <cstdio>
00025
00026 using namespace realea;
00027 using namespace realea::internal;
00028
00029 void MA2LSIA::setEffortRatio(double ratio) {
00030 if (ratio == 1)
00031 throw new string("MA2LSIA::effortRatio is not valide");
00032
00033 m_effort = ratio;
00034 }
00035
00036 MA2LSIA::MA2LSIA(IEAlgorithm *alg, ILocalSearch *ls) : Hybrid(alg,ls), m_memory(NULL) {
00037 m_effort = -1;
00038 m_restart = NULL;
00039 m_debug = false;
00040 m_select_improvement = NULL;
00041 m_frec_update = 5;
00042 }
00043
00044 void MA2LSIA::setDebug(void) {
00045 m_debug = true;
00046 }
00047
00048 MA2LSIA::~MA2LSIA(void) {
00049 if (m_memory) {
00050 delete m_memory;
00051 }
00052
00053 if (m_restart) {
00054 delete m_restart;
00055 }
00056
00057 if (m_select_improvement) {
00058 delete m_select_improvement;
00059 }
00060
00061 if (m_initeval) {
00062 delete m_initeval;
00063 }
00064 }
00065
00066 unsigned MA2LSIA::calculateFrec(double nevalalg, double nevalls, unsigned intensity, unsigned evalprev, double ratio) {
00067
00068 assert(ratio > 0);
00069
00070 double coc = ratio*(nevalalg + nevalls + intensity) - evalprev;
00071 double div = (1-ratio);
00072
00073 if (div == 0) {
00074 throw string("MA2LSIA::Ratio is too low");
00075 }
00076
00077 return ((unsigned) floor(coc/div));
00078 }
00079
00080 unsigned MA2LSIA::init(void) {
00081 initLs();
00082
00083 m_initMaxEval = m_running->maxEval();
00084 unsigned neval = m_alg->init();
00085
00086 if (m_select_improvement == NULL) {
00087 m_select_improvement = new SelectBestToImprove();
00088 }
00089
00090 if (m_memory == NULL) {
00091 m_memory = new LSParametersMemory(m_alg->getPop()->size());
00092 m_alg->getPop()->setObserver(m_memory);
00093 }
00094
00095 m_nevalalg = neval;
00096 m_nevalls = 0;
00097 return neval;
00098 }
00099
00100 void MA2LSIA::setMaxEval(unsigned int maxeval) {
00101 assert(maxeval >= m_intensity);
00102 unsigned frec = calculateFrec(m_nevalalg, m_nevalls, m_intensity, m_nevalalg, m_effort);
00103 m_alg->setMaxEval(frec);
00104 }
00105
00106 void MA2LSIA::setRestart(RestartStrategy *restart, int maxfailed) {
00107
00108 if (m_restart) {
00109 delete m_restart;
00110
00111 }
00112
00113 m_restart = restart;
00114 m_maxfailed = maxfailed;
00115 }
00116
00117 void MA2LSIA::setRunning(Running *running) {
00118 ProxyEA::setRunning(running);
00119 unsigned frec = calculateFrec(m_nevalalg, m_nevalls, m_intensity, m_nevalalg, m_effort);
00120 m_alg->setRunning(m_running->getSubRunning(frec));
00121 }
00122
00123 void MA2LSIA::updateFrec(double ratio_effort, double ratio_improvement) {
00124
00125 if (ratio_effort != ratio_improvement) {
00126 double C = ratio_effort/ratio_improvement;
00127 unsigned frec = (unsigned) ceil(C*m_intensity/(1-C));
00128
00129 if (frec < 50) {
00130 frec = 50;
00131 }
00132 else if (frec > 3000) {
00133 frec = 3000;
00134 }
00135
00136 printf("New MaxEval: %u\n", frec);
00137 m_alg->setMaxEval(frec);
00138 }
00139 }
00140
00141
00142
00143 void MA2LSIA::recoverIndividual(unsigned oldind, tGen *aind, unsigned size, tGen *aoptional, unsigned size_optional) {
00144 m_alg->recoverIndividual(oldind, aind, size-1, aoptional, size_optional);
00145
00146 if (aind[size]) {
00147 m_alg->getPop()->getInd(oldind)->incremCount("non_improved");
00148 }
00149
00150 if (aoptional != NULL) {
00151 IParallelLocalSearch *ls = (IParallelLocalSearch *) m_ls;
00152 ILSParameters *params = ls->recoverOptions(aoptional, size_optional);
00153 assert(m_memory);
00154 m_memory->store(oldind, params);
00155 }
00156
00157 }
00158
00159 void MA2LSIA::storeIndividual(tIndividualRealPtr ind, tGen **paind, unsigned *pmax, tGen **paoptional, unsigned *psize_optional) {
00160 tGen *asol, *aoptional_sol;
00161 tGen *asol_ma;
00162 unsigned size_sol, size_optional;
00163 tGen *aparams;
00164 unsigned size_param;
00165 unsigned size;
00166
00167 m_alg->storeIndividual(ind, &asol, &size_sol, &aoptional_sol, &size_optional);
00168 assert(size_optional == 0 && aoptional_sol == NULL);
00169
00170 asol_ma = new tGen[size_sol+1];
00171 copy(asol, asol+size_sol, asol_ma);
00172 delete[] asol;
00173 asol_ma[size_sol] = (ind->getCount("non_improved") > 0) ? 1 : 0;
00174
00175 *paind = asol_ma;
00176 *pmax = size_sol+1;
00177
00178 size_param = 0;
00179
00180 if (m_memory) {
00181 unsigned posind = ind->getId();
00182 IParallelLocalSearch *ls = (IParallelLocalSearch *) m_ls;
00183 ILSParameters *params = m_memory->recover(posind);
00184 ls->storeOptions(params, &aparams, &size_param);
00185 }
00186
00187 size = size_optional+size_param;
00188 assert(size > 0);
00189
00190 *psize_optional = size_param;
00191 *paoptional = NULL;
00192
00193 if (aoptional_sol != NULL || aparams != NULL) {
00194 *paoptional = new tGen[size];
00195
00196 if (aoptional_sol != NULL) {
00197 copy(aoptional_sol, aoptional_sol+size_optional, *paoptional);
00198 delete[] aoptional_sol;
00199 }
00200
00201 if (aparams != NULL) {
00202 copy(aparams, aparams+size_param, *paoptional+size_optional);
00203 delete[] aparams;
00204 }
00205
00206 }
00207 }
00208
00209 void MA2LSIA::setDif(bool debug, string ident, unsigned id, tFitness oldfit, tFitness newfit) {
00210 if (debug) {
00211
00212 if (oldfit!= newfit) {
00213 printf("%s[%2d]:\t%e-> %e\t\t%e\n", ident.c_str(), id, oldfit, newfit, fabs(newfit-oldfit));
00214 }
00215 else {
00216 printf("%s[%2d]:\t%e\n", ident.c_str(), id, newfit);
00217 }
00218 }
00219
00220 }
00221
00222 bool MA2LSIA::hasDiversity(PopulationReal *pop) {
00223 return true;
00224 double percen[5];
00225 pop->getPercentils(percen, 4);
00226
00227
00228 printf("EA::Improvement: %e\t%e\t%e\t%e\t%e\n", percen[0], percen[1],
00229 percen[2], percen[3], percen[4]);
00230
00231
00232 if (percen[2] == percen[4]) {
00233 return false;
00234 }
00235 else if (percen[1] == percen[3]) {
00236 return false;
00237 }
00238 else if (fabs((percen[0] - percen[2])/percen[2]) < 1e-3) {
00239 return false;
00240 }
00241 else {
00242 return true;
00243 }
00244 }
00245
00246 void MA2LSIA::setInitEval(IEval*eval) {
00247 Hybrid::setInitEval(eval);
00248 m_initeval = (IEvalInd *) new EvalRunning(eval, m_running);
00249 }
00250
00251 unsigned MA2LSIA::realApply(tChromosomeReal &bestsol, tFitness &bestfitness) {
00252 tIndividualReal *ind, *best;
00253 unsigned posind;
00254 tFitness oldfitness, fitness, fitness_alg;
00255 unsigned ndim = bestsol.size();
00256 tChromosomeReal sol(ndim), sol_alg(ndim);
00257 unsigned alg_failed;
00258
00259 PopulationReal *pop_alg = m_alg->getPop();
00260 deque<tIndividualReal*> ind_to_improve;
00261 tFitness improvement_alg, improvement_ls;
00262 tFitness improvement_alg_step, improvement_ls_step;
00263 double nevalalg_step, nevalls_step;
00264 tFitness improvement_ratio, old_improvement_ratio, improvement;
00265 unsigned inc_neval;
00266
00267 sol=bestsol;
00268 fitness = bestfitness;
00269 improvement_alg = improvement_ls = 0;
00270 improvement_alg_step = improvement_ls_step = 0;
00271 nevalalg_step = nevalls_step = 0;
00272
00273 unsigned initMax = m_running->numEval();
00274 fitness_alg = pop_alg->getInd(pop_alg->getBest())->perf();
00275
00276 improvement_ratio = m_effort;
00277
00278 alg_failed = 0;
00279 unsigned n_itera = 0;
00280
00281
00282 while (!m_running->isFinish()) {
00283 tFitness old_fitness = fitness_alg;
00284 inc_neval = m_alg->realApply(sol_alg, fitness_alg);
00285 m_nevalalg += inc_neval; nevalalg_step += inc_neval;
00286 improvement = fabs(fitness_alg-old_fitness);
00287 improvement_alg += improvement; improvement_alg_step += improvement;
00288
00289 if (fitness_alg == old_fitness) {
00290 alg_failed++;
00291 }
00292 else {
00293 alg_failed = 0;
00294 }
00295
00296 if (m_debug) {
00297 setDif(m_debug, "Alg", pop_alg->getBest(), old_fitness, fitness_alg);
00298 }
00299
00300
00301 if (m_running->isOptime(fitness_alg)) {
00302 continue;
00303 }
00304
00305
00306 m_select_improvement->getIndsToImprove(pop_alg, ind_to_improve);
00307
00308 if (ind_to_improve.size()!=0) {
00309
00310 posind = m_select_improvement->selectIndToImprove(ind_to_improve);
00311 }
00312 else {
00313
00314 posind = m_random->randint(0, pop_alg->size()-1);
00315 }
00316
00317 ind = pop_alg->getInd(posind);
00318 sol = ind->sol();
00319
00320 ILSParameters *params = m_memory->recover(posind);
00321 bool recover = (params != NULL);
00322
00323 if (params == NULL) {
00324
00325 params = m_ls->getInitOptions(sol);
00326 }
00327
00328 fitness = ind->perf();
00329 oldfitness = fitness;
00330
00331 inc_neval = m_ls->apply(params, sol, fitness, m_intensity);
00332
00333 m_nevalls += inc_neval;
00334 nevalls_step += inc_neval;
00335
00336 ind->incremCount("ls");
00337 improvement = fabs(fitness-oldfitness);
00338 improvement_ls += improvement;
00339 improvement_ls_step += improvement;
00340
00341 setDif(m_debug, "LS ", ind->getId(), oldfitness, fitness);
00342
00343 if (m_problem->isBetter(fitness, fitness_alg)) {
00344 fitness_alg = fitness;
00345 }
00346
00347 if (!m_problem->isBetter(fitness, oldfitness)) {
00348 ind->incremCount("non_improved");
00349
00350 if (recover) {
00351 m_memory->remove(posind);
00352 }
00353 else {
00354 delete params;
00355 }
00356
00357 if (ind_to_improve.empty() && m_restart != NULL && !m_running->isFinish()) {
00358 m_restart->apply(pop_alg, m_problem, m_initeval);
00359
00360 if (m_debug) {
00361 printf("Restart_NotImprovement\t: %e\n", fitness);
00362 }
00363 }
00364 }
00365 else {
00366 pop_alg->change(posind, sol, fitness);
00367 m_memory->store(posind, params);
00368 }
00369
00370 if (m_restart != NULL && m_maxfailed > 0) {
00371 if (alg_failed > m_maxfailed && !hasDiversity(pop_alg) && !m_running->isFinish()) {
00372 m_restart->apply(pop_alg, m_problem, m_initeval);
00373
00374 if (m_debug) {
00375 printf("Restart_AlgFailed\t: %e\n", fitness_alg);
00376 }
00377 alg_failed = 0;
00378 }
00379 }
00380
00381 n_itera ++;
00382
00383 if (n_itera == m_frec_update) {
00384 old_improvement_ratio = improvement_ratio;
00385 improvement_ratio = improvement_alg_step/(improvement_alg_step+improvement_ls_step);
00386 updateFrec(old_improvement_ratio, improvement_ratio);
00387 nevalalg_step = nevalls_step = 0;
00388 improvement_alg_step = improvement_ls_step = 0;
00389 n_itera = 0;
00390 }
00391 }
00392
00393 if (m_debug) {
00394 double ratio_effort = ( (double)m_nevalalg)/(m_nevalalg+m_nevalls);
00395 printf("RatioEffort Alg/LS: [%.0f/%.0f]\n", 100*ratio_effort, 100*(1-ratio_effort));
00396
00397 double ratio_alg = improvement_alg/(improvement_alg+improvement_ls);
00398 printf("RatioImprovement Alg/LS: [%.0f/%.0f]\n", 100*ratio_alg, 100*(1-ratio_alg));
00399 }
00400 unsigned neval = m_running->numEval()-initMax;
00401 best = pop_alg->getInd(pop_alg->getBest());
00402 bestsol = best->sol();
00403 bestfitness = best->perf();
00404 m_running->reset();
00405 m_alg->setMaxEval(m_intensity);
00406 return neval;
00407 }