28#include "EVNTrainer.h"
29#include "GeneticAlgorithm.h"
31#include "BrainsFactory.h"
34#include "ObjectsPacMan.h"
35#include "Pac-Man_Evolution.h"
38#define PME_EVNTRAINER_EVOLVED "Evolved"
39#define PME_EVNTRAINER_TRAINING "Training-"
42EVNTrainer* EVNTrainer::mInstance =
nullptr;
45EVNTrainer& EVNTrainer::Instance()
47 if(!mInstance) mInstance =
new(std::nothrow) EVNTrainer;
52void EVNTrainer::Terminate()
54 if(mInstance)
delete mInstance;
59EVNTrainer::EVNTrainer()
61 dCrossOverRate = PME_GA_CROSSOVER_RATE;
62 dMutationRate = PME_GA_MUTATION_RATE;
63 dMaxPerturbation = PME_GA_MAX_PERTURBATION;
64 iNumElite = PME_GA_NUM_ELITE;
65 iNumCopiesElite = PME_GA_NUM_COPIES_ELITE;
66 iPopulation = PME_GA_POPULATION;
70EVNTrainer::~EVNTrainer()
75Sint32 EVNTrainer::Creature::info()
77 Log& mLog = *Main::Instance().ILogMgr().get();
80 if(iNumBestCreatures > 0)
82 for(k = 0; k < iNumBestCreatures && k < vBestCreaturesNN.size(); ++k)
84 mLog.msg(LML_INFO,
" BestCreature (%d/%d): ", k + 1, iNumBestCreatures);
85 for(i = 0; i < vBestCreaturesNN[k].vWeights.size(); ++i)
87 mLog.msg(LML_INFO,
"%.6f", vBestCreaturesNN[k].vWeights[i]);
88 if(i != (vBestCreaturesNN[k].vWeights.size() - 1)) mLog.msg(LML_INFO,
",");
90 mLog.msg(LML_INFO,
"\n");
92 mLog.msg(LML_INFO,
"\n");
98EVNTrainer::Creature::Creature(Sint32 iIdentifier)
102 iBestCreatureGeneration = 0;
103 dBestCreatureFitness = 0;
104 iNumBestCreatures = 3;
105 vBestCreaturesNN.clear();
108 vGenomesPopulation.clear();
112EVNTrainer::Creature::~Creature()
114 if(pGA !=
nullptr)
delete pGA;
119Sint32 EVNTrainer::load(
string& sGhostName, ArtificialNeuralNet* pNN,
string& sCDCFile,
string& sXMLName)
122 Main& mC64 = Main::Instance();
123 Log& mLog = *Main::Instance().ILogMgr().get();
125 Sint32 iInputs, iOutputs, iLayers, iNpL, iGeneration, iActivationFunc;
127 vector<double> vWeights;
128 string sName, sType, sBuff;
132 if(sCDCFile.empty()) sCDCFile = PME_GHOSTS_NN_FILE;
134 if(sXMLName.empty()) sXMLName = PME_GHOSTS_NN_BLOCK;
137 sizePos = sGhostName.find_first_of(
"-", 0);
138 if(sizePos == string::npos)
return -1;
139 sName = sGhostName.substr(0, sizePos);
140 sType = sGhostName.substr(sizePos + 1, sGhostName.length());
143 if(mC64.ITool().fileExists(sCDCFile) == 0) idXML = mC64.IXMLMgr().load(sCDCFile, sXMLName);
146 idXML = mC64.IXMLMgr().loadFromFile(sXMLName);
149 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not load XML file '%s' from '%s'\n", sXMLName.c_str(), sCDCFile.c_str());
153 pXML = mC64.IXMLMgr().get(idXML);
156 if(pXML->nodePointTo(3,
"Ghosts", sName.c_str(), sType.c_str()) != 0)
158 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not find 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
159 mC64.IXMLMgr().close(idXML);
164 if(pXML->getAttribute(
"generation", iGeneration) != 0)
166 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'generation' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
167 mC64.IXMLMgr().close(idXML);
170 if(pXML->getAttribute(
"fitness", dFitness) != 0)
172 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'fitness' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
173 mC64.IXMLMgr().close(idXML);
176 if(pXML->getAttribute(
"activation_func", iActivationFunc) != 0)
178 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'activation_func' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
179 mC64.IXMLMgr().close(idXML);
182 if(iActivationFunc < 0) iActivationFunc = ANN_ACTIVATION_LINEAR;
183 else if(iActivationFunc > 2) iActivationFunc = ANN_ACTIVATION_SIGMOID;
184 if(pXML->getAttribute(
"inputs", iInputs) != 0)
186 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'inputs' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
187 mC64.IXMLMgr().close(idXML);
190 if(pXML->getAttribute(
"outputs", iOutputs) != 0)
192 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'outputs' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
193 mC64.IXMLMgr().close(idXML);
196 if(pXML->getAttribute(
"layers", iLayers) != 0)
198 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'layers' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
199 mC64.IXMLMgr().close(idXML);
202 if(pXML->getAttribute(
"neurons_per_layer", iNpL) != 0)
204 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'neurons_per_layer' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
205 mC64.IXMLMgr().close(idXML);
210 if(pXML->getText(sBuff) != 0)
212 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read neuron weights for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
213 mC64.IXMLMgr().close(idXML);
218 mC64.IXMLMgr().close(idXML);
221 pNN->init(iInputs, iOutputs, iLayers, iNpL);
222 pNN->setActivationFunction(iActivationFunc);
225 parseWeights((
char*)sBuff.c_str(), vWeights);
226 if(pNN->getNumberOfWeights() > vWeights.size())
228 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read neuron weights for 'Ghosts\\%s\\%s'. Parsed '%d' but needed '%d'\n", sName.c_str(), sType.c_str(), vWeights.size(), pNN->getNumberOfWeights());
231 pNN->setWeights(vWeights);
235 mLog.msg(LML_INFO,
" [EVNTrainer] Info: '%s\\%s' ghost loaded: G('%d') - F('%.6f') - I('%d') - O('%d') - AF('%d')\n",
236 sName.c_str(), sType.c_str(), iGeneration, dFitness, iInputs, iOutputs, iActivationFunc);
243Sint32 EVNTrainer::execute(GlobalStatus& pGlobalStatus, GameField& pGameField)
245 Main& mC64 = Main::Instance();
246 Log& mLog = *mC64.ILogMgr().get();
247 Sint32 i, j, k, iDone, iLifes;
256 if(initCreatures(pGlobalStatus) != 0)
258 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: no ghost ready to be trained.\n");
263 for(k = 0; k < (Sint32)vCreatures.size(); ++k)
265 i = vCreatures[k]->vBrains[0]->getNeuralNet()->getNumberOfWeights();
266 vCreatures[k]->pGA =
new(std::nothrow) GeneticAlgorithm(iPopulation, dMutationRate, dCrossOverRate, dMaxPerturbation, iNumElite, iNumCopiesElite, i);
267 for(j = 0; j < iPopulation; ++j)
269 vCreatures[k]->pGA->init(j, vCreatures[k]->vBrains[j]->getNeuralNet()->getWeights());
271 vCreatures[k]->vGenomesPopulation = vCreatures[k]->pGA->getChromos();
276 Sint32 iTimeStart, iTimeGenerationStart, iTimePopulationStart;
277 mLog.msg(LML_INFO,
"\n [EVNTrainer] Starting evolution of '%d' creatures with a population of '%d' during '%d' generations\n", vCreatures.size(), iPopulation, pGlobalStatus.workBench.iExecutions);
278 mLog.msg(LML_INFO,
" CrossOver rate of '%.2f' - Mutation rate of '%.2f' with a max perturbation of '%.2f'\n", PME_GA_CROSSOVER_RATE, PME_GA_MUTATION_RATE, PME_GA_MAX_PERTURBATION);
279 FILE* fp = fopen(pGlobalStatus.workBench.szOutputCSV,
"wt");
280 fprintf(fp,
"BestCreatureFitness,AveragePopulationFitness\n");
281 iTimeStart = mC64.ITimer().getTicksNow();
284 pGlobalStatus.iGameType = PME_GAME_WORKBENCH;
285 while(i < pGlobalStatus.workBench.iExecutions)
291 mLog.msg(LML_INFO,
" Generation '%d':\n", i);
292 iTimeGenerationStart = mC64.ITimer().getTicksNow();
295 for(j = 0; j < iPopulation; ++j)
298 iTimePopulationStart = mC64.ITimer().getTicksNow();
301 iDone = pGameField.init();
302 pGlobalStatus.iPoints = 0;
305 for(k = 0; k < (Sint32)vCreatures.size(); ++k)
307 pActor = pGameField.getActor(vCreatures[k]->iID);
308 if(pActor) pActor->setBrain((PME_BRAIN_TYPE_TRAINING0 << j) | vCreatures[k]->iID);
312 while(iDone == PME_LOOP)
314 iDone = pGameField.execute();
315 if(iDone == PME_MAZE_END) iDone = pGameField.nextMaze();
319 pPacMan =
reinterpret_cast<PacMan*
>(pGameField.getActor(PME_OBJECT_PACMAN));
320 if(pPacMan !=
nullptr) iLifes = pPacMan->getLifes();
321 else iLifes = PME_PACMAN_START_LIFES;
322 if(iDone == PME_BREAK)
324 pGlobalStatus.iPoints = pGlobalStatus.iPoints * (iLifes * 10);
326 dFitness = (1.0 / (double)pGlobalStatus.iPoints);
327 for(k = 0; k < (Sint32)vCreatures.size(); ++k) vCreatures[k]->vBrains[j]->setFitness(dFitness);
331 mLog.msg(LML_INFO,
" Population '%d' reached Maze '%d' in %2.2f seconds with a fitness of '%.6f' (",
332 j, pGameField.getMazeNumber(), (float)(mC64.ITimer().getTicksNow() - iTimePopulationStart) / 1000.0f, dFitness);
333 if(iDone == PME_BREAK) mLog.msg(LML_INFO,
"Aborted, %d lifes)\n", iLifes);
334 else mLog.msg(LML_INFO,
"PacMan died)\n");
342 for(k = 0; k < (Sint32)vCreatures.size(); ++k)
345 for(j = 0; j < iPopulation; ++j)
348 vCreatures[k]->vGenomesPopulation[j].dFitness = vCreatures[k]->vBrains[j]->getFitness();
351 if(vCreatures[k]->vBrains[j]->getFitness() > vCreatures[k]->dBestCreatureFitness)
353 vCreatures[k]->dBestCreatureFitness = vCreatures[k]->vBrains[j]->getFitness();
354 vCreatures[k]->iBestCreatureGeneration = vCreatures[k]->iGeneration;
358 if(vCreatures[k]->vBestCreaturesNN.size() < vCreatures[k]->iNumBestCreatures)
361 vCreatures[k]->vBestCreaturesNN.push_back(vCreatures[k]->vGenomesPopulation[j]);
362 std::sort(vCreatures[k]->vBestCreaturesNN.begin(), vCreatures[k]->vBestCreaturesNN.end());
364 else if(vCreatures[k]->iNumBestCreatures > 0)
367 if(vCreatures[k]->vGenomesPopulation[j].dFitness > vCreatures[k]->vBestCreaturesNN[0].dFitness)
369 vCreatures[k]->vBestCreaturesNN.push_back(vCreatures[k]->vGenomesPopulation[j]);
375 if(vCreatures[k]->iNumBestCreatures > 0)
377 std::sort(vCreatures[k]->vBestCreaturesNN.rbegin(), vCreatures[k]->vBestCreaturesNN.rend());
378 vCreatures[k]->vBestCreaturesNN.resize(vCreatures[k]->iNumBestCreatures);
379 std::sort(vCreatures[k]->vBestCreaturesNN.begin(), vCreatures[k]->vBestCreaturesNN.end());
383 if(i < pGlobalStatus.workBench.iExecutions)
384 vCreatures[k]->vGenomesPopulation = vCreatures[k]->pGA->epoch(vCreatures[k]->vGenomesPopulation);
387 for(j = 0; j < iPopulation; ++j)
389 vCreatures[k]->vBrains[j]->getNeuralNet()->setWeights(vCreatures[k]->vGenomesPopulation[j].vWeights);
394 ++vCreatures[k]->iGeneration;
399 fprintf(fp,
"%.6f,%.6f\n", vCreatures[0]->dBestCreatureFitness, vCreatures[0]->pGA->fitnessAverage());
401 mLog.msg(LML_INFO,
" Done in %2.2f seconds. BestF '%.6f' AverageF '%.6f' Mutations '%d' CrossOvers '%d' - BestF so far '%.6f'\n",
402 (
float)(mC64.ITimer().getTicksNow() - iTimeGenerationStart) / 1000.0f, vCreatures[0]->pGA->fitnessBest(), vCreatures[0]->pGA->fitnessAverage(),
403 vCreatures[0]->pGA->getMutation(), vCreatures[0]->pGA->getCrossOver(), vCreatures[0]->dBestCreatureFitness);
408 saveCreatures(PME_GHOSTS_NN_FILE, PME_GHOSTS_NN_BLOCK);
413 mLog.msg(LML_INFO,
"\n [EVNTrainer] Evolution finished in %2.2f seconds. Best fitness '%.6f' reached on generation '%d'\n",
414 (
float)(mC64.ITimer().getTicksNow() - iTimeStart) / 1000.0f, vCreatures[0]->dBestCreatureFitness, vCreatures[0]->iBestCreatureGeneration + 1);
416 for(k = 0; k < (Sint32)vCreatures.size(); ++k)
419 vCreatures[k]->info();
421 delete vCreatures[k];
428Sint32 EVNTrainer::initCreatures(GlobalStatus& pGlobalStatus)
431 BrainEvolved* pBrain;
436 if(pGlobalStatus.workBench.iGhostRedBrain >= PME_BRAIN_TYPE_TRAINING0)
439 if(createDefaultANN(
"Red", PME_GHOSTS_NN_FILE, PME_GHOSTS_NN_BLOCK) == 0)
442 pCreature =
new(std::nothrow) Creature(PME_OBJECT_GHOST_RED);
443 for(i = 0; i < iPopulation; ++i)
445 pBrain =
reinterpret_cast<BrainEvolved*
>(BrainsFactory::Instance().getBrain((PME_BRAIN_TYPE_TRAINING0 << i) | PME_OBJECT_GHOST_RED));
447 pCreature->vBrains.push_back(pBrain);
449 vCreatures.push_back(pCreature);
455 if(pGlobalStatus.workBench.iGhostPinkBrain >= PME_BRAIN_TYPE_TRAINING0)
458 if(createDefaultANN(
"Pink", PME_GHOSTS_NN_FILE, PME_GHOSTS_NN_BLOCK) == 0)
461 pCreature =
new(std::nothrow) Creature(PME_OBJECT_GHOST_PINK);
462 for(i = 0; i < iPopulation; ++i)
464 pBrain =
reinterpret_cast<BrainEvolved*
>(BrainsFactory::Instance().getBrain((PME_BRAIN_TYPE_TRAINING0 << i) | PME_OBJECT_GHOST_PINK));
466 pCreature->vBrains.push_back(pBrain);
468 vCreatures.push_back(pCreature);
474 if(pGlobalStatus.workBench.iGhostBlueBrain >= PME_BRAIN_TYPE_TRAINING0)
477 if(createDefaultANN(
"Blue", PME_GHOSTS_NN_FILE, PME_GHOSTS_NN_BLOCK) == 0)
480 pCreature =
new(std::nothrow) Creature(PME_OBJECT_GHOST_BLUE);
481 for(i = 0; i < iPopulation; ++i)
483 pBrain =
reinterpret_cast<BrainEvolved*
>(BrainsFactory::Instance().getBrain((PME_BRAIN_TYPE_TRAINING0 << i) | PME_OBJECT_GHOST_BLUE));
485 pCreature->vBrains.push_back(pBrain);
487 vCreatures.push_back(pCreature);
493 if(pGlobalStatus.workBench.iGhostOrangeBrain >= PME_BRAIN_TYPE_TRAINING0)
496 if(createDefaultANN(
"Orange", PME_GHOSTS_NN_FILE, PME_GHOSTS_NN_BLOCK) == 0)
499 pCreature =
new(std::nothrow) Creature(PME_OBJECT_GHOST_ORANGE);
500 for(i = 0; i < iPopulation; ++i)
502 pBrain =
reinterpret_cast<BrainEvolved*
>(BrainsFactory::Instance().getBrain((PME_BRAIN_TYPE_TRAINING0 << i) | PME_OBJECT_GHOST_ORANGE));
504 pCreature->vBrains.push_back(pBrain);
506 vCreatures.push_back(pCreature);
518Sint32 EVNTrainer::createDefaultANN(
const string& sGhostName,
string sCDCFile,
string sXMLName)
521 Main& mC64 = Main::Instance();
522 Log& mLog = *Main::Instance().ILogMgr().get();
524 Sint32 iInputs, iOutputs, iLayers, iNpL, iNumWeights, iActivationFunc, i, j;
525 vector<double> vWeights;
526 string sName, sType, sBuff, sNumber;
529 bool bCDCUsage =
false, bSaveXML =
false;
532 sizePos = sGhostName.find_first_of(
"-", 0);
533 if(sizePos == string::npos) sName = sGhostName;
534 else sName = sGhostName.substr(0, sizePos);
535 sType = PME_EVNTRAINER_EVOLVED;
538 if(mC64.ITool().fileExists(sCDCFile) == 0) idXML = mC64.IXMLMgr().load(sCDCFile, sXMLName);
541 idXML = mC64.IXMLMgr().loadFromFile(sXMLName);
544 idXML = mC64.IXMLMgr().create(
"Ghosts");
547 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not load XML file '%s' from '%s' and could not create a new one\n", sXMLName.c_str(), sCDCFile.c_str());
552 else bCDCUsage =
true;
553 pXML = mC64.IXMLMgr().get(idXML);
556 if(pXML->nodePointTo(1,
"Ghosts") != 0)
558 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: 'Ghosts' node not found, creating it... ");
559 if(pXML->nodeCreate(
"Ghosts") != 0)
561 mLog.msg(LML_NORMAL,
"error!\n");
562 mC64.IXMLMgr().close(idXML);
565 mLog.msg(LML_NORMAL,
"done!\n");
569 if(pXML->nodePointTo(2,
"Ghosts", sName.c_str()) != 0)
571 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: 'Ghosts\\%s' subnode not found, creating it... ", sName.c_str());
572 if(pXML->nodeCreate(sName) != 0)
574 mLog.msg(LML_NORMAL,
"error!\n");
575 mC64.IXMLMgr().close(idXML);
578 mLog.msg(LML_NORMAL,
"done!\n");
582 if(pXML->nodePointTo(3,
"Ghosts", sName.c_str(), sType.c_str()) != 0)
584 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: 'Ghosts\\%s\\%s' subnode not found, creating it... ", sName.c_str(), sType.c_str());
585 if(pXML->nodeCreate(sType) != 0)
587 mLog.msg(LML_NORMAL,
"error!\n");
588 mC64.IXMLMgr().close(idXML);
592 iOutputs = PME_ANN_GHOST_OUTPUT;
595 iInputs = PME_ANN_GHOST_RED_INPUT;
596 iNpL = PME_ANN_GHOST_RED_HIDDEN;
597 iActivationFunc = PME_ANN_GHOST_RED_ACTIVATION;
599 else if(sName ==
"Pink")
601 iInputs = PME_ANN_GHOST_PINK_INPUT;
602 iNpL = PME_ANN_GHOST_PINK_HIDDEN;
603 iActivationFunc = PME_ANN_GHOST_PINK_ACTIVATION;
605 else if(sName ==
"Blue")
607 iInputs = PME_ANN_GHOST_BLUE_INPUT;
608 iNpL = PME_ANN_GHOST_BLUE_HIDDEN;
609 iActivationFunc = PME_ANN_GHOST_BLUE_ACTIVATION;
611 else if(sName ==
"Orange")
613 iInputs = PME_ANN_GHOST_ORANGE_INPUT;
614 iNpL = PME_ANN_GHOST_ORANGE_HIDDEN;
615 iActivationFunc = PME_ANN_GHOST_ORANGE_ACTIVATION;
619 mLog.msg(LML_NORMAL,
" error! name is unsupported\n");
620 mC64.IXMLMgr().close(idXML);
625 iNumWeights = (iInputs * iNpL);
626 iNumWeights = iNumWeights + (iNpL * iOutputs);
627 #ifdef ANN_ENABLE_BIAS
628 iNumWeights = iNumWeights + iNpL + iOutputs;
634 iNumWeights = (iInputs * iOutputs);
635 #ifdef ANN_ENABLE_BIAS
636 iNumWeights = iNumWeights + iOutputs;
640 pXML->setAttribute(
"generation", 0);
641 pXML->setAttribute(
"fitness", 0.0);
642 pXML->setAttribute(
"activation_func", iActivationFunc);
643 pXML->setAttribute(
"inputs", iInputs);
644 pXML->setAttribute(
"outputs", iOutputs);
645 pXML->setAttribute(
"layers", iLayers);
646 pXML->setAttribute(
"neurons_per_layer", iNpL);
650 for(j = 0; j < iNumWeights; j++)
653 snprintf(szNumber,
sizeof(szNumber),
"%.6f", generateWeights());
655 if(j != (iNumWeights - 1)) sBuff +=
",";
657 pXML->setText(sBuff);
658 mLog.msg(LML_NORMAL,
"done!\n");
662 if(pXML->getAttribute(
"activation_func", iActivationFunc) != 0)
664 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'activation_func' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
665 mC64.IXMLMgr().close(idXML);
668 if(iActivationFunc < 0) iActivationFunc = ANN_ACTIVATION_LINEAR;
669 else if(iActivationFunc > 2) iActivationFunc = ANN_ACTIVATION_SIGMOID;
670 if(pXML->getAttribute(
"inputs", iInputs) != 0)
672 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'inputs' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
673 mC64.IXMLMgr().close(idXML);
676 if(pXML->getAttribute(
"outputs", iOutputs) != 0)
678 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'outputs' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
679 mC64.IXMLMgr().close(idXML);
682 if(pXML->getAttribute(
"layers", iLayers) != 0)
684 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'layers' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
685 mC64.IXMLMgr().close(idXML);
688 if(pXML->getAttribute(
"neurons_per_layer", iNpL) != 0)
690 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read 'neurons_per_layer' attribute for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
691 mC64.IXMLMgr().close(idXML);
696 if(pXML->getText(sBuff) != 0)
698 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not read neuron weights for 'Ghosts\\%s\\%s' node\n", sName.c_str(), sType.c_str());
699 mC64.IXMLMgr().close(idXML);
704 iNumWeights = parseWeights((
char*)sBuff.c_str(), vWeights);
707 for(i = 0; i < PME_GA_POPULATION; ++i)
709 sBuff = PME_EVNTRAINER_TRAINING;
710 mC64.ITool().intToStrDec(i, sNumber);
714 if(pXML->nodePointTo(3,
"Ghosts", sName.c_str(), sBuff.c_str()) != 0)
716 mLog.msg(LML_NORMAL,
" [EVNTrainer] Info: creating '%s' node. Weights in the interval of [%d,%d] with precision '%.6f'\n", sBuff.c_str(), ANN_WEIGHT_MIN, ANN_WEIGHT_MAX, ANN_PRECISION);
717 pXML->nodePointTo(2,
"Ghosts", sName.c_str());
718 pXML->nodeCreate(sBuff);
719 pXML->setAttribute(
"generation", 0);
720 pXML->setAttribute(
"fitness", 0.0);
721 pXML->setAttribute(
"activation_func", iActivationFunc);
722 pXML->setAttribute(
"inputs", iInputs);
723 pXML->setAttribute(
"outputs", iOutputs);
724 pXML->setAttribute(
"layers", iLayers);
725 pXML->setAttribute(
"neurons_per_layer", iNpL);
728 for(j = 0; j < iNumWeights; j++)
731 snprintf(szNumber,
sizeof(szNumber),
"%.6f", generateWeights());
733 if(j != (iNumWeights - 1)) sBuff +=
",";
735 pXML->setText(sBuff);
743 if(bCDCUsage) pXML->save(sCDCFile);
744 else pXML->saveToFile(sXMLName);
746 mC64.IXMLMgr().close(idXML);
752Sint32 EVNTrainer::saveCreatures(
string sCDCFile,
string sXMLName)
754 Main& mC64 = Main::Instance();
755 Log& mLog = *Main::Instance().ILogMgr().get();
757 bool bCDCUsage =
false;
758 Sint32 idXML = -1, i, k;
759 string sBuff, sNumber, sName;
762 if(sCDCFile.empty()) sCDCFile = PME_GHOSTS_NN_FILE;
764 if(sXMLName.empty()) sXMLName = PME_GHOSTS_NN_BLOCK;
767 if(mC64.ITool().fileExists(sCDCFile) == 0) idXML = mC64.IXMLMgr().load(sCDCFile, sXMLName);
770 idXML = mC64.IXMLMgr().loadFromFile(sXMLName);
773 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not load XML file '%s' from '%s'\n", sXMLName.c_str(), sCDCFile.c_str());
777 else bCDCUsage =
true;
778 pXML = mC64.IXMLMgr().get(idXML);
781 for(k = 0; k < (Sint32)vCreatures.size(); ++k)
784 if(vCreatures[k]->iID == PME_OBJECT_GHOST_RED) sName =
"Red";
786 else if(vCreatures[k]->iID == PME_OBJECT_GHOST_PINK) sName =
"Pink";
788 else if(vCreatures[k]->iID == PME_OBJECT_GHOST_BLUE) sName =
"Blue";
790 else if(vCreatures[k]->iID == PME_OBJECT_GHOST_ORANGE) sName =
"Orange";
794 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: internal creature ID is unknown\n");
795 mC64.IXMLMgr().close(idXML);
800 if(pXML->nodePointTo(3,
"Ghosts", sName.c_str(), PME_EVNTRAINER_EVOLVED) != 0)
802 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not find 'Ghosts\\%s\\%s' node\n", sName.c_str(), PME_EVNTRAINER_EVOLVED);
803 mC64.IXMLMgr().close(idXML);
807 updateNode(pXML, vCreatures[k], -1);
810 for(i = 0; i < PME_GA_POPULATION; ++i)
812 sBuff = PME_EVNTRAINER_TRAINING;
813 mC64.ITool().intToStrDec(i, sNumber);
817 if(pXML->nodePointTo(3,
"Ghosts", sName.c_str(), sBuff.c_str()) != 0)
819 mLog.msg(LML_NORMAL,
" [EVNTrainer] Warning: could not find 'Ghosts\\%s\\%s' node\n", sName.c_str(), sBuff.c_str());
820 mC64.IXMLMgr().close(idXML);
824 updateNode(pXML, vCreatures[k], i);
829 if(bCDCUsage) pXML->save(sCDCFile);
830 else pXML->saveToFile(sXMLName);
831 mC64.IXMLMgr().close(idXML);
836Sint32 EVNTrainer::updateNode(XML* pXML, Creature* pCreature, Sint32 iNum)
838 Sint32 iGeneration, j;
842 vector<double> pWeights;
845 if(pXML->getAttribute(
"generation", iGeneration) != 0)
return -1;
846 if(pXML->getAttribute(
"fitness", dFitness) != 0)
return -1;
852 if(dFitness > pCreature->dBestCreatureFitness)
return 0;
853 iGeneration = iGeneration + 1 + pCreature->iBestCreatureGeneration;
854 dFitness = pCreature->dBestCreatureFitness;
855 pWeights = pCreature->vBestCreaturesNN[0].vWeights;
859 iGeneration += pCreature->iGeneration;
860 dFitness = pCreature->vBrains[iNum]->getFitness();
861 pWeights = pCreature->vBrains[iNum]->getNeuralNet()->getWeights();
865 pXML->setAttribute(
"generation", iGeneration);
866 dFitness = applyWeightPrecision(dFitness);
867 snprintf(szNumber,
sizeof(szNumber),
"%.6f", dFitness);
869 pXML->setAttribute(
"fitness", sWeights);
874 for(j = 0; j < pWeights.size(); j++)
876 snprintf(szNumber,
sizeof(szNumber),
"%.6f", pWeights[j]);
877 sWeights += szNumber;
878 if(j != (pWeights.size() - 1)) sWeights +=
",";
880 pXML->setText(sWeights);
886Sint32 EVNTrainer::parseWeights(
char* from, vector<double>& to)
889 char seps[] =
",\n\t";
893 token = strtok(from, seps);
898 token = strtok(NULL, seps);