00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "factory.h"
00021 #include "gas/simplega.h"
00022 #include "core/reproduction.h"
00023 #include "core/genome.h"
00024 #include "core/evaluation.h"
00025 #include <QThreadPool>
00026 #include <QtConcurrentMap>
00027 using namespace QtConcurrent;
00028
00029 namespace farsa {
00030
00031 SimpleGA::SimpleGA()
00032 : GeneticAlgo() {
00033 fitfunc = 0;
00034 reprod = 0;
00035 numGens = 0;
00036 currPhase = initEvaluation;
00037 numThreadv = 1;
00038 isInitialized = false;
00039 isFinalized = true;
00040 }
00041
00042 SimpleGA::~SimpleGA() {
00043 foreach( SimpleGA::evaluationThread* e, evalThreads ) {
00044 delete e;
00045 }
00046 delete fitfunc;
00047 }
00048
00049 void SimpleGA::configure( ConfigurationParameters& params, QString prefix ) {
00050 setGenome( params.getObjectFromGroup<Genome>( prefix + QString( "GENOME" ) ) );
00051 setEvaluation( params.getObjectFromGroup<Evaluation>( prefix + QString( "EVALUATION" ) ) );
00052 fitfunc->setGenome( genome() );
00053 setReproduction( params.getObjectFromGroup<Reproduction>( prefix + QString( "REPRODUCTION" ) ) );
00054 setNumGenerations( params.getValue( prefix + QString( "ngenerations" ) ).toInt() );
00055 if ( numGenerations() == 0 ) {
00056 qWarning( "Setting number of Generations to ZERO!! Check your config file" );
00057 }
00058 setNumThreads( params.getValue( prefix + QString( "numThreads" ) ).toInt() );
00059 }
00060
00061 void SimpleGA::save( ConfigurationParameters& params, QString prefix ) {
00062 params.createParameter( prefix, QString("type"), "SimpleGA" );
00063 params.createParameter( prefix, QString("numThreads"), QString("%1").arg( numThreads() ) );
00064 params.createParameter( prefix, QString("ngenerations"), QString("%1").arg( numGenerations() ) );
00065
00066 fitfunc->save( params, params.createSubGroup( prefix, "EVALUATION" ) );
00067
00068 reproduction()->save( params, params.createSubGroup( prefix, "REPRODUCTION" ) );
00069
00070 genome()->save( params, params.createSubGroup( prefix, "GENOME" ) );
00071 }
00072
00073 void SimpleGA::describe( QString type ) {
00074 Descriptor d = addTypeDescription( type, "Simple Genetic Algorithm" );
00075 d.describeInt( "numThreads" ).limits( 1, 32 ).help( "Number of threads to parallelize the evaluation of individuals" );
00076 d.describeInt( "ngenerations" ).limits( 1, INT_MAX ).def( 1000 ).help( "Number of the generations of the evolutionary process" );
00077 d.describeSubgroup( "EVALUATION" ).type( "Evaluation" ).props( IsMandatory ).help( "Object that calculate the fitness", "Create a subclass of Evalution and code your custom fitness function" );
00078 d.describeSubgroup( "REPRODUCTION").type( "Reproduction" ).props( IsMandatory ).help( "Object that generate the new generations" );
00079 d.describeSubgroup( "GENOME" ).type( "Genome" ).props( IsMandatory ).help( "Object containing the individuals under evolution" );
00080 }
00081
00082 void SimpleGA::setNumThreads( int numThreads ) {
00083 if ( numThreads < 1 ) {
00084 qWarning( "The number of Threads must be greater than one!!" );
00085 }
00086 Q_ASSERT_X( !isInitialized && isFinalized ,
00087 "SimpleGA::setNumThreads",
00088 "This method can only called before initialize of SimpleGA" );
00089 Q_ASSERT_X( fitfunc != 0 ,
00090 "SimpleGA::setNumThreads",
00091 "This method must be called after an Evaluation object has been setted by SimpleGA::setEvaluation" );
00092 numThreadv = numThreads;
00093 return;
00094 }
00095
00096 int SimpleGA::numThreads() {
00097 return numThreadv;
00098 }
00099
00100 void SimpleGA::setEvaluation( Evaluation* fitfunc ) {
00101 this->fitfunc = fitfunc;
00102 this->fitfunc->setGA( this );
00103 }
00104
00105 Evaluation* SimpleGA::evaluationPrototype()
00106 {
00107 return fitfunc;
00108 }
00109
00110 QVector<Evaluation*> SimpleGA::evaluationPool() {
00111 QVector<Evaluation*> ev;
00112 foreach( SimpleGA::evaluationThread* e, evalThreads ) {
00113 ev.append( e->eval );
00114 }
00115 return ev;
00116 }
00117
00118 void SimpleGA::setReproduction( Reproduction* reprod ) {
00119 this->reprod = reprod;
00120 this->reprod->setGA( this );
00121 }
00122
00123 Reproduction* SimpleGA::reproduction() {
00124 return reprod;
00125 }
00126
00127 void SimpleGA::initialize() {
00128 if ( isInitialized && !isFinalized ) return;
00129 Q_ASSERT_X( fitfunc != 0 ,
00130 "SimpleGA::initialize",
00131 "You have to setup the Evaluation object of SimpleGA (Fitness Function)" );
00132 Q_ASSERT_X( reprod !=0 ,
00133 "SimpleGA::initialize",
00134 "You have to setup the Reproduction operator of SimpleGA" );
00135
00136 isInitialized = true;
00137 isFinalized = false;
00138 setGeneration( 0 );
00139 currPhase = initEvaluation;
00140 evolutionEnd = false;
00141 evaluationDone = false;
00142
00143 for( int i=0; i<evalThreads.size(); i++ ) {
00144 delete (evalThreads[i]);
00145 }
00146 evalThreads.clear();
00147 for( int i=0; i<numThreadv; i++ ) {
00148 evalThreads.append( new evaluationThread( this, fitfunc ) );
00149 }
00150
00151 QThreadPool::globalInstance()->setMaxThreadCount( numThreadv );
00152 }
00153
00154 void SimpleGA::gaStep() {
00155 switch( currPhase ) {
00156 case initEvaluation:
00157 for( int i=0; i<numThreadv; i++ ) {
00158 evalThreads[i]->sequence.clear();
00159 }
00160 for( int i=0; i<(int)genome()->size(); i++ ) {
00161 evalThreads[ i%numThreadv ]->sequence.append( i );
00162 }
00163 for( int i=0; i<numThreadv; i++ ) {
00164 evalThreads[i]->idSeq = 0;
00165 evalThreads[i]->id = evalThreads[i]->sequence[ evalThreads[i]->idSeq ];
00166 evalThreads[i]->eval->setGenome( genome() );
00167 evalThreads[i]->eval->initialize( genome()->at( evalThreads[i]->id ) );
00168 evalThreads[i]->blocked = false;
00169 }
00170 currPhase = evaluating;
00171 break;
00172 case evaluating: {
00173 nextGeneration = true;
00174 if ( numThreadv == 1 ) {
00175
00176 evalThreads[0]->runStep();
00177 } else {
00178 QFuture<void> future = map( evalThreads, SimpleGA::runStepWrapper );
00179 future.waitForFinished();
00180 }
00181 if ( nextGeneration ) {
00182 currPhase = nextGeneration_pass1;
00183 }
00184 }
00185 break;
00186 case nextGeneration_pass1:
00187 qSort( genome()->begin(), genome()->end(), Genotype::rankGreaterThanComparator );
00188 updateStats();
00189 evaluationDone = true;
00190 if ( generation() < numGens ) {
00191 currPhase = nextGeneration_pass2;
00192 } else {
00193 currPhase = endEvolution;
00194 }
00195 break;
00196 case nextGeneration_pass2: {
00197
00198
00199
00200 Genome* old = genome();
00201 setGenome( reprod->reproduction( old ) );
00202 delete old;
00203 fitfunc->setGenome( genome() );
00204 evaluationDone = false;
00205 setGeneration( generation()+1 );
00206 currPhase = initEvaluation;
00207 }
00208 break;
00209 case endEvolution:
00210 finalize();
00211 break;
00212 default:
00213 qFatal( "Default switch in SimpleGA::gaStep" );
00214 break;
00215 }
00216 }
00217
00218 void SimpleGA::skipEvaluation() {
00219
00220 evaluationDone = true;
00221 if ( generation() < numGens ) {
00222 currPhase = nextGeneration_pass2;
00223 } else {
00224 currPhase = endEvolution;
00225 }
00226 }
00227
00228 void SimpleGA::finalize() {
00229 if ( isFinalized && !isInitialized ) return;
00230
00231 isInitialized = false;
00232 isFinalized = true;
00233 evolutionEnd = true;
00234 }
00235
00236 SimpleGA::evaluationThread::evaluationThread( SimpleGA* p, Evaluation* eProto )
00237 : parent(p), id(0), blocked(false) {
00238 eval = eProto->clone();
00239 eval->setGenome( p->genome() );
00240 eval->setGA( p );
00241 }
00242
00243 SimpleGA::evaluationThread::~evaluationThread() {
00244 delete eval;
00245 sequence.clear();
00246 }
00247
00248 void SimpleGA::evaluationThread::runStep() {
00249 if ( blocked ) {
00250 return;
00251 }
00252
00253 parent->nextGeneration = false;
00254 eval->evaluateStep();
00255 if ( eval->isEvaluationDone() ) {
00256 int nextIdSeq = idSeq + 1;
00257 eval->finalize();
00258 eval->genotype()->setRank( eval->genotype()->fitness() );
00259 if ( nextIdSeq >= sequence.size() ) {
00260 blocked = true;
00261 return;
00262 }
00263 idSeq = nextIdSeq;
00264 int nextId = sequence[ idSeq ];
00265 id = nextId;
00266 eval->initialize( parent->genome()->at( id ) );
00267 }
00268 }
00269
00270 void SimpleGA::runStepWrapper( SimpleGA::evaluationThread* e ) {
00271 e->runStep();
00272 }
00273
00274 }