21 #include "gas/nsga2.h"
22 #include "core/reproduction.h"
23 #include "core/genome.h"
24 #include "core/evaluation.h"
25 #include "configurationhelper.h"
28 #include <QThreadPool>
29 #include <QtConcurrentMap>
30 using namespace QtConcurrent;
46 foreach( NSGA2::evaluationThread* e, evalThreads ) {
75 d.
describeInt(
"numThreads" ).
limits( 1, 32 ).
def(1).
help(
"Number of threads to parallelize the evaluation of individuals" );
76 d.
describeInt(
"ngenerations" ).
limits( 1, INT_MAX ).
def( 1000 ).
help(
"Number of the generations of the evolutionary process" );
83 if ( numThreads < 1 ) {
84 qWarning(
"The number of Threads must be greater than one!!" );
87 "NSGA2::setNumThreads",
88 "This method can only called before initialize of NSGA2" );
90 "NSGA2::setNumThreads",
91 "This method must be called after an Evaluation object has been setted by NSGA2::setEvaluation" );
102 this->fitfunc->
setGA(
this );
111 QVector<Evaluation*> ev;
112 foreach( NSGA2::evaluationThread* e, evalThreads ) {
113 ev.append( e->eval );
120 this->reprod->
setGA(
this );
131 "You have to setup the Evaluation object of NSGA2 (Fitness Function)" );
134 "You have to setup the Reproduction operator of NSGA2" );
143 for(
int i=0; i<evalThreads.size(); i++ ) {
144 delete (evalThreads[i]);
147 for(
int i=0; i<numThreadv; i++ ) {
148 evalThreads.append(
new evaluationThread(
this,
fitfunc ) );
149 evalThreads.last()->eval->initGeneration(0);
152 QThreadPool::globalInstance()->setMaxThreadCount( numThreadv );
158 for(
int i=0; i<numThreadv; i++ ) {
159 evalThreads[i]->sequence.clear();
161 for(
int i=0; i<(int)
genome()->
size(); i++ ) {
162 evalThreads[ i%numThreadv ]->sequence.append( i );
164 for(
int i=0; i<numThreadv; i++ ) {
165 evalThreads[i]->idSeq = 0;
166 evalThreads[i]->id = evalThreads[i]->sequence[ evalThreads[i]->idSeq ];
167 evalThreads[i]->eval->setGenome(
genome() );
168 evalThreads[i]->eval->initialize(
genome()->at( evalThreads[i]->
id ) );
169 evalThreads[i]->blocked =
false;
174 nextGeneration =
true;
175 if ( numThreadv == 1 ) {
177 evalThreads[0]->runStep();
179 QFuture<void> future = map( evalThreads, NSGA2::runStepWrapper );
180 future.waitForFinished();
182 if ( nextGeneration ) {
187 case nextGeneration_pass1: {
191 nsgaGenome allGenome;
192 for(
unsigned int i=0; i<lastPareto.
size(); i++ ) {
193 allGenome.append(
new nsgaGenotype( lastPareto.
at(i), 0, 0.0 ) );
195 for(
unsigned int i=0; i<
genome()->
size(); i++ ) {
196 allGenome.append(
new nsgaGenotype(
genome()->at(i), 0, 0.0 ) );
200 QVector<nsgaGenome> frontsByRank = fastNonDominatedSort( allGenome );
203 unsigned int currentGenotype = 0;
204 int numOfFronts = frontsByRank.size();
205 int numObjs = allGenome[0]->genotype->numOfObjectives();
206 for(
int front=0; front<numOfFronts; front++ ) {
208 crowdingDistanceAssignment( frontsByRank[front] );
209 qStableSort( frontsByRank[front].begin(), frontsByRank[front].end(), NSGA2::crowdingDistanceGreaterThan );
210 foreach( nsgaGenotype* gen, frontsByRank[front] ) {
212 gen->genotype->setRank( 2*(numOfFronts - front) + (gen->distance/numObjs) );
213 genome()->
set( currentGenotype, gen->genotype );
215 if ( currentGenotype ==
genome()->size() )
break;
217 if ( currentGenotype ==
genome()->size() )
break;
223 for(
int i=0; i<allGenome.size(); i++ ) {
224 delete (allGenome[i]);
228 for(
int i=0; i<numThreadv; i++ ) {
229 evalThreads[i]->eval->endGeneration(
generation() );
238 case nextGeneration_pass2: {
248 for(
int i=0; i<numThreadv; i++ ) {
249 evalThreads[i]->eval->initGeneration(
generation() );
258 qFatal(
"Default switch in NSGA2::gaStep" );
281 QVector<NSGA2::nsgaGenome> NSGA2::fastNonDominatedSort( nsgaGenome& pareto ) {
282 QMap<nsgaGenotype*, nsgaGenome> dominatedBy;
283 QVector<nsgaGenome> frontsByRank;
284 frontsByRank.resize(1);
286 for(
int p=0; p<pareto.size(); p++ ) {
288 pareto[p]->dominationCounter = 0;
289 for(
int q=0; q<pareto.size(); q++ ) {
290 if ( p==q )
continue;
291 if ( pareto[q]->genotype->dominatedBy( pareto[p]->genotype ) ) {
293 dominatedBy[ pareto[p] ].append( pareto[q] );
294 }
else if ( pareto[p]->genotype->dominatedBy( pareto[q]->genotype ) ) {
295 pareto[p]->dominationCounter++;
299 if ( pareto[p]->dominationCounter == 0 ) {
301 frontsByRank[0].append( pareto[p] );
306 int currentFront = 0;
309 for(
int i=0; i<frontsByRank[currentFront].size(); i++ ) {
310 nsgaGenotype* p = frontsByRank[currentFront][i];
311 nsgaGenome pDominate = dominatedBy[p];
312 for(
int q=0; q<pDominate.size(); q++ ) {
313 pDominate[q]->dominationCounter--;
314 if ( pDominate[q]->dominationCounter == 0 ) {
315 pDominate[q]->rank = currentFront+1;
316 newFront.append( pDominate[q] );
321 if ( newFront.isEmpty() ) {
324 frontsByRank.append( newFront );
328 for(
int i=0; i<frontsByRank.size(); i++ ) {
329 total += frontsByRank[i].size();
334 void NSGA2::crowdingDistanceAssignment( nsgaGenome& genome ) {
335 int dimGenome = genome.size();
336 if ( dimGenome == 0 )
return;
337 int numObjs = genome[0]->genotype->numOfObjectives();
339 QVector<double> fmax;
340 QVector<double> fmin;
341 fmax.resize( numObjs );
342 fmin.resize( numObjs );
343 for(
int i=0; i<numObjs; i++ ) {
344 fmax[i] = genome[0]->genotype->objective( i );
345 fmin[i] = genome[0]->genotype->objective( i );
348 for(
int i=0; i<dimGenome; i++ ) {
349 genome[i]->distance = 0;
350 for(
int m=0; m<numObjs; m++ ) {
351 fmax[m] = qMax( fmax[m], genome[i]->genotype->objective(m) );
352 fmin[m] = qMin( fmin[m], genome[i]->genotype->objective(m) );
356 nObjectiveGreaterThan objCompare;
357 for(
int m=0; m<numObjs; m++ ) {
359 objCompare.currentObjective = m;
360 qStableSort( genome.begin(), genome.end(), objCompare );
363 genome[0]->distance = numObjs;
364 genome.last()->distance = numObjs;
365 for(
int i=1; i<dimGenome-1; i++ ) {
366 double m1 = genome[i+1]->genotype->objective(m);
367 double m2 = genome[i-1]->genotype->objective(m);
368 genome[i]->distance += fabs(m1-m2)/(fmax[m]-fmin[m]);
370 if ( genome[i]->distance != genome[i]->distance ) {
371 genome[i]->distance = 0.0;
377 NSGA2::evaluationThread::evaluationThread( NSGA2* p, Evaluation* eProto )
378 : parent(p), id(0), blocked(false) {
379 eval = eProto->clone();
380 eval->setGenome( p->genome() );
384 NSGA2::evaluationThread::~evaluationThread() {
389 void NSGA2::evaluationThread::runStep() {
394 parent->nextGeneration =
false;
395 eval->evaluateStep();
396 if ( eval->isEvaluationDone() ) {
397 int nextIdSeq = idSeq + 1;
399 if ( nextIdSeq >= sequence.size() ) {
404 int nextId = sequence[ idSeq ];
406 eval->initialize( parent->genome()->at(
id ) );
410 void NSGA2::runStepWrapper( NSGA2::evaluationThread* e ) {