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 ) {
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" );
144 for(
int i=0; i<evalThreads.size(); i++ ) {
145 delete (evalThreads[i]);
148 for(
int i=0; i<numThreadv; i++ ) {
149 evalThreads.append(
new evaluationThread(
this,
fitfunc ) );
150 evalThreads.last()->eval->initGeneration(
generation() );
153 QThreadPool::globalInstance()->setMaxThreadCount( numThreadv );
159 for(
int i=0; i<numThreadv; i++ ) {
160 evalThreads[i]->sequence.clear();
162 for(
int i=0; i<(int)
genome()->
size(); i++ ) {
163 evalThreads[ i%numThreadv ]->sequence.append( i );
165 for(
int i=0; i<numThreadv; i++ ) {
166 evalThreads[i]->idSeq = 0;
167 evalThreads[i]->id = evalThreads[i]->sequence[ evalThreads[i]->idSeq ];
168 evalThreads[i]->eval->setGenome(
genome() );
169 evalThreads[i]->eval->initialize(
genome()->at( evalThreads[i]->
id ) );
170 evalThreads[i]->blocked =
false;
175 nextGeneration =
true;
176 if ( numThreadv == 1 ) {
178 evalThreads[0]->runStep();
180 QFuture<void> future = map( evalThreads, NSGA2::runStepWrapper );
181 future.waitForFinished();
183 if ( nextGeneration ) {
188 case nextGeneration_pass1: {
192 nsgaGenome allGenome;
193 for(
unsigned int i=0; i<lastPareto.
size(); i++ ) {
194 allGenome.append(
new nsgaGenotype( lastPareto.
at(i), 0, 0.0 ) );
196 for(
unsigned int i=0; i<
genome()->
size(); i++ ) {
197 allGenome.append(
new nsgaGenotype(
genome()->at(i), 0, 0.0 ) );
201 QVector<nsgaGenome> frontsByRank = fastNonDominatedSort( allGenome );
204 unsigned int currentGenotype = 0;
205 int numOfFronts = frontsByRank.size();
206 int numObjs = allGenome[0]->genotype->numOfObjectives();
207 for(
int front=0; front<numOfFronts; front++ ) {
209 crowdingDistanceAssignment( frontsByRank[front] );
210 qStableSort( frontsByRank[front].begin(), frontsByRank[front].end(), NSGA2::crowdingDistanceGreaterThan );
211 foreach( nsgaGenotype* gen, frontsByRank[front] ) {
213 gen->genotype->setRank( 2*(numOfFronts - front) + (gen->distance/numObjs) );
214 genome()->
set( currentGenotype, gen->genotype );
216 if ( currentGenotype ==
genome()->size() )
break;
218 if ( currentGenotype ==
genome()->size() )
break;
224 for(
int i=0; i<allGenome.size(); i++ ) {
225 delete (allGenome[i]);
229 for(
int i=0; i<numThreadv; i++ ) {
230 evalThreads[i]->eval->endGeneration(
generation() );
241 case nextGeneration_pass2: {
251 for(
int i=0; i<numThreadv; i++ ) {
252 evalThreads[i]->eval->initGeneration(
generation() );
261 qFatal(
"Default switch in NSGA2::gaStep" );
284 QVector<NSGA2::nsgaGenome> NSGA2::fastNonDominatedSort( nsgaGenome& pareto ) {
285 QMap<nsgaGenotype*, nsgaGenome> dominatedBy;
286 QVector<nsgaGenome> frontsByRank;
287 frontsByRank.resize(1);
289 for(
int p=0; p<pareto.size(); p++ ) {
291 pareto[p]->dominationCounter = 0;
292 for(
int q=0; q<pareto.size(); q++ ) {
293 if ( p==q )
continue;
294 if ( pareto[q]->genotype->dominatedBy( pareto[p]->genotype ) ) {
296 dominatedBy[ pareto[p] ].append( pareto[q] );
297 }
else if ( pareto[p]->genotype->dominatedBy( pareto[q]->genotype ) ) {
298 pareto[p]->dominationCounter++;
302 if ( pareto[p]->dominationCounter == 0 ) {
304 frontsByRank[0].append( pareto[p] );
309 int currentFront = 0;
312 for(
int i=0; i<frontsByRank[currentFront].size(); i++ ) {
313 nsgaGenotype* p = frontsByRank[currentFront][i];
314 nsgaGenome pDominate = dominatedBy[p];
315 for(
int q=0; q<pDominate.size(); q++ ) {
316 pDominate[q]->dominationCounter--;
317 if ( pDominate[q]->dominationCounter == 0 ) {
318 pDominate[q]->rank = currentFront+1;
319 newFront.append( pDominate[q] );
324 if ( newFront.isEmpty() ) {
327 frontsByRank.append( newFront );
331 for(
int i=0; i<frontsByRank.size(); i++ ) {
332 total += frontsByRank[i].size();
337 void NSGA2::crowdingDistanceAssignment( nsgaGenome& genome ) {
338 int dimGenome = genome.size();
339 if ( dimGenome == 0 )
return;
340 int numObjs = genome[0]->genotype->numOfObjectives();
342 QVector<double> fmax;
343 QVector<double> fmin;
344 fmax.resize( numObjs );
345 fmin.resize( numObjs );
346 for(
int i=0; i<numObjs; i++ ) {
347 fmax[i] = genome[0]->genotype->objective( i );
348 fmin[i] = genome[0]->genotype->objective( i );
351 for(
int i=0; i<dimGenome; i++ ) {
352 genome[i]->distance = 0;
353 for(
int m=0; m<numObjs; m++ ) {
354 fmax[m] = qMax( fmax[m], genome[i]->genotype->objective(m) );
355 fmin[m] = qMin( fmin[m], genome[i]->genotype->objective(m) );
359 nObjectiveGreaterThan objCompare;
360 for(
int m=0; m<numObjs; m++ ) {
362 objCompare.currentObjective = m;
363 qStableSort( genome.begin(), genome.end(), objCompare );
366 genome[0]->distance = numObjs;
367 genome.last()->distance = numObjs;
368 for(
int i=1; i<dimGenome-1; i++ ) {
369 double m1 = genome[i+1]->genotype->objective(m);
370 double m2 = genome[i-1]->genotype->objective(m);
371 genome[i]->distance += fabs(m1-m2)/(fmax[m]-fmin[m]);
373 if ( genome[i]->distance != genome[i]->distance ) {
374 genome[i]->distance = 0.0;
380 NSGA2::evaluationThread::evaluationThread( NSGA2* p, Evaluation* eProto )
381 : parent(p), id(0), blocked(false) {
382 eval = eProto->clone();
383 eval->setGenome( p->genome() );
387 NSGA2::evaluationThread::~evaluationThread() {
392 void NSGA2::evaluationThread::runStep() {
397 parent->nextGeneration =
false;
398 eval->evaluateStep();
399 if ( eval->isEvaluationDone() ) {
400 int nextIdSeq = idSeq + 1;
402 if ( nextIdSeq >= sequence.size() ) {
407 int nextId = sequence[ idSeq ];
409 eval->initialize( parent->genome()->at(
id ) );
413 void NSGA2::runStepWrapper( NSGA2::evaluationThread* e ) {