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