00001
00019 #include "simplex.h"
00020 #include <realea/common/distance.h>
00021 #include <realea/common/random.h>
00022 #include <algorithm>
00023 #include <numeric>
00024 #include <cassert>
00025 #include <cmath>
00026
00027 using namespace realea;
00028
00029 class SimplexParams : public ILSParameters {
00030 public:
00034 vector<tChromosomeReal> m_simplex;
00035
00039 vector<tFitness > m_fitnessElem;
00040
00044 vector<tGen> m_cum_simplex;
00045
00046 int ndim(void) {
00047 assert(!m_simplex.empty());
00048 return m_simplex[0].size();
00049 }
00050
00051 SimplexParams(void) : m_simplex(), m_fitnessElem(), m_cum_simplex() {
00052 }
00053
00054 void calculateCentroide(void);
00055 void getBest(vector<tGen> &sol, tFitness &fitness);
00056 };
00057
00061 template<class T>
00062 class SortIndex : binary_function<int,int,bool>{
00063 public:
00064 T* m_values;
00065
00066 SortIndex(T* values) : m_values(values) {}
00067
00068 bool operator()(int &elem1, int &elem2) {
00069 return m_values[elem1] < m_values[elem2];
00070 }
00071 };
00072
00073
00080 tChromosomeReal &accumulate_var(tChromosomeReal &result, tChromosomeReal &elem) {
00081 int i, ndim=result.size();
00082
00083 for (i = 0; i < ndim; ++i) {
00084 result[i] += elem[i];
00085 }
00086
00087 return result;
00088 }
00089
00090
00091
00092 void SimplexParams::calculateCentroide(void) {
00093 int ndim = m_simplex[0].size();
00094
00095 if (m_cum_simplex.empty()) {
00096 fill_n(back_inserter(m_cum_simplex), ndim, 0.0);
00097 }
00098 else {
00099
00100 fill(m_cum_simplex.begin(), m_cum_simplex.end(), 0.0);
00101 }
00102
00103
00104 m_cum_simplex = accumulate(m_simplex.begin(), m_simplex.end(), m_cum_simplex,
00105 ptr_fun(accumulate_var));
00106 }
00107
00108 void SimplexParams::getBest(vector<tGen> &sol, tFitness &fitness) {
00109 int i, ndim=sol.size();
00110 int best;
00111
00112 vector<int> index(ndim+1);
00113
00114 for (i = 0; i <= ndim; i++) {
00115 index[i] = i;
00116 }
00117
00118 SortIndex<tFitness > mySort(&m_fitnessElem[0]);
00119
00120
00121 best = *min_element(index.begin(), index.end(), mySort);
00122
00123
00124 copy(m_simplex[best].begin(), m_simplex[best].end(), sol.begin());
00125 fitness = m_fitnessElem[best];
00126 }
00127
00128 Simplex::Simplex(void) {
00129 }
00130
00131 void Simplex::getExtremes(ILSParameters *params, int &best_index, int &next_worst_index, int &worst_index) {
00132 SimplexParams *p = (SimplexParams *) params;
00133 tFitness bestFitness, worstFitness, nextworstFitness;
00134 tFitness fitness;
00135 int elem = p->m_fitnessElem.size();
00136 int i;
00137
00138 best_index = worst_index = next_worst_index = 0;
00139 bestFitness = worstFitness = nextworstFitness = p->m_fitnessElem[0];
00140
00141 for (i = 1; i < elem; i++) {
00142 fitness = p->m_fitnessElem[i];
00143
00144 if (m_problem->isBetter(fitness, bestFitness)) {
00145 best_index = i;
00146 bestFitness = fitness;
00147 }
00148 else if (m_problem->isBetter(worstFitness, fitness)) {
00149 next_worst_index = worst_index;
00150 nextworstFitness = worstFitness;
00151 worst_index = i;
00152 worstFitness = fitness;
00153 }
00154 else if (m_problem->isBetter(nextworstFitness, fitness) && i != worst_index) {
00155 next_worst_index = i;
00156 nextworstFitness = fitness;
00157 }
00158
00159 }
00160
00161 }
00162
00163 ILSParameters *Simplex::getInitOptions(tChromosomeReal &sol) {
00164
00165 int ndim;
00166
00167 ndim = sol.size();
00168
00169 SimplexParams *p = new SimplexParams();
00170
00171 p->m_simplex.clear();
00172 p->m_simplex.reserve(ndim+1);
00173 p->m_fitnessElem.reserve(ndim+1);
00174
00175 return p;
00176 }
00177
00178 tFitness Simplex::move(ILSParameters *params, int posi, double factor) {
00179 SimplexParams *p = (SimplexParams *) params;
00180 tGen *worst_point;
00181 tFitness *worst_value;
00182 unsigned ndim = p->ndim();
00183 tFitness rfac,new_value;
00184
00185 vector<tGen> new_point(ndim);
00186 unsigned i;
00187
00188 worst_point = &p->m_simplex[posi][0];
00189 worst_value = &p->m_fitnessElem[posi];
00190
00191 rfac = (1.0-factor)/(double)ndim;
00192 DomainRealPtr domain = m_problem->getDomain();
00193
00194 for (i=0;i<ndim; i++) {
00195
00196 new_point[i]=p->m_cum_simplex[i]*rfac - worst_point[i]*(rfac-factor);
00197 new_point[i]=domain->clip(i, new_point[i]);
00198 }
00199
00200 new_value = m_eval->eval(new_point);
00201
00202
00203 if (m_problem->isBetter(new_value, *worst_value)) {
00204 *worst_value = new_value;
00205
00206
00207 for (i=0; i<ndim; i++) {
00208 p->m_cum_simplex[i] += new_point[i]-worst_point[i];
00209 worst_point[i] = new_point[i];
00210 }
00211 }
00212
00213 return new_value;
00214 }
00215
00216 unsigned Simplex::restart_simplex(ILSParameters *params, int best, unsigned max) {
00217 SimplexParams *p = (SimplexParams *) params;
00218 int ndim = p->ndim();
00219 int elem = p->m_simplex.size();
00220 int i, j;
00221 unsigned num=0;
00222
00223 for (i = 0; i < elem && num < max && !m_running->isFinish(); ++i) {
00224 if (i == best)
00225 continue;
00226
00227
00228 for (j = 0; j < ndim; ++j) {
00229 p->m_simplex[i][j] = 0.5*(p->m_simplex[i][j]+p->m_simplex[best][j]);
00230 }
00231
00232 p->m_fitnessElem[i] = m_eval->eval(p->m_simplex[i]);
00233 num++;
00234 }
00235
00236 return num;
00237 }
00238
00239
00240 unsigned Simplex::apply(ILSParameters *params, tChromosomeReal &sol, tFitness &sol_perf, unsigned maxeval) {
00241 SimplexParams *p = (SimplexParams*) params;
00242 tFitness newFitness;
00243 int best, worst, next_worst;
00244 double factor = 1.0;
00245 unsigned num;
00246
00247 num = 0;
00248
00249 if (p->m_simplex.empty()) {
00250 num = initParams(sol, sol_perf, p);
00251 }
00252
00253 p->calculateCentroide();
00254
00255 while (num < maxeval && !m_running->isFinish()) {
00256 getExtremes(p, best, next_worst, worst);
00257
00258 tFitness &bestFitness = p->m_fitnessElem[best];
00259 tFitness &worstFitness = p->m_fitnessElem[worst];
00260 tFitness &nextworstFitness = p->m_fitnessElem[next_worst];
00261
00262 int actual = worst;
00263
00264
00265 newFitness = move(p, actual, -factor);
00266 num++;
00267
00268
00269 if (m_running->isFinish()) {
00270
00271 }
00272 else if (m_problem->isBetter(newFitness, bestFitness) || newFitness == bestFitness) {
00273 newFitness = move(p, actual, 2.0*factor);
00274 num++;
00275 }
00276
00277 else if (!m_problem->isBetter(newFitness, nextworstFitness)) {
00278
00279 newFitness = move(p, actual, factor/2.0);
00280 num++;
00281
00282 if (m_problem->isBetter(worstFitness, newFitness) || worstFitness == newFitness) {
00283
00284 num += restart_simplex(p, best, maxeval-num);
00285
00286 p->calculateCentroide();
00287 }
00288 }
00289 }
00290
00291 p->getBest(sol, sol_perf);
00292 return num;
00293 }
00294
00295 unsigned SimplexDim::initParams(tChromosomeReal &sol, tFitness fitness, ILSParameters *params) {
00296 SimplexParams *p = (SimplexParams *) params;
00297 vector<tGen> copysol(sol);
00298 tFitness newFitness;
00299 tGen min, max, dif;
00300 int ndim, i;
00301
00302
00303 p->m_simplex.push_back(sol);
00304 p->m_fitnessElem.push_back(fitness);
00305
00306 DomainRealPtr domain = m_problem->getDomain();
00307 ndim = domain->getDimension();
00308
00309
00310 for (i = 0; i < ndim; i++) {
00311 domain->getValues(i, &min, &max);
00312 dif = (max-min);
00313 copysol[i] += 0.1*dif;
00314 copysol[i] = domain->clip(i, copysol[i]);
00315 newFitness = m_eval->eval(copysol);
00316 p->m_fitnessElem.push_back(newFitness);
00317 p->m_simplex.push_back(copysol);
00318 copysol[i] = sol[i];
00319 }
00320
00321 return ndim;
00322 }
00323
00324 unsigned SimplexNeigh::initParams(tChromosomeReal &sol, tFitness fitness, ILSParameters *params) {
00325 SimplexParams *p = (SimplexParams *) params;
00326 vector<tGen> copysol(sol);
00327 tFitness newFitness;
00328 int ndim, i;
00329
00330
00331 p->m_simplex.push_back(sol);
00332 p->m_fitnessElem.push_back(fitness);
00333
00334 DomainRealPtr domain = m_problem->getDomain();
00335 ndim = domain->getDimension();
00336
00337
00338 vector<unsigned> minind(sol.size());
00339
00340 min_dim_distance(sol, m_pop, minind);
00341
00342 for (i = 0; i < ndim; i++) {
00343 unsigned pos = minind[i];
00344 tChromosomeReal ind = m_pop->getInd(pos)->sol();
00345 copy(ind.begin(), ind.end(), copysol.begin());
00346 newFitness = m_eval->eval(copysol);
00347 p->m_fitnessElem.push_back(newFitness);
00348 p->m_simplex.push_back(copysol);
00349 }
00350
00351 return ndim;
00352
00353 }
00354
00355