00001
00020 #include "solis.h"
00021 #include <realea/common/distance.h>
00022 #include <realea/common/random.h>
00023 #include <algorithm>
00024 #include <cassert>
00025 #include <cmath>
00026
00027 using namespace realea;
00028
00029 class SolisParams : public ILSParameters {
00030 public:
00031 SolisParams(unsigned dim) : bias(dim) {
00032 }
00033 unsigned dim(void) {
00034 return bias.size();
00035 }
00036
00037 double delta;
00038 vector<double> bias;
00039 unsigned numFailed;
00040 unsigned numSuccess;
00041 virtual ~SolisParams(void) {}
00042
00043 virtual void store(tGen **aparams, unsigned *psize) {
00044 unsigned size = 3+bias.size();
00045 tGen *params = new tGen[size];
00046 params[0] = delta;
00047 params[1] = numFailed;
00048 params[2] = numSuccess;
00049 copy(bias.begin(), bias.end(), params+3);
00050 *aparams = params;
00051 *psize = size;
00052 }
00053
00054 virtual void recover(tGen *params, unsigned size) {
00055 assert(size > 3);
00056 delta = params[0];
00057 numFailed = (unsigned) ceil(params[1]);
00058 numSuccess = (unsigned) ceil(params[2]);
00059 copy(params+3, params+size, bias.begin());
00060 }
00061
00062 };
00063
00064
00065 SolisWets::SolisWets(void) {
00066 m_maxdelta = m_mindelta = -1;
00067 }
00068
00069 void SolisWets::setDelta(double maxdelta) {
00070 assert(maxdelta > 0);
00071 m_maxdelta = maxdelta;
00072 }
00073
00074 void SolisWets::setDelta(double mindelta, double maxdelta) {
00075 assert(mindelta > 0 && mindelta <= maxdelta);
00076 m_mindelta = mindelta;
00077 m_maxdelta = maxdelta;
00078 }
00079
00080 ILSParameters *SolisWets::recoverOptions(tGen *params, unsigned size) {
00081 SolisParams *option;
00082 unsigned dim = m_problem->getDimension();
00083
00084 option = new SolisParams(dim);
00085 option->recover(params, size);
00086 return ((ILSParameters *) option);
00087 }
00088
00089 void SolisWets::storeOptions(ILSParameters *params, tGen **paparams, unsigned *psize) {
00090 unsigned dim = m_problem->getDimension();
00091 unsigned size = dim+3;
00092
00093 if (params != NULL) {
00094 SolisParams *p = (SolisParams *) params;
00095 p->store(paparams, psize);
00096 assert(size == *psize);
00097 }
00098 else {
00099 *paparams = NULL;
00100 }
00101
00102 *psize = size;
00103 }
00104
00105
00106 ILSParameters *SolisWets::getInitOptions(tChromosomeReal &sol) {
00107 SolisParams *option;
00108 unsigned dim = m_problem->getDimension();
00109 option = new SolisParams(dim);
00110 option->numFailed = option->numSuccess = 0;
00111 unsigned nearest;
00112 if (m_pop == NULL) {
00113 assert(m_maxdelta > 0);
00114 option->delta = m_maxdelta;
00115 }
00116 else {
00120 double dist = distanceMin(sol, m_pop, &nearest);
00121 option->delta = dist/2.0;
00122
00123 if (m_maxdelta > 0 && option->delta > m_maxdelta) {
00124 option->delta = m_maxdelta;
00125 }
00126 else if (m_mindelta > 0 && option->delta < m_mindelta) {
00127 option->delta = m_mindelta;
00128 }
00129
00130 }
00131
00132 fill(option->bias.begin(), option->bias.end(), 0.0);
00133
00134 return ((ILSParameters *) option);
00135 }
00136
00137 tFitness SolisWets::getNeighbour(ILSParameters *param, tChromosomeReal &actual, tChromosomeReal &dif, tChromosomeReal &newsol) {
00138 unsigned i;
00139 SolisParams *p = (SolisParams *) param;
00140 unsigned ndim = actual.size();
00141 DomainRealPtr domain = m_problem->getDomain();
00142
00143 for (i = 0; i < ndim; i++) {
00144 if (domain->canBeChanged(i)) {
00145 dif[i] = m_random->normal(p->delta);
00146 newsol[i] = actual[i] + p->bias[i] + dif[i];
00147 }
00148 else
00149 newsol[i] = actual[i];
00150 }
00151
00152 domain->clip(newsol);
00153 return m_eval->eval(newsol);
00154 }
00155
00156
00157
00158 static double increm_bias(const double &bias, const double &dif) {
00159 return 0.2*bias+0.4*(dif+bias);
00160 }
00161
00162 static double dec_bias(const double &bias, const double &dif) {
00163 return bias-0.4*(dif+bias);
00164 }
00165
00166 unsigned SolisWets::apply(ILSParameters *params, tChromosomeReal &sol, tFitness &sol_perf, unsigned maxeval) {
00167 SolisParams *p = (SolisParams *) params;
00168 unsigned ndim = sol.size();
00169 tChromosomeReal dif(ndim), newsol(ndim);
00170 DomainRealPtr domain = m_problem->getDomain();
00171 tFitness newsol_perf;
00172 unsigned gen;
00173 unsigned numEval = 0;
00174
00175 for (numEval = 0; numEval < maxeval && !m_running->isFinish(); ) {
00176 newsol_perf = getNeighbour(p, sol, dif, newsol);
00177 numEval++;
00178
00179
00180 if (m_problem->isBetter(newsol_perf, sol_perf) ) {
00181 copy(newsol.begin(), newsol.end(), sol.begin());
00182 sol_perf = newsol_perf;
00183
00184
00185 transform(p->bias.begin(), p->bias.end(), dif.begin(), p->bias.begin(),
00186 ptr_fun(increm_bias));
00187 p->numSuccess++;
00188 p->numFailed = 0;
00189 }
00190 else if (numEval < maxeval && !m_problem->isBetter(newsol_perf, sol_perf) && !m_running->isFinish()) {
00191
00192 for (gen = 0; gen < ndim; gen++) {
00193 newsol[gen] = sol[gen] - p->bias[gen] - dif[gen];
00194 }
00195
00196 domain->clip(newsol);
00197 newsol_perf = m_eval->eval(newsol);
00198 numEval++;
00199
00200 if (m_problem->isBetter(newsol_perf, sol_perf)) {
00201 copy(newsol.begin(), newsol.end(), sol.begin());
00202 sol_perf = newsol_perf;
00203
00204
00205 transform(p->bias.begin(), p->bias.end(), dif.begin(), p->bias.begin(),
00206 ptr_fun(dec_bias));
00207
00208 p->numSuccess++;
00209 p->numFailed = 0;
00210 }
00211 else {
00212
00213 transform(p->bias.begin(), p->bias.end(), p->bias.begin(),
00214 bind2nd(multiplies<double>(), 0.5));
00215 p->numFailed++;
00216 p->numSuccess = 0;
00217 }
00218
00219 }
00220
00221 if (p->numSuccess >= maxSuccess) {
00222 p->numSuccess = 0;
00223 p->delta *= 2;
00224 }
00225 else if (p->numFailed >= maxFailed) {
00226 p->numFailed = 0;
00227 p->delta *= 0.5;
00228 }
00229
00230 }
00231
00232 return numEval;
00233 }