00001 #include "SIGEL_GP/SIG_GPManager.h"
00002
00003 #include <qarray.h>
00004 #include <qfile.h>
00005 #include <qdir.h>
00006 #include "SIGEL_Tools/SIG_IO.h"
00007 #include "SIGEL_GP/SIG_GPMutationTournament.h"
00008 #include "SIGEL_GP/SIG_GPSimpleTournament.h"
00009 #include "SIGEL_GP/SIG_GPCrossOverTournament.h"
00010 #include "SIGEL_GP/SIG_GPExperimentHistoryEntry.h"
00011
00012 SIGEL_GP::SIG_GPManager::SIG_GPManager(SIGEL_GP::SIG_GPExperiment &experiment)
00013 : actExperiment( experiment ),
00014 taskCanDoList(),
00015 tours(),
00016 userTerminated( false ),
00017 currentGenerationNo(0),
00018 randomizer( actExperiment.gpParameter.getRandomSeed() ),
00019 trainer( actExperiment ),
00020 schlussJetzt( false ),
00021 fitnessCalculated( false )
00022 {
00023 tours.setAutoDelete( true );
00024 };
00025
00026
00027
00028 SIGEL_GP::SIG_GPFitnessTrainer &SIGEL_GP::SIG_GPManager::getActTrainer()
00029 {
00030 return trainer;
00031 };
00032
00033
00034 SIGEL_GP::SIG_GPExperiment &SIGEL_GP::SIG_GPManager::getActExperiment()
00035 {
00036 return actExperiment;
00037 };
00038
00039 void SIGEL_GP::SIG_GPManager::evolutionLoop()
00040 {
00041 int maxTouchsPerLoop = actExperiment.gpParameter.getMaxTouchsPerLoop();
00042 int toDoSweepsPerLoop = actExperiment.gpParameter.getToDoSweepsPerLoop();
00043
00044 SIG_GPPopulation &pop = actExperiment.population;
00045
00046 while ( !taskCanDoList.isEmpty() )
00047 {
00048
00049 stopIfNecessary( false );
00050
00051 if (schlussJetzt)
00052 return;
00053
00054 haveABreak();
00055
00056 trainer.sweepToSpawn();
00057
00058 for (int sweepCounter = 0;
00059 (sweepCounter < toDoSweepsPerLoop) && (!taskCanDoList.isEmpty());
00060 sweepCounter++)
00061 {
00062
00063 #ifdef SIG_DEBUG
00064 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager sweeping the taskCanDoList (sweepCounter: "
00065 << sweepCounter
00066 << ").\n";
00067 #endif
00068
00069 int touchsCounter = 0;
00070
00071 QValueListIterator<int> canDoIter = taskCanDoList.begin();
00072
00073 while (canDoIter != taskCanDoList.end())
00074 {
00075 if ((touchsCounter == maxTouchsPerLoop) && (maxTouchsPerLoop != -1))
00076 break;
00077
00078 SIG_GPTournament &actTour=*tours[ *canDoIter ];
00079 int actIndiNumber = actTour.indis.size();
00080
00081 #ifdef SIG_DEBUG
00082 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager inspecting tournament No. "
00083 << *canDoIter
00084 << ".\n"
00085 << "justWaiting: "
00086 << actTour.justWaiting
00087 << "\n"
00088 << "depNumber: "
00089 << actTour.depNumber
00090 << "\n"
00091 << "indis:\n";
00092 for (int i = 0; i < actTour.indis.size(); i++)
00093 SIGEL_Tools::SIG_IO::cerr << " indNumber: "
00094 << (*actTour.indis[ i ]).indNumber
00095 << "\n"
00096 << " successor: "
00097 << (*actTour.indis[ i ]).successor
00098 << "\n"
00099 << " fitTaskId: "
00100 << (*actTour.indis[ i ]).fitTaskId
00101 << "\n";
00102 #endif
00103
00104 if (!actTour.justWaiting)
00105 {
00106 #ifdef SIG_DEBUG
00107 SIGEL_Tools::SIG_IO::cerr << "Playing tournament "
00108 << *canDoIter
00109 << "\n";
00110 #endif
00111
00112 actTour.run();
00113
00114 for (int i = 0; i < actIndiNumber; i++)
00115 {
00116 SIG_GPIndividual &actInd = pop.getIndividual( actTour.indis[i]->indNumber );
00117
00118 if (actInd.upToDate())
00119 {
00120 #ifdef SIG_DEBUG
00121 SIGEL_Tools::SIG_IO::cerr << "Individual "
00122 << actInd.getPoolPos()
00123 << " is up to date.\n";
00124 #endif
00125
00126 int actSuccessor = actTour.indis[i]->successor;
00127 if (actSuccessor != -1)
00128 {
00129 tours[ actSuccessor ]->depNumber -= 1;
00130 if( tours[ actSuccessor ]->depNumber == 0 )
00131 {
00132 taskCanDoList << actSuccessor;
00133 };
00134 };
00135 }
00136 else
00137 {
00138 #ifdef SIG_DEBUG
00139 SIGEL_Tools::SIG_IO::cerr << "Individual "
00140 << actInd.getPoolPos()
00141 << " is not up to date.\n";
00142 #endif
00143
00144 actTour.justWaiting = true;
00145 actTour.indis[i]->fitTaskId = trainer.spawnTask( actInd );
00146 updateIndividualView( actTour.indis[i]->indNumber );
00147 };
00148
00149 updateIndividualView( actTour.indis[i]->indNumber );
00150
00151 };
00152 }
00153 else
00154 {
00155 actTour.justWaiting = false;
00156
00157 for (int j=0; j<actIndiNumber; j++)
00158 {
00159 SIG_GPTournamentIndividual &actTourInd = *actTour.indis[j];
00160
00161 if (actTourInd.fitTaskId != -1)
00162 {
00163 double actFitness = trainer.checkTask( actTourInd.fitTaskId );
00164 if (actFitness != -1)
00165 {
00166 SIG_GPIndividual &actInd = pop.getIndividual( actTourInd.indNumber );
00167 actInd.setFitness( actFitness );
00168 updateIndividualView( actTourInd.indNumber );
00169 actTourInd.fitTaskId = -1;
00170
00171 int actSuccessor = actTourInd.successor;
00172 if (actSuccessor != -1)
00173 {
00174 tours[ actSuccessor ]->depNumber -= 1;
00175 if (tours[ actSuccessor ]->depNumber == 0)
00176 taskCanDoList << actSuccessor;
00177 };
00178 }
00179 else
00180 actTour.justWaiting = true;
00181 };
00182 };
00183 };
00184 if (!actTour.justWaiting)
00185 canDoIter = taskCanDoList.remove( canDoIter );
00186 else
00187 ++canDoIter;
00188
00189 touchsCounter++;
00190 };
00191 };
00192 };
00193 };
00194
00195 void SIGEL_GP::SIG_GPManager::createTours(int quantity)
00196 {
00197
00198 #ifdef SIG_DEBUG
00199 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager creates "
00200 << quantity
00201 << " Tournaments.\n";
00202 #endif
00203
00204
00205
00206 SIG_GPPopulation &pop = actExperiment.population;
00207
00208
00209 tours.clear();
00210 tours.resize(quantity);
00211
00212 for(int i=0;i<quantity;i++)
00213 {
00214 QArray< int > poolPositions( 2 );
00215
00216 poolPositions[0] = randomizer.getRandomInt( pop.getSize() );
00217 poolPositions[1] = randomizer.getRandomInt( pop.getSize() - 1 );
00218
00219 poolPositions[1] = (poolPositions[1] >= poolPositions[0]) ? poolPositions[1] + 1 : poolPositions[1];
00220
00221 int totalProbCount = actExperiment.gpParameter.getReproductionProb()
00222 + actExperiment.gpParameter.getMutationProb()
00223 + actExperiment.gpParameter.getXoverProb();
00224
00225
00226 if (!totalProbCount)
00227 {
00228 SIGEL_Tools::SIG_IO::cerr << "Cannot create tournaments - bad probabilities!\n";
00229 return;
00230 };
00231
00232 int randomResult = randomizer.getRandomInt( totalProbCount ) + 1;
00233
00234 SIG_GPTournament *actTour = 0;
00235
00236 if (randomResult <= actExperiment.gpParameter.getReproductionProb())
00237 {
00238
00239 #ifdef SIG_DEBUG
00240 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager creates a Simple Tournament.\n"
00241 << "Player's positions are "
00242 << poolPositions[0]
00243 << " and "
00244 << poolPositions[1]
00245 << ".\n";
00246 #endif
00247
00248 actTour = new SIG_GPSimpleTournament(randomizer,
00249 trainer,
00250 pop,
00251 actExperiment.gpParameter,
00252 *actExperiment.robot.getLangParam(),
00253 poolPositions[0],
00254 poolPositions[1]);
00255 }
00256 else if ( randomResult <= actExperiment.gpParameter.getReproductionProb()
00257 + actExperiment.gpParameter.getMutationProb() )
00258 {
00259
00260 #ifdef SIG_DEBUG
00261 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager creates a Mutation Tournament.\n"
00262 << "Player's positions are "
00263 << poolPositions[0]
00264 << " and "
00265 << poolPositions[1]
00266 << ".\n";
00267 #endif
00268
00269 actTour = new SIG_GPMutationTournament(randomizer,
00270 trainer,
00271 pop,
00272 actExperiment.gpParameter,
00273 *actExperiment.robot.getLangParam(),
00274 poolPositions[0],
00275 poolPositions[1]);
00276 }
00277 else
00278 {
00279 int newPoolPos = randomizer.getRandomInt( pop.getSize() - 2 );
00280
00281 poolPositions.sort();
00282
00283 newPoolPos = (newPoolPos >= poolPositions[0]) ? newPoolPos + 1 : newPoolPos;
00284 newPoolPos = (newPoolPos >= poolPositions[1]) ? newPoolPos + 1 : newPoolPos;
00285
00286 poolPositions.resize( 3 );
00287 poolPositions[2] = newPoolPos;
00288 poolPositions.sort();
00289
00290 newPoolPos = randomizer.getRandomInt( pop.getSize() - 3 );
00291
00292 newPoolPos = (newPoolPos >= poolPositions[0]) ? newPoolPos + 1 : newPoolPos;
00293 newPoolPos = (newPoolPos >= poolPositions[1]) ? newPoolPos + 1 : newPoolPos;
00294 newPoolPos = (newPoolPos >= poolPositions[2]) ? newPoolPos + 1 : newPoolPos;
00295
00296 poolPositions.resize( 4 );
00297 poolPositions[3] = newPoolPos;
00298
00299 #ifdef SIG_DEBUG
00300 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager creates a Crossover Tournament.\n"
00301 << "Player's positions are "
00302 << poolPositions[0]
00303 << ", "
00304 << poolPositions[1]
00305 << ", "
00306 << poolPositions[2]
00307 << " and "
00308 << poolPositions[3]
00309 << ".\n";
00310 #endif
00311
00312 actTour = new SIG_GPCrossOverTournament(randomizer,
00313 trainer,
00314 pop,
00315 actExperiment.gpParameter,
00316 *actExperiment.robot.getLangParam(),
00317 poolPositions[0],
00318 poolPositions[1],
00319 poolPositions[2],
00320 poolPositions[3]);
00321 };
00322
00323 tours.insert( i, actTour );
00324 };
00325 };
00326
00327 void SIGEL_GP::SIG_GPManager::evalNewIndis()
00328 {
00329
00330 #ifdef SIG_DEBUG
00331 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager evaluates new Individuals.\n";
00332 #endif
00333
00334 QList< QArray<int> > fitTaskList;
00335 fitTaskList.setAutoDelete( true );
00336
00337
00338 SIG_GPPopulation &pop=actExperiment.population;
00339
00340
00341 int poolSize=pop.getSize();
00342
00343 for (int i=0;i<poolSize;i++)
00344 {
00345 stopIfNecessary( true );
00346
00347 if (schlussJetzt)
00348 return;
00349
00350 haveABreak();
00351
00352 SIG_GPIndividual &actInd=pop.getIndividual(i);
00353
00354 bool upToDate = actInd.upToDate();
00355
00356
00357 if(!upToDate)
00358 {
00359
00360 #ifdef SIG_DEBUG
00361 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager: Individual Number "
00362 << i
00363 << " hasn't an actual fitness value and will be evaluated.\n";
00364 #endif
00365
00366 QArray<int> *actFitTask = new QArray<int>(2);
00367 (*actFitTask)[0] = trainer.spawnTask(actInd);
00368 (*actFitTask)[1] = actInd.getPoolPos();
00369
00370 fitTaskList.append( actFitTask );
00371 };
00372 };
00373
00374 while (!fitTaskList.isEmpty())
00375 {
00376
00377 #ifdef SIG_DEBUG
00378 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager entering loop sweeping the fitTaskList\n";
00379 #endif
00380
00381 stopIfNecessary( true );
00382
00383 if (schlussJetzt)
00384 return;
00385
00386 haveABreak();
00387
00388 trainer.sweepToSpawn();
00389 QArray<int> *actFitTask = fitTaskList.first();
00390 QArray<int> *prevFitTask = 0;
00391
00392 while (actFitTask)
00393 {
00394 double actFitness = trainer.checkTask( (*actFitTask)[0] );
00395
00396 #ifdef SIG_DEBUG
00397 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager checking task "
00398 << (*actFitTask)[0]
00399 << ", has fitness "
00400 << actFitness
00401 << ".\n";
00402 #endif
00403
00404 if (actFitness != -1)
00405 {
00406
00407 #ifdef SIG_DEBUG
00408 SIGEL_Tools::SIG_IO::cerr << "Fitness is ready.\n";
00409 #endif
00410
00411 pop.getIndividual( (*actFitTask)[1] ).setFitness( actFitness );
00412 updateIndividualView( (*actFitTask)[1] );
00413
00414 fitTaskList.remove();
00415 actFitTask = fitTaskList.current();
00416 if (actFitTask == prevFitTask)
00417 break;
00418 }
00419 else
00420 {
00421
00422 #ifdef SIG_DEBUG
00423 SIGEL_Tools::SIG_IO::cerr << "Fitness is not yet ready.\n";
00424 #endif
00425
00426 prevFitTask = actFitTask;
00427 actFitTask = fitTaskList.next();
00428 };
00429 };
00430 };
00431
00432 fitnessCalculated = true;
00433
00434 };
00435
00436 void SIGEL_GP::SIG_GPManager::calcInitTourSet()
00437 {
00438
00439 #ifdef SIG_DEBUG
00440 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager is calculating the initial set of active tournaments.\n";
00441 #endif
00442
00443 taskCanDoList.clear();
00444
00445
00446 SIG_GPPopulation &pop=getActExperiment().population;
00447
00448 QArray<int> lastAccesses( pop.getSize() );
00449
00450 for (int i=0; i < pop.getSize(); i++)
00451 lastAccesses[i] = -1;
00452
00453 for(int i=0; i < tours.size(); i++)
00454 {
00455
00456 #ifdef SIG_DEBUG
00457 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager inspecting tournament "
00458 << i << ".\n";
00459 #endif
00460
00461
00462 SIG_GPTournament &actTour=*tours[i];
00463
00464 int actIndisNumber=actTour.indis.size();
00465
00466 for (int j=0; j<actIndisNumber; j++)
00467 {
00468
00469 #ifdef SIG_DEBUG
00470 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager inspecting tournament individual"
00471 << j << ".\n";
00472 #endif
00473
00474 SIG_GPTournamentIndividual &actInd = *actTour.indis[j];
00475 int lastAccess = lastAccesses[ actInd.indNumber ];
00476
00477 if (lastAccess != -1)
00478 {
00479 SIG_GPTournament &prevTour = *tours[lastAccess];
00480 int prevIndisNumber = prevTour.indis.size();
00481
00482 for (int k=0; k<prevIndisNumber; k++)
00483 {
00484 SIG_GPTournamentIndividual &prevInd = *prevTour.indis[k];
00485 if ( prevInd.indNumber == actInd.indNumber )
00486 {
00487 prevInd.successor = i;
00488 };
00489 };
00490
00491 actTour.depNumber += 1;
00492 };
00493 lastAccesses[ actInd.indNumber ] = i;
00494 };
00495
00496 if (actTour.depNumber == 0)
00497 taskCanDoList << i;
00498 };
00499 };
00500
00501 void SIGEL_GP::SIG_GPManager::haveABreak()
00502 {
00503
00504 };
00505
00506 void SIGEL_GP::SIG_GPManager::messageEvolutionStop()
00507 {
00508
00509 schlussJetzt = true;
00510 };
00511
00512 void SIGEL_GP::SIG_GPManager::updateIndividualView( int )
00513 { };
00514
00515 void SIGEL_GP::SIG_GPManager::stopIfNecessary(bool generationBreak)
00516 {
00517 if (checkTerminationConditions( generationBreak ))
00518 {
00519 trainer.stopTrainersSlaves();
00520 messageEvolutionStop();
00521 };
00522 };
00523
00524 bool SIGEL_GP::SIG_GPManager::checkTerminationConditions(bool generationBreak)
00525 {
00526 bool exitIsPermitted = (!actExperiment.gpParameter.getSaveExit() || generationBreak);
00527
00528
00529
00530
00531
00532
00533 if (userTerminated)
00534 return true;
00535
00536 if (!fitnessCalculated)
00537 return false;
00538
00539 if (exitIsPermitted)
00540 {
00541 bool timeExpired = false;
00542
00543 if (actExperiment.gpParameter.getTerminationUsesDate())
00544 timeExpired = ( actExperiment.gpParameter.getTerminationTime() <= QDateTime::currentDateTime() );
00545 else
00546 {
00547 int durationHours = ( actExperiment.gpParameter.getTerminationDurationDays() * 24)
00548 + actExperiment.gpParameter.getTerminationDurationHours();
00549 int durationMinutes = ( durationHours * 60 )
00550 + actExperiment.gpParameter.getTerminationDurationMinutes();
00551 int durationSeconds = ( durationMinutes * 60 )
00552 + actExperiment.gpParameter.getTerminationDurationSeconds();
00553
00554 QDateTime terminationTime = startTime.addSecs( durationSeconds );
00555
00556 timeExpired = ( terminationTime <= QDateTime::currentDateTime() );
00557 };
00558
00559 bool generationsReached = ( actExperiment.gpParameter.getTerminationGenerationNo() <= currentGenerationNo );
00560
00561 switch (actExperiment.gpParameter.getTerminationModel())
00562 {
00563 case SIG_GPParameter::byTime:
00564 return timeExpired;
00565 break;
00566 case SIG_GPParameter::byGeneration:
00567 return generationsReached;
00568 break;
00569 case SIG_GPParameter::byTimeGeneration:
00570 return timeExpired || generationsReached;
00571 break;
00572 case SIG_GPParameter::byUser:
00573 return false;
00574 break;
00575 };
00576 }
00577 else
00578 return false;
00579 };
00580
00581 void SIGEL_GP::SIG_GPManager::run()
00582 {
00583 if (!tours.isEmpty())
00584 {
00585 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager::run() wurde mehr als einmal aufgerufen!\n";
00586 messageEvolutionStop();
00587 };
00588
00589 if (actExperiment.getPopulation().getSize() < 4)
00590 {
00591 SIGEL_Tools::SIG_IO::cerr << "Population contains less than 4 Individuals, cannot evolve!\n";
00592 messageEvolutionStop();
00593 };
00594
00595 startTime = QDateTime::currentDateTime();
00596
00597 for (;;)
00598 {
00599 #ifdef SIG_DEBUG
00600 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager entering endless for-loop.\n";
00601 #endif
00602
00603 stopIfNecessary( true );
00604
00605 if (schlussJetzt)
00606 return;
00607
00608 evalNewIndis();
00609
00610 stopIfNecessary( true );
00611
00612 if (schlussJetzt)
00613 return;
00614
00615 createTours( actExperiment.gpParameter.getTournamentsPerGeneration() * actExperiment.getPopulation().getSize() );
00616
00617 calcInitTourSet();
00618
00619 evolutionLoop();
00620
00621 if (schlussJetzt)
00622 return;
00623
00624 currentGenerationNo++;
00625 actExperiment.population.poolGeneration++;
00626
00627 for (int i=0; i < actExperiment.population.getSize(); i++)
00628 {
00629 actExperiment.population.getIndividual( i ).increaseAge();
00630 updateIndividualView( i );
00631 };
00632
00633 int poolImageGeneration = actExperiment.getGPParameter().getPoolImageGeneration();
00634
00635 int poolGenerationNo = actExperiment.population.poolGeneration;
00636 QDateTime generationBreak = QDateTime::currentDateTime();
00637 double bestFitness = actExperiment.population.getBestFitness( true );
00638 double minFitness = actExperiment.population.getWorstFitness( true );
00639 double averageFitness = actExperiment.population.getAverageFitness();
00640 SIG_GPExperimentHistoryEntry *newExpHistEntry = new SIG_GPExperimentHistoryEntry( poolGenerationNo,
00641 generationBreak,
00642 bestFitness,
00643 minFitness,
00644 averageFitness );
00645
00646 actExperiment.experimentHistory.append( newExpHistEntry );
00647
00648 if ( poolImageGeneration
00649 && ((currentGenerationNo % poolImageGeneration) == 0) )
00650 {
00651 QDir poolImageDir = actExperiment.getGPParameter().getPoolImageDirectory();
00652
00653 QString poolImageName = poolImageDir.path()
00654 + QString( "/" )
00655 + actExperiment.experimentName
00656 + QString( "_PoolImage_" )
00657 + QDateTime::currentDateTime().toString()
00658 + ".pol";
00659
00660 #ifdef SIG_DEBUG
00661 SIGEL_Tools::SIG_IO::cerr << "SIG_GPManager saving poolImage, currentGenerationNo: "
00662 << currentGenerationNo
00663 << ", filename: "
00664 << poolImageName
00665 << "\n";
00666 #endif
00667
00668 QFile poolImage( poolImageName );
00669
00670 if (poolImage.open( IO_WriteOnly ))
00671 {
00672 QTextStream buffer( &poolImage );
00673 actExperiment.getPopulation().writeToFile( buffer );
00674 poolImage.close();
00675 }
00676 else
00677 SIGEL_Tools::SIG_IO::cerr << "Could not save Pool under "
00678 << poolImageName
00679 << "!\n";
00680 };
00681 };
00682 };
00683
00684 SIGEL_GP::SIG_GPManager::~SIG_GPManager()
00685 { };
00686
00687
00688
00689