00001 #include "NSGA_II.h"
00002
00003
00004
00005
00006
00007
00008 NSGA_II::NSGA_II(unsigned n_f__)
00009 {
00010 #ifdef DEBUG
00011 cout << "NSGA_II::NSGA_II()" << endl;
00012 #endif
00013
00014 selectDimension = 3;
00015 selectFunction.clear();
00016
00017 for (unsigned i = 0; i < selectDimension; i++)
00018 selectFunction.push_back(i);
00019
00020 n_f_ = n_f__;
00021 nadir.resize(n_f_);
00022 ideal.resize(n_f_);
00023
00024 dpSelection = false;
00025 fixedNadirIdeal = false;
00026 }
00027
00028
00029
00030
00031 void NSGA_II::select(vector<Individual*>& P, vector<Individual*>& O, unsigned mu, unsigned kappa, unsigned lambda, vector<int>& direction,
00032 vector<double>& bestF)
00033 {
00034 #ifdef DEBUG
00035 cout << "NSGA_II::select()" << endl;
00036 #endif
00037
00038
00039 vector<Individual*> Q;
00040 int size = 0;
00041 for (unsigned i = 0; i < lambda; i++)
00042 {
00043 if (O[i] != NULL)
00044 {
00045 Q.push_back(O[i]);
00046 O[i] = NULL;
00047 size++;
00048 }
00049 }
00050
00051
00052 for (unsigned i = 0; i < mu; i++)
00053 {
00054 if (P[i]->age <= kappa)
00055 {
00056 Q.push_back(P[i]);
00057 P[i] = NULL;
00058 size++;
00059 }
00060 }
00061
00062
00063 for (unsigned i = 0; i < mu; i++)
00064 {
00065 delete P[i];
00066 P[i] = NULL;
00067 }
00068
00069 vector<vector<int> > front;
00070 fastNondominatedSort(Q, front, direction, bestF);
00071
00072
00073
00074 bool ready = false;
00075 if (dpSelection)
00076 {
00077 vector<int> indices;
00078 for (int i = 0; i < size; i++)
00079 indices.push_back(i);
00080
00081
00082 quickSort(indices, 0, size-1, &Q, -1, NULL);
00083
00084
00085
00086 int numDomIndividuals = 0;
00087 for (int i = 0; i < size; i++)
00088 {
00089
00090 if (Q[indices[i]]->numDominating == 0)
00091 break;
00092
00093 numDomIndividuals++;
00094 }
00095
00096 int numToDiscard = size - mu;
00097 if (numDomIndividuals >= numToDiscard)
00098 {
00099 #ifdef DEBUG
00100 cout << "NSGA_II::select(), using dominating points selection" << endl;
00101 #endif
00102
00103
00104 P.clear();
00105 for (unsigned i = 0; i < mu; i++)
00106 {
00107 P.push_back(Q[indices[size-1 - i]]);
00108 Q[indices[size-1 - i]] = NULL;
00109 }
00110
00111 ready = true;
00112 }
00113 }
00114
00115
00116 if (!ready)
00117 {
00118 #ifdef DEBUG
00119 cout << "NSGA_II::select(), using front based selection" << endl;
00120 #endif
00121
00122 int PSize, frontSize, remaining, numFronts = front.size();
00123 P.clear();
00124 for (int i = 0; i < numFronts; i++)
00125 {
00126 PSize = P.size();
00127 frontSize = front[i].size();
00128
00129 if ((unsigned) PSize == mu)
00130 break;
00131
00132 if ((unsigned) (PSize + frontSize) <= mu)
00133 {
00134 remaining = frontSize;
00135 }
00136 else
00137 {
00138 remaining = mu - PSize;
00139
00140 if (selectDimension > 1)
00141 frontSort(front[i], Q, direction);
00142 }
00143
00144
00145 for (int j = 0; j < remaining; j++)
00146 {
00147 P.push_back(Q[front[i][j]]);
00148 Q[front[i][j]] = NULL;
00149 }
00150 }
00151 }
00152
00153
00154 for (int i = 0; i < size; i++)
00155 delete Q[i];
00156 }
00157
00158
00159
00160
00161
00162
00163
00164 void NSGA_II::fastNondominatedSort(vector<Individual*>& Q, vector<vector<int> >& front, vector<int>& direction, vector<double>& bestF)
00165 {
00166 #ifdef DEBUG
00167 cout << "NSGA_II::fastNondominatedSort()" << endl;
00168 #endif
00169
00170 int size = Q.size();
00171 unsigned tempNumDom;
00172 map<int, vector<int> > dominates;
00173 map<int, unsigned> numDominating;
00174 vector<int> tempDom, tempFront;
00175 MOComparison result;
00176
00177 for (int i = 0; i < size; i++)
00178 {
00179 tempDom.clear();
00180 tempNumDom = 0;
00181
00182 for (int j = 0; j < size; j++)
00183 {
00184 if (i == j)
00185 continue;
00186
00187 result = compare(Q[i], Q[j], direction, bestF, false, false);
00188
00189 if (result == _Dominating)
00190 tempDom.push_back(j);
00191 else if (result == _Dominated)
00192 tempNumDom++;
00193 }
00194
00195
00196 if (tempNumDom == 0)
00197 tempFront.push_back(i);
00198
00199 dominates[i] = tempDom;
00200 numDominating[i] = Q[i]->numDominating = tempNumDom;
00201 }
00202
00203 front.push_back(tempFront);
00204
00205 int k = 0, frontSize = front[0].size();
00206 while (!frontSize == 0)
00207 {
00208
00209 tempFront.clear();
00210
00211
00212 for (int i = 0; i < frontSize; i++)
00213 {
00214 size = dominates[front[k][i]].size();
00215 for (int j = 0; j < size; j++)
00216 {
00217 numDominating[dominates[front[k][i]][j]]--;
00218
00219
00220 if (numDominating[dominates[front[k][i]][j]] == 0)
00221 tempFront.push_back(dominates[front[k][i]][j]);
00222 }
00223 }
00224
00225 k++;
00226 front.push_back(tempFront);
00227 frontSize = front[k].size();
00228 }
00229
00230 front.pop_back();
00231 }
00232
00233
00234
00235 MOComparison NSGA_II::compare(Individual* A, Individual* B, vector<int>& direction, vector<double>& bestWorstF, bool determineValues, bool worst)
00236 {
00237 bool better = false,
00238 worse = false;
00239
00240
00241 for (unsigned i = 0; i < selectDimension; i++)
00242 {
00243 if (direction[selectFunction[i]] == 1 || (direction[selectFunction[i]] == -1 && worst))
00244 {
00245 if (A->F[selectFunction[i]] > B->F[selectFunction[i]])
00246 {
00247 better = true;
00248
00249 if (A->F[selectFunction[i]] > bestWorstF[selectFunction[i]] && (A->feasible || determineValues))
00250 bestWorstF[selectFunction[i]] = A->F[selectFunction[i]];
00251 }
00252 else if (A->F[selectFunction[i]] < B->F[selectFunction[i]])
00253 {
00254 worse = true;
00255
00256 if (B->F[selectFunction[i]] > bestWorstF[selectFunction[i]] && (B->feasible || determineValues))
00257 bestWorstF[selectFunction[i]] = B->F[selectFunction[i]];
00258 }
00259 else
00260 {
00261 if (A->F[selectFunction[i]] > bestWorstF[selectFunction[i]] && (A->feasible || determineValues))
00262 bestWorstF[selectFunction[i]] = A->F[selectFunction[i]];
00263 }
00264 }
00265 else if (direction[selectFunction[i]] == -1 || (direction[selectFunction[i]] == 1 && worst))
00266 {
00267 if (A->F[selectFunction[i]] < B->F[selectFunction[i]])
00268 {
00269 better = true;
00270
00271 if (A->F[selectFunction[i]] < bestWorstF[selectFunction[i]] && (A->feasible || determineValues))
00272 bestWorstF[selectFunction[i]] = A->F[selectFunction[i]];
00273 }
00274 else if (A->F[selectFunction[i]] > B->F[selectFunction[i]])
00275 {
00276 worse = true;
00277
00278 if (B->F[selectFunction[i]] < bestWorstF[selectFunction[i]] && (B->feasible || determineValues))
00279 bestWorstF[selectFunction[i]] = B->F[selectFunction[i]];
00280 }
00281 else
00282 {
00283 if (A->F[selectFunction[i]] < bestWorstF[selectFunction[i]] && (A->feasible || determineValues))
00284 bestWorstF[selectFunction[i]] = A->F[selectFunction[i]];
00285 }
00286 }
00287
00288 if (better && worse && !determineValues)
00289 break;
00290 }
00291
00292 if (worse)
00293 {
00294 if (better)
00295 return _Nondominated;
00296 else
00297 return _Dominated;
00298 }
00299 else
00300 {
00301 if (better)
00302 return _Dominating;
00303 else
00304 return _Equals;
00305 }
00306 }
00307
00308
00309 void NSGA_II::frontSort(vector<int>& currFront, vector<Individual*>& Q, vector<int>& direction)
00310 {
00311 #ifdef DEBUG
00312 cout << "NSGA_II::frontSort(), nD crowding distance sorting" << endl;
00313 #endif
00314
00315 int frontSize = currFront.size();
00316 map<int, double> distance;
00317 double scale;
00318
00319 for (int i = 0; i < frontSize; i++)
00320 distance[currFront[i]] = 0;
00321
00322
00323 for (unsigned i = 0; i < selectDimension; i++)
00324 {
00325
00326 quickSort(currFront, 0, frontSize-1, &Q, selectFunction[i], NULL);
00327
00328
00329 distance[currFront[0]] = DBL_MAX;
00330 distance[currFront[frontSize-1]] = DBL_MAX;
00331
00332
00333 if (fixedNadirIdeal)
00334 {
00335
00336 if (direction[selectFunction[i]] == 1)
00337 scale = ideal[selectFunction[i]] - nadir[selectFunction[i]];
00338 else
00339 scale = nadir[selectFunction[i]] - ideal[selectFunction[i]];
00340 }
00341 else
00342 scale = Q[currFront[0]]->F[selectFunction[i]] - Q[currFront[frontSize-1]]->F[selectFunction[i]];
00343
00344
00345 for (int j = 1; j < frontSize-1; j++)
00346 {
00347 if (scale != 0)
00348 distance[currFront[j]] += (Q[currFront[j-1]]->F[selectFunction[i]] - Q[currFront[j+1]]->F[selectFunction[i]]) / scale;
00349 }
00350 }
00351
00352
00353 quickSort(currFront, 0, frontSize-1, NULL, -1, &distance);
00354 }
00355
00356
00357 void NSGA_II::quickSort(vector<int>& currFront, int top, int bottom,
00358 vector<Individual*>* Q, int objective, map<int, double>* distance)
00359 {
00360 #ifdef DEBUG
00361 cout << "NSGA_II::quickSort(), sorting on " << ((Q != NULL) ? ((objective >= 0) ? "objective " + itos(objective) : "numDominating")
00362 : "distance") << endl;
00363 #endif
00364
00365
00366
00367
00368 int middle;
00369 if (top < bottom)
00370 {
00371 middle = partition(currFront, top, bottom, Q, objective, distance);
00372 quickSort(currFront, top, middle, Q, objective, distance);
00373 quickSort(currFront, middle+1, bottom, Q, objective, distance);
00374 }
00375 }
00376
00377 int NSGA_II::partition(vector<int>& currFront, int top, int bottom,
00378 vector<Individual*>* Q, int objective, map<int, double>* distance)
00379 {
00380 #ifdef DEBUG
00381 cout << "NSGA_II::partition(), top=" << top << ", bottom=" << bottom << endl;
00382 #endif
00383
00384 int temp,
00385 i = top - 1,
00386 j = bottom + 1;
00387
00388 double x = (Q != NULL) ? ((objective >= 0) ? Q->at(currFront[top])->F[objective] : Q->at(currFront[top])->numDominating)
00389 : distance->find(currFront[top])->second;
00390
00391 do
00392 {
00393 do
00394 {
00395 j--;
00396 } while (x > ((Q != NULL) ? ((objective >= 0) ? Q->at(currFront[j])->F[objective] : Q->at(currFront[j])->numDominating)
00397 : distance->find(currFront[j])->second));
00398
00399 do
00400 {
00401 i++;
00402 } while (x < ((Q != NULL) ? ((objective >= 0) ? Q->at(currFront[i])->F[objective] : Q->at(currFront[i])->numDominating)
00403 : distance->find(currFront[i])->second));
00404
00405 if (i < j)
00406 {
00407
00408 temp = currFront[i];
00409 currFront[i] = currFront[j];
00410 currFront[j] = temp;
00411 }
00412 } while (i < j);
00413
00414
00415 return j;
00416 }
00417
00418
00419 void NSGA_II::determineNadirIdeal(vector<int>& currFront, int frontSize, vector<Individual*>& Q, vector<int>& direction)
00420 {
00421 #ifdef DEBUG
00422 cout << "NSGA_II::determineNadirIdeal()" << endl;
00423 #endif
00424
00425 if (fixedNadirIdeal)
00426 return;
00427
00428
00429 for (unsigned i = 0; i < selectDimension; i++)
00430 {
00431 if (direction[selectFunction[i]] == 1)
00432 {
00433 ideal[selectFunction[i]] = 0;
00434 nadir[selectFunction[i]] = DBL_MAX;
00435 }
00436 else
00437 {
00438 ideal[selectFunction[i]] = DBL_MAX;
00439 nadir[selectFunction[i]] = 0;
00440 }
00441 }
00442
00443
00444 for (int i = 0; i < frontSize; i++)
00445 {
00446 for (int j = 0; j < frontSize; j++)
00447 {
00448 if (i == j)
00449 continue;
00450
00451 compare(Q[currFront[i]], Q[currFront[j]], direction, ideal, true, false);
00452 compare(Q[currFront[i]], Q[currFront[j]], direction, nadir, true, true);
00453 }
00454 }
00455 }
00456