21 #include "gas/nsga2.h"
22 #include "core/reproduction.h"
23 #include "core/genome.h"
24 #include "core/evaluation.h"
27 #include <QThreadPool>
28 #include <QtConcurrentMap>
29 using namespace QtConcurrent;
45 foreach( NSGA2::evaluationThread* e, evalThreads ) {
58 qWarning(
"Setting number of Generations to ZERO!! Check your config file" );
77 d.
describeInt(
"numThreads" ).
limits( 1, 32 ).
help(
"Number of threads to parallelize the evaluation of individuals" );
78 d.
describeInt(
"ngenerations" ).
limits( 1, INT_MAX ).
def( 1000 ).
help(
"Number of the generations of the evolutionary process" );
85 if ( numThreads < 1 ) {
86 qWarning(
"The number of Threads must be greater than one!!" );
89 "NSGA2::setNumThreads",
90 "This method can only called before initialize of NSGA2" );
92 "NSGA2::setNumThreads",
93 "This method must be called after an Evaluation object has been setted by NSGA2::setEvaluation" );
104 this->fitfunc->
setGA(
this );
113 QVector<Evaluation*> ev;
114 foreach( NSGA2::evaluationThread* e, evalThreads ) {
115 ev.append( e->eval );
122 this->reprod->
setGA(
this );
133 "You have to setup the Evaluation object of NSGA2 (Fitness Function)" );
136 "You have to setup the Reproduction operator of NSGA2" );
145 for(
int i=0; i<evalThreads.size(); i++ ) {
146 delete (evalThreads[i]);
149 for(
int i=0; i<numThreadv; i++ ) {
150 evalThreads.append(
new evaluationThread(
this,
fitfunc ) );
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]);
236 case nextGeneration_pass2: {
253 qFatal(
"Default switch in NSGA2::gaStep" );
276 QVector<NSGA2::nsgaGenome> NSGA2::fastNonDominatedSort( nsgaGenome& pareto ) {
277 QMap<nsgaGenotype*, nsgaGenome> dominatedBy;
278 QVector<nsgaGenome> frontsByRank;
279 frontsByRank.resize(1);
281 for(
int p=0; p<pareto.size(); p++ ) {
283 pareto[p]->dominationCounter = 0;
284 for(
int q=0; q<pareto.size(); q++ ) {
285 if ( p==q )
continue;
286 if ( pareto[q]->genotype->dominatedBy( pareto[p]->genotype ) ) {
288 dominatedBy[ pareto[p] ].append( pareto[q] );
289 }
else if ( pareto[p]->genotype->dominatedBy( pareto[q]->genotype ) ) {
290 pareto[p]->dominationCounter++;
294 if ( pareto[p]->dominationCounter == 0 ) {
296 frontsByRank[0].append( pareto[p] );
301 int currentFront = 0;
304 for(
int i=0; i<frontsByRank[currentFront].size(); i++ ) {
305 nsgaGenotype* p = frontsByRank[currentFront][i];
306 nsgaGenome pDominate = dominatedBy[p];
307 for(
int q=0; q<pDominate.size(); q++ ) {
308 pDominate[q]->dominationCounter--;
309 if ( pDominate[q]->dominationCounter == 0 ) {
310 pDominate[q]->rank = currentFront+1;
311 newFront.append( pDominate[q] );
316 if ( newFront.isEmpty() ) {
319 frontsByRank.append( newFront );
323 for(
int i=0; i<frontsByRank.size(); i++ ) {
324 total += frontsByRank[i].size();
329 void NSGA2::crowdingDistanceAssignment( nsgaGenome& genome ) {
330 int dimGenome = genome.size();
331 if ( dimGenome == 0 )
return;
332 int numObjs = genome[0]->genotype->numOfObjectives();
334 QVector<double> fmax;
335 QVector<double> fmin;
336 fmax.resize( numObjs );
337 fmin.resize( numObjs );
338 for(
int i=0; i<numObjs; i++ ) {
339 fmax[i] = genome[0]->genotype->objective( i );
340 fmin[i] = genome[0]->genotype->objective( i );
343 for(
int i=0; i<dimGenome; i++ ) {
344 genome[i]->distance = 0;
345 for(
int m=0; m<numObjs; m++ ) {
346 fmax[m] = qMax( fmax[m], genome[i]->genotype->objective(m) );
347 fmin[m] = qMin( fmin[m], genome[i]->genotype->objective(m) );
351 nObjectiveGreaterThan objCompare;
352 for(
int m=0; m<numObjs; m++ ) {
354 objCompare.currentObjective = m;
355 qStableSort( genome.begin(), genome.end(), objCompare );
358 genome[0]->distance = numObjs;
359 genome.last()->distance = numObjs;
360 for(
int i=1; i<dimGenome-1; i++ ) {
361 double m1 = genome[i+1]->genotype->objective(m);
362 double m2 = genome[i-1]->genotype->objective(m);
363 genome[i]->distance += fabs(m1-m2)/(fmax[m]-fmin[m]);
365 if ( genome[i]->distance != genome[i]->distance ) {
366 genome[i]->distance = 0.0;
372 NSGA2::evaluationThread::evaluationThread( NSGA2* p, Evaluation* eProto )
373 : parent(p), id(0), blocked(false) {
374 eval = eProto->clone();
375 eval->setGenome( p->genome() );
379 NSGA2::evaluationThread::~evaluationThread() {
384 void NSGA2::evaluationThread::runStep() {
389 parent->nextGeneration =
false;
390 eval->evaluateStep();
391 if ( eval->isEvaluationDone() ) {
392 int nextIdSeq = idSeq + 1;
394 if ( nextIdSeq >= sequence.size() ) {
399 int nextId = sequence[ idSeq ];
401 eval->initialize( parent->genome()->at(
id ) );
405 void NSGA2::runStepWrapper( NSGA2::evaluationThread* e ) {