00001 #include "ECF.h"
00002 #include <fstream>
00003 #include <iomanip>
00004 #include <time.h>
00005
00006
00012 State::State()
00013 {
00014 this->population_ = static_cast<PopulationP> (new Population);
00015 this->crossover_ = static_cast<CrossoverP> (new Crossover);
00016 this->mutation_ = static_cast<MutationP> (new Mutation);
00017 this->context_ = static_cast<EvolutionContextP> (new EvolutionContext);
00018
00019 XMLNode::setGlobalOptions(XMLNode::char_encoding_legacy);
00020
00021 bInitialized_ = false;
00022 bCommandLine_ = false;
00023 bAlgorithmSet_ = false;
00024 bGenotypeSet_ = false;
00025 bEvaluatorSet_ = false;
00026 bLoadMilestone_ = false;
00027 bBatchMode_ = false;
00028 bBatchStart_ = false;
00029 bBatchSingleMilestone_ = false;
00030 bBatchWriteStats_ = false;
00031
00032
00033
00034 AlgorithmP alg = static_cast<AlgorithmP> (new SteadyStateTournament);
00035 this->mAlgorithms_[alg->getName()] = alg;
00036 alg = static_cast<AlgorithmP> (new RouletteWheel);
00037 this->mAlgorithms_[alg->getName()] = alg;
00038 alg = static_cast<AlgorithmP> (new ParticleSwarmOptimization);
00039 this->mAlgorithms_[alg->getName()] = alg;
00040 alg = static_cast<AlgorithmP> (new Elimination);
00041 this->mAlgorithms_[alg->getName()] = alg;
00042 alg = static_cast<AlgorithmP> (new XCS);
00043 this->mAlgorithms_[alg->getName()] = alg;
00044 alg = static_cast<AlgorithmP> (new RandomSearch);
00045 this->mAlgorithms_[alg->getName()] = alg;
00046 alg = static_cast<AlgorithmP> (new GeneticAnnealing);
00047 this->mAlgorithms_[alg->getName()] = alg;
00048 alg = static_cast<AlgorithmP> (new DifferentialEvolution);
00049 this->mAlgorithms_[alg->getName()] = alg;
00050 alg = static_cast<AlgorithmP> (new ArtificialBeeColony);
00051 this->mAlgorithms_[alg->getName()] = alg;
00052 alg = static_cast<AlgorithmP> (new GenHookeJeeves);
00053 this->mAlgorithms_[alg->getName()] = alg;
00054 alg = static_cast<AlgorithmP> (new Clonalg);
00055 this->mAlgorithms_[alg->getName()] = alg;
00056 alg = static_cast<AlgorithmP> (new OptIA);
00057 this->mAlgorithms_[alg->getName()] = alg;
00058 alg = static_cast<AlgorithmP> (new EvolutionStrategy);
00059 this->mAlgorithms_[alg->getName()] = alg;
00060
00061 #ifdef _MPI
00062
00063 alg = static_cast<AlgorithmP> (new AlgSGenGpea);
00064 this->mAlgorithms_[alg->getName()] = alg;
00065 alg = static_cast<AlgorithmP> (new AlgAEliGpea);
00066 this->mAlgorithms_[alg->getName()] = alg;
00067 alg = static_cast<AlgorithmP> (new AlgAEliGpea2);
00068 this->mAlgorithms_[alg->getName()] = alg;
00069 #endif
00070
00071
00072 GenotypeP gen = static_cast<GenotypeP> (new BitString::BitString);
00073 this->mGenotypes_[gen->getName()] = gen;
00074 gen = static_cast<GenotypeP> (new Binary::Binary);
00075 this->mGenotypes_[gen->getName()] = gen;
00076 gen = static_cast<GenotypeP> (new Tree::Tree);
00077 this->mGenotypes_[gen->getName()] = gen;
00078 gen = static_cast<GenotypeP> (new Permutation::Permutation);
00079 this->mGenotypes_[gen->getName()] = gen;
00080 gen = static_cast<GenotypeP> (new FloatingPoint::FloatingPoint);
00081 this->mGenotypes_[gen->getName()] = gen;
00082
00083
00084
00085
00086 OperatorP op = static_cast<OperatorP> (new TermStagnationOp);
00087 this->allTerminationOps_.push_back(op);
00088 op = static_cast<OperatorP> (new TermMaxGenOp);
00089 this->allTerminationOps_.push_back(op);
00090 op = static_cast<OperatorP> (new TermFitnessValOp);
00091 this->allTerminationOps_.push_back(op);
00092 op = static_cast<OperatorP> (new TermMaxTimeOp);
00093 this->allTerminationOps_.push_back(op);
00094 op = static_cast<OperatorP> (new TermMaxEvalOp);
00095 this->allTerminationOps_.push_back(op);
00096
00097 setRandomizer(static_cast<RandomizerP> (new SimpleRandomizer));
00098 this->registry_ = static_cast<RegistryP> (new Registry);
00099 this->logger_ = static_cast<LoggerP> (new Logger);
00100 this->comm_ = static_cast<CommunicatorP> (new Comm::Communicator);
00101 this->migration_ = static_cast<MigrationP> (new Migration);
00102 }
00103
00104
00109 void State::registerParameters()
00110 {
00111
00112 registry_->registerEntry("milestone.interval", (voidP) (new uint(0)), ECF::UINT,
00113 "milestone saving interval in generations; 0: save only at the end (default: 0)");
00114 registry_->registerEntry("milestone.filename", (voidP) (new std::string("milestone.txt")), ECF::STRING,
00115 "milestone file (if stated) stores all the population (default: none)");
00116 registry_->registerEntry("batch.repeats", (voidP) (new uint(0)), ECF::UINT,
00117 "number of independent runs to perform (default: 1)");
00118 registry_->registerEntry("batch.singlemilestone", (voidP) (new uint(0)), ECF::UINT,
00119 "use only one milestone file for all the batch runs (1) or one for each run (0) (default: 0)");
00120 registry_->registerEntry("batch.statsfile", (voidP) (new std::string("")), ECF::STRING,
00121 "output batch end of run stats in a single file (default: none)");
00122
00123
00124 registry_->registerEntry("milestone.generation_", (voidP) (new uint(0)), ECF::UINT);
00125 registry_->registerEntry("milestone.elapsedtime_", (voidP) (new uint(0)), ECF::UINT);
00126 registry_->registerEntry("batch.remaining_", (voidP) (new uint(0)), ECF::UINT);
00127 registry_->registerEntry("batch.logfile_", (voidP) (new std::string("")), ECF::STRING);
00128
00129 ECF_LOG(this, 4, "Registering parameters: algorithms, operators");
00130
00131
00132 alg_iter itAlg;
00133 for(itAlg = mAlgorithms_.begin(); itAlg != mAlgorithms_.end(); ++itAlg)
00134 itAlg->second->registerParameters(state_);
00135
00136
00137 mAlgorithms_.begin()->second->registerParallelParameters(state_);
00138
00139
00140 for(uint i = 0; i < allTerminationOps_.size(); i++)
00141 allTerminationOps_[i]->registerParameters(state_);
00142
00143
00144 for(uint i = 0; i < allUserOps_.size(); i++)
00145 allUserOps_[i]->registerParameters(state_);
00146
00147 mutation_->registerParameters(state_);
00148 crossover_->registerParameters(state_);
00149 randomizer_->registerParameters(state_);
00150 population_->registerParameters(state_);
00151 logger_->registerParameters(state_);
00152 migration_->registerParameters(state_);
00153 evalOp_->registerParameters(state_);
00154 }
00155
00156
00161 void State::readParameters()
00162 {
00163 ECF_LOG(this, 4, "Rading parameters from the Registry");
00164
00165
00166 if(registry_->isModified("milestone.filename"))
00167 bSaveMilestone_ = true;
00168 else
00169 bSaveMilestone_ = false;
00170
00171 voidP sptr = registry_->getEntry("milestone.interval");
00172 milestoneInterval_ = *((uint*) sptr.get());
00173
00174 sptr = registry_->getEntry("milestone.filename");
00175 milestoneFilename_ = *((std::string*) sptr.get());
00176
00177
00178 if(registry_->isModified("milestone.generation_"))
00179 bLoadMilestone_ = true;
00180 else
00181 bLoadMilestone_ = false;
00182
00183 sptr = registry_->getEntry("milestone.generation_");
00184 milestoneGeneration_ = *((uint*) sptr.get());
00185
00186 sptr = registry_->getEntry("milestone.elapsedtime_");
00187 milestoneElapsedTime_ = *((uint*) sptr.get());
00188
00189
00190 sptr = registry_->getEntry("batch.repeats");
00191 batchRepeats_ = *((uint*) sptr.get());
00192
00193 sptr = registry_->getEntry("batch.remaining_");
00194 batchRemaining_ = *((uint*) sptr.get());
00195
00196 sptr = registry_->getEntry("batch.statsfile");
00197 batchStatsFile_ = *((std::string*) sptr.get());
00198
00199 sptr = registry_->getEntry("batch.logfile_");
00200 batchLogFile_ = *((std::string*) sptr.get());
00201
00202 sptr = registry_->getEntry("batch.singlemilestone");
00203 bBatchSingleMilestone_ = (*((uint*) sptr.get()) % 2) ? true:false;
00204
00205 if(registry_->isModified("batch.repeats") && batchRepeats_ > 1)
00206 bBatchStart_ = true;
00207 else
00208 bBatchStart_ = false;
00209 }
00210
00211
00215 void State::dumpParameters(std::string fileName, bool addClear)
00216 {
00217 XMLNode xMainNode = XMLNode::createXMLTopNode("ECF");
00218 xMainNode.addAttribute("version", ECF_VERSION.c_str());
00219 xMainNode.addClear("ECF parameter dump - list of all parameters", "<!-- ", " -->");
00220
00221 this->state_ = this->getState();
00222
00223 this->registerParameters();
00224
00225
00226 for(gen_iter itGen = mGenotypes_.begin(); itGen != mGenotypes_.end(); ++itGen) {
00227 itGen->second->setGenotypeId(0);
00228 itGen->second->registerParameters(state_);
00229
00230
00231 std::vector<CrossoverOpP> crx = itGen->second->getCrossoverOp();
00232 for(uint iOp = 0; iOp < crx.size(); iOp++) {
00233 crx[iOp]->myGenotype_ = itGen->second;
00234 crx[iOp]->registerParameters(state_);
00235 }
00236
00237
00238 std::vector<MutationOpP> mut = itGen->second->getMutationOp();
00239 for(uint iOp = 0; iOp < mut.size(); iOp++) {
00240 mut[iOp]->myGenotype_ = itGen->second;
00241 mut[iOp]->registerParameters(state_);
00242 }
00243 }
00244
00245
00246 XMLNode xRegistry;
00247 this->registry_->dumpEntries(xRegistry);
00248
00249
00250 XMLNode xAlgorithms = XMLNode::createXMLTopNode(NODE_ALGORITHM);
00251 xMainNode.addChild(xAlgorithms);
00252
00253
00254 alg_iter itAlg;
00255 for(itAlg = mAlgorithms_.begin(); itAlg != mAlgorithms_.end(); ++itAlg) {
00256
00257
00258 std::string algorithmName = itAlg->first;
00259 XMLNode xAlgorithm = XMLNode::createXMLTopNode(algorithmName.c_str());
00260 xAlgorithms.addChild(xAlgorithm);
00261
00262
00263 for(int i = 0; i < xRegistry.nChildNode(); i++) {
00264 XMLNode child = xRegistry.getChildNode(i);
00265 std::string key = child.getAttributeValue();
00266
00267 if(key.compare(0, algorithmName.size(), algorithmName) == 0) {
00268
00269 XMLNode xEntry = child.deepCopy();
00270 child.deleteNodeContent();
00271 i--;
00272
00273
00274 std::string key = xEntry.getAttribute("key");
00275 key.erase(0, algorithmName.length() + 1);
00276 xEntry.updateAttribute(key.c_str(), NULL, "key");
00277 xAlgorithm.addChild(xEntry);
00278
00279
00280 std::string desc = xEntry.getAttribute("desc");
00281 if(addClear && desc != "") {
00282 xAlgorithm.addClear(desc.c_str(), "<!-- ", " -->");
00283 }
00284 if(addClear)
00285 xEntry.deleteAttribute("desc");
00286 }
00287 }
00288 }
00289
00290
00291 XMLNode xGenotypes = XMLNode::createXMLTopNode(NODE_GENOTYPE);
00292 xMainNode.addChild(xGenotypes);
00293
00294
00295 for(gen_iter itGen = mGenotypes_.begin(); itGen != mGenotypes_.end(); ++itGen) {
00296
00297
00298 std::string genotypeName = itGen->first;
00299 XMLNode xGenotype = XMLNode::createXMLTopNode(genotypeName.c_str());
00300 xGenotypes.addChild(xGenotype);
00301
00302
00303 for(int i = 0; i < xRegistry.nChildNode(); i++) {
00304 XMLNode child = xRegistry.getChildNode(i);
00305 std::string key = child.getAttributeValue();
00306
00307 if(key.compare(0, genotypeName.size(), genotypeName) == 0) {
00308
00309 XMLNode xEntry = child.deepCopy();
00310 child.deleteNodeContent();
00311 i--;
00312
00313
00314 std::string key = xEntry.getAttribute("key");
00315 key.erase(0, genotypeName.length() + 1);
00316 xEntry.updateAttribute(key.c_str(), NULL, "key");
00317 xGenotype.addChild(xEntry);
00318
00319
00320 std::string desc = xEntry.getAttribute("desc");
00321 if(addClear && desc != "") {
00322 xGenotype.addClear(desc.c_str(), "<!-- ", " -->");
00323 }
00324 if(addClear)
00325 xEntry.deleteAttribute("desc");
00326 }
00327 }
00328 }
00329
00330
00331 if(addClear) {
00332 XMLNode xRegClear = XMLNode::createXMLTopNode(NODE_REGISTRY);
00333 for(int i = 0; i < xRegistry.nChildNode(); i++) {
00334 XMLNode xEntry = xRegistry.getChildNode(i);
00335 XMLNode xE2 = xEntry.deepCopy();
00336 std::string desc = xEntry.getAttribute("desc");
00337 xE2.deleteAttribute("desc");
00338 xRegClear.addChild(xE2);
00339 if(desc != "")
00340 xRegClear.addClear(desc.c_str(), "<!-- ", " -->");
00341 }
00342 xMainNode.addChild(xRegClear);
00343 }
00344 else
00345
00346 xMainNode.addChild(xRegistry);
00347
00348 xMainNode.writeToFile(fileName.c_str());
00349 }
00350
00351
00352
00358 bool State::parseConfig(std::string filename)
00359 {
00360 std::ifstream fin(filename.c_str());
00361 if (!fin) {
00362 throw std::string("Error opening file " + filename);
00363 }
00364 std::cout << "Parsing configuration file: " << filename << std::endl;
00365
00366 std::string xmlFile, temp;
00367 while (!fin.eof()) {
00368 getline(fin, temp);
00369 xmlFile += "\n" + temp;
00370 }
00371
00372 XMLResults results;
00373 xConfig_ = XMLNode::parseString(xmlFile.c_str(), "ECF", &results);
00374 if (results.error != eXMLErrorNone) {
00375 std::cerr << "Configuration file: " << XMLNode::getError(results.error);
00376 std::cerr << " (line " << results.nLine << ", col " << results.nColumn << ")" << std::endl;
00377 throw("");
00378 }
00379
00380 if (xConfig_.isEmpty())
00381 return false;
00382
00383 int n = xConfig_.nChildNode();
00384 for (int i = 0; i < n; ++i) {
00385 XMLNode child = xConfig_.getChildNode(i);
00386 std::string name = child.getName();
00387 bool ok = true;
00388
00389 if (name == NODE_REGISTRY)
00390 ok &= registry_->readEntries(child);
00391 else if (name == NODE_ALGORITHM)
00392 ok &= parseAlgorithmNode(child);
00393 else if (name == NODE_GENOTYPE)
00394 ok &= parseGenotypeNode(child);
00395 else if (name == NODE_POPULATION)
00396 continue;
00397 else
00398 std::cerr << "Unknown node: " << name << std::endl;
00399
00400 if (!ok)
00401 throw "";
00402 }
00403
00404 return true;
00405 }
00406
00407
00413 bool State::parseAlgorithmNode(XMLNode node)
00414 {
00415 int n = node.nChildNode();
00416 if (n > 1)
00417 std::cout << "Warning: multiple Algorithm nodes found! (using the first one)" << std::endl;
00418
00419 XMLNode child = node.getChildNode(0);
00420 alg_iter alg = mAlgorithms_.find(child.getName());
00421 if (alg == mAlgorithms_.end()) {
00422 throw std::string("Error: unknown Algorithm : ") + child.getName();
00423 }
00424
00425 algorithm_ = alg->second;
00426 bAlgorithmSet_ = true;
00427
00428 if (! registry_->readEntries(child, child.getName()))
00429 return false;
00430
00431 return true;
00432 }
00433
00434
00440 bool State::parseGenotypeNode(XMLNode node)
00441 {
00442 int n = node.nChildNode();
00443 for (int i = 0; i < n; ++i) {
00444 XMLNode child = node.getChildNode(i);
00445 gen_iter gen = mGenotypes_.find(child.getName());
00446 if (gen == mGenotypes_.end()) {
00447 throw std::string("Error: unknown Genotype : ") + child.getName();
00448 }
00449
00450 uint genotypeId = (uint) genotype_.size();
00451 gen->second->setGenotypeId(genotypeId);
00452 gen->second->registerParameters(state_);
00453 setGenotype(gen->second);
00454
00455 if (! registry_->readEntries(child, child.getName(), genotypeId))
00456 return false;
00457 }
00458
00459 return true;
00460 }
00461
00462
00469 bool State::initializeComponents(int argc, char **argv)
00470 {
00471 try {
00472
00473 context_->initialize();
00474
00475 logger_->initialize(state_);
00476 randomizer_->initialize(state_);
00477
00478
00479
00480
00481 ECF_LOG(this, 4, "Initializing active genotypes...");
00482 for(uint i = 0; i < genotype_.size(); i++) {
00483 GenotypeP copy = (GenotypeP) genotype_[i]->copy();
00484 bInitialized_ &= copy->initialize(state_);
00485 }
00486 if(!bInitialized_) {
00487 throw "Error: Genotype initialization failed!";
00488 }
00489
00490
00491 bInitialized_ &= comm_->initialize(state_, argc, argv);
00492
00493
00494 ECF_LOG(this, 4, "Initializing population and algorithm...");
00495 algorithm_->evalOp_ = this->evalOp_;
00496 algorithm_->crossover_ = crossover_;
00497 algorithm_->mutation_ = mutation_;
00498 algorithm_->state_ = state_;
00499 algorithm_->initialize(state_);
00500
00501 population_->initialize(state_);
00502 algorithm_->initializeParallel(state_);
00503
00504 ECF_LOG(this, 4, "Initializing genetic operators...");
00505 mutation_->initialize(state_);
00506 crossover_->initialize(state_);
00507 migration_->initialize(state_);
00508
00509
00510 ECF_LOG(this, 4, "Initializing termination operators...");
00511 activeTerminationOps_.clear();
00512 for(uint i = 0; i < allTerminationOps_.size(); i++)
00513 if(allTerminationOps_[i]->initialize(state_))
00514 activeTerminationOps_.push_back(allTerminationOps_[i]);
00515
00516 if(activeTerminationOps_.empty())
00517 activeTerminationOps_.push_back(allTerminationOps_[0]);
00518
00519
00520 ECF_LOG(this, 4, "Initializing user defined operators...");
00521 activeUserOps_.clear();
00522 for(uint i = 0; i < allUserOps_.size(); i++)
00523 if(allUserOps_[i]->initialize(state_))
00524 activeUserOps_.push_back(allUserOps_[i]);
00525
00526
00527 ECF_LOG(this, 4, "Initializing evaluation operator...");
00528 if(!evalOp_->initialize(state_))
00529 throw "Error: Evaluation operator initialization failed!";
00530
00531
00532 ECF_LOG(this, 4, "Generating test individual...");
00533 individual_ = (IndividualP) (new Individual(state_));
00534
00535 }
00536
00537 catch(std::string& msg) {
00538 std::cerr << msg << std::endl;
00539 bInitialized_ = false;
00540 }
00541 catch(const char* msg) {
00542 std::cerr << msg << std::endl;
00543 bInitialized_ = false;
00544 }
00545 catch(...) {
00546 std::cerr << "Unknown error in initialization!" << std::endl;
00547 bInitialized_ = false;
00548 }
00549
00550 return bInitialized_;
00551 }
00552
00553
00555 FitnessP State::getFitnessObject()
00556 {
00557 try {
00558 if(!fitness_) {
00559 context_->evaluatedIndividual = individual_;
00560 fitness_ = evalOp_->evaluate(individual_);
00561 }
00562
00563 }
00564 catch(...) {
00565 std::cerr << "Error in evaluation operator!" << std::endl;
00566 }
00567
00568 return fitness_;
00569 }
00570
00571
00578 bool State::runBatch()
00579 {
00580 bBatchStart_ = false;
00581 bBatchMode_ = true;
00582
00583 bool bUseLog = registry_->isModified("log.filename");
00584
00585
00586 if(!bLoadMilestone_)
00587 batchRemaining_ = batchRepeats_;
00588 uint numerals = 1 + (uint) (log((double) batchRepeats_) / log((double) 10.));
00589
00590
00591 std::string logFileName = *(std::string*) registry_->getEntry("log.filename").get();
00592 std::string logFileExt = "";
00593 if(bLoadMilestone_)
00594 logFileName = batchLogFile_;
00595 else
00596 batchLogFile_ = logFileName;
00597
00598 if(logFileName.find(".") != std::string::npos) {
00599 logFileExt = logFileName.substr(logFileName.find("."));
00600 logFileName = logFileName.substr(0, logFileName.find("."));
00601 }
00602
00603
00604 std::string milestoneName = *(std::string*) registry_->getEntry("milestone.filename").get();
00605 std::string milestoneExt = "";
00606 if(milestoneName.find(".") != std::string::npos) {
00607 milestoneExt = milestoneName.substr(milestoneName.find("."));
00608 milestoneName = milestoneName.substr(0, milestoneName.find("."));
00609 }
00610
00611
00612 std::ofstream statsFile;
00613 if(registry_->isModified("batch.statsfile")) {
00614 if(bLoadMilestone_)
00615 statsFile.open(batchStatsFile_.c_str(), std::ios_base::app);
00616 else {
00617 statsFile.open(batchStatsFile_.c_str());
00618 statsFile << "runId\tfit_min\tfit_max\tfit_avg\tfit_std\t#evals\ttime\tgen\n";
00619 }
00620 if(!statsFile) {
00621 ECF_LOG_ERROR(this, "Error: can't open batch statsfile (" + batchStatsFile_ + ")!");
00622 return false;
00623 }
00624 statsFile.close();
00625 bBatchWriteStats_ = true;
00626 }
00627
00628 uint runId = batchRepeats_ - batchRemaining_ + 1;
00629
00630
00631 for(; runId <= batchRepeats_; runId++) {
00632
00633 if(bUseLog) {
00634 std::stringstream ss;
00635 ss << std::setw(numerals) << std::setfill('0') << runId;
00636 std::string currentLogName = logFileName + "_" + ss.str() + logFileExt;
00637 registry_->modifyEntry("log.filename", (voidP) new std::string(currentLogName));
00638 }
00639
00640
00641 if(!bBatchSingleMilestone_) {
00642 std::stringstream ss;
00643 ss << std::setw(numerals) << std::setfill('0') << runId;
00644 milestoneFilename_ = milestoneName + "_" + ss.str() + milestoneExt;
00645 }
00646
00647
00648 batchRemaining_--;
00649 bInitialized_ = true;
00650 if(!initializeComponents(argc_, argv_))
00651 break;
00652 ECF_LOG(this, 1, "Running in batch mode: run " + uint2str(runId) + "/" + uint2str(batchRepeats_));
00653 run();
00654
00655
00656 if(comm_->getCommGlobalRank() == 0) {
00657 if(bBatchWriteStats_) {
00658 statsFile.open(batchStatsFile_.c_str(), std::ios_base::app);
00659 std::vector<double> stats = population_->getStats()->getStats();
00660 statsFile << runId << '\t';
00661 statsFile << stats[ECF::FIT_LOW] << '\t' << stats[ECF::FIT_HIGH] << '\t' << stats[ECF::FIT_AVG] << '\t' << stats[ECF::FIT_DEV] << '\t';
00662 statsFile << stats[ECF::STAT_EVAL] << '\t' << stats[ECF::STAT_TIME] << '\t' << getGenerationNo() << '\n';
00663 statsFile.close();
00664 }
00665 }
00666 }
00667
00668
00669
00670 bBatchMode_ = false;
00671 comm_->finalize();
00672
00673 if(bInitialized_)
00674 std::cout << "Batch mode end (" << batchRepeats_ << " runs concluded)." << std::endl;
00675
00676 if(statsFile)
00677 statsFile.close();
00678 return true;
00679 }
00680
00681
00682
00693 bool State::initialize(int argc, char **argv)
00694 {
00695 this->state_ = this->getState();
00696
00697 genotype_.clear();
00698 mutation_->operators.clear();
00699 crossover_->operators.clear();
00700
00701 bInitialized_ = false;
00702 argc_ = argc;
00703 argv_ = argv;
00704
00705 try {
00706
00707 std::cout << "-- ECF, version " << ECF_VERSION << " --" << std::endl;
00708
00709 if(!bEvaluatorSet_) {
00710 throw "Error: no EvaluateOp defined!";
00711 }
00712
00713 std::string config_file;
00714 if (argc > 1) {
00715
00716 if(parseCommandLine(argc, argv))
00717 return false;
00718
00719
00720 config_file = argv[1];
00721 }
00722
00723 registerParameters();
00724
00725 if (config_file != "") {
00726 parseConfig(config_file);
00727 }
00728 else {
00729 std::cout << "Warning: no configuration file given." << std::endl;
00730 std::cout << "Example usage: <ECF_executable> <parameter_file>" << std::endl;
00731 }
00732
00733
00734 if (!bAlgorithmSet_)
00735 algorithm_ = mAlgorithms_.find("SteadyStateTournament")->second;
00736
00737 if(!bGenotypeSet_) {
00738 throw "Error: no Genotype defined!";
00739 }
00740
00741 readParameters();
00742
00743
00744 bInitialized_ = true;
00745
00746
00747 if(bBatchStart_)
00748 return true;
00749
00750 initializeComponents(argc, argv);
00751
00752 if(bLoadMilestone_)
00753 loadMilestone();
00754
00755 ECF_LOG(this, 4, "Initialization complete.");
00756
00757 }
00758
00759 catch(std::string& msg) {
00760 std::cerr << msg << std::endl;
00761 }
00762 catch(const char* msg) {
00763 std::cerr << msg << std::endl;
00764 }
00765 catch(...) {
00766 std::cerr << "Unknown error in initialization!" << std::endl;
00767 }
00768
00769 return bInitialized_;
00770 }
00771
00772
00773
00779 bool State::parseCommandLine(int argc, char** argv)
00780 {
00781
00782 std::vector< std::string > arg;
00783 for(int i = 0; i < argc; i++)
00784 arg.push_back(argv[i]);
00785
00786 bCommandLine_ = true;
00787
00788
00789 if(arg[1] == "-gui") {
00790 if(argc > 3 && arg[2] == "-pardump")
00791 dumpParameters(arg[3], false);
00792 }
00793
00794
00795 else if(arg[1] == "-pardump") {
00796 if(argc < 3) {
00797 std::cerr << "No output file given for parameter dump! (usage: <executable> -pardump <filename>)" << std::endl;
00798 }
00799 else {
00800 std::cout << "Exporting complete parameter list to \'" << arg[2] << "\'...\n";
00801 dumpParameters(arg[2]);
00802 }
00803 }
00804
00805
00806 else if(arg[1].substr(0,2) == "-h" || arg[1].substr(0,3) == "--h") {
00807 std::cout << "Current command line arguments:\n";
00808 std::cout << "\t<parameter_file> run ECF with given parameter file\n";
00809 std::cout << "\t-pardump <file> dump all parameters in a given file\n";
00810 std::cout << "\t-h, -help display this help\n";
00811 }
00812
00813 else
00814 bCommandLine_ = false;
00815
00816 return bCommandLine_;
00817 }
00818
00819
00820
00824 bool State::isImplicitParallel()
00825 { return algorithm_->isImplicitParallel(); }
00826
00827
00831 bool State::isAlgorithmParallel()
00832 { return algorithm_->isParallel(); }
00833
00834
00839 void State::write(XMLNode& xState)
00840 {
00841 registry_->modifyEntry("milestone.generation_", (voidP) (new uint(getGenerationNo())));
00842 registry_->modifyEntry("milestone.elapsedtime_", (voidP) (new time_t(elapsedTime_)));
00843 registry_->modifyEntry("batch.remaining_", (voidP) (new uint(batchRemaining_)));
00844 if(registry_->isModified("log.filename"))
00845 registry_->modifyEntry("batch.logfile_", (voidP) (new std::string(batchLogFile_)));
00846 }
00847
00848
00853 void State::saveMilestone()
00854 {
00855 XMLNode xMainNode = XMLNode::createXMLTopNode("ECF");
00856 xMainNode.addAttribute("milestone", ctime(¤tTime_));
00857
00858 XMLNode xMilestone;
00859 this->write(xMilestone);
00860 xMainNode.addChild(xMilestone);
00861
00862 XMLNode xNode = this->xConfig_.getChildNode(NODE_ALGORITHM);
00863 xNode = xNode.deepCopy();
00864 xMainNode.addChild(xNode);
00865 xNode = this->xConfig_.getChildNode(NODE_GENOTYPE);
00866 xNode = xNode.deepCopy();
00867 xMainNode.addChild(xNode);
00868
00869 this->registry_->write(xNode);
00870 xMainNode.addChild(xNode);
00871
00872
00873 XMLNode xPopulation;
00874 population_->write(xPopulation);
00875 xMainNode.addChild(xPopulation);
00876
00877 #ifdef _MPI
00878 if(comm_->getCommGlobalRank() != 0)
00879 return;
00880 #endif
00881
00882 xMainNode.writeToFile(milestoneFilename_.c_str());
00883 }
00884
00885
00890 void State::loadMilestone()
00891 {
00892 ECF_LOG(this, 4, "Loading population and evolutionary context from milestone...");
00893 XMLNode xPopulation = xConfig_.getChildNode("Population");
00894 population_->read(xPopulation);
00895
00896 context_->generationNo_ = milestoneGeneration_;
00897 }
00898
00899
00900
00901
00902
00903
00904
00914 uint State::setGenotype(GenotypeP genotype)
00915 {
00916 genotype_.push_back((GenotypeP) genotype->copy());
00917 uint index = (uint) genotype_.size() - 1;
00918 genotype_[index]->setGenotypeId(index);
00919 genotype->setGenotypeId(index);
00920
00921 genotype_[index]->registerParameters(state_);
00922
00923
00924 crossover_->operators.push_back(genotype_[index]->getCrossoverOp());
00925 for(uint iOp = 0; iOp < crossover_->operators[index].size(); iOp++) {
00926 crossover_->operators[index][iOp]->myGenotype_ = genotype_[index];
00927 crossover_->operators[index][iOp]->registerParameters(state_);
00928 }
00929
00930 mutation_->operators.push_back(genotype_[index]->getMutationOp());
00931 for(uint iOp = 0; iOp < mutation_->operators[index].size(); iOp++) {
00932 mutation_->operators[index][iOp]->myGenotype_ = genotype_[index];
00933 mutation_->operators[index][iOp]->registerParameters(state_);
00934 }
00935
00936 bGenotypeSet_ = true;
00937 return index;
00938 }
00939
00941 void State::setAlgorithm(AlgorithmP algorithm)
00942 {
00943 algorithm_ = algorithm;
00944 bAlgorithmSet_ = true;
00945 }
00946
00947
00953 void State::setEvalOp(EvaluateOpP eval)
00954 {
00955 evalOp_ = eval;
00956 bEvaluatorSet_ = true;
00957 }
00958
00959
00965 void State::setEvalOp(EvaluateOp* eval)
00966 {
00967 evalOp_ = (EvaluateOpP) eval;
00968 bEvaluatorSet_ = true;
00969 }
00970
00971
00972
00973
00974
00975
00984 bool State::addGenotype(GenotypeP gen)
00985 {
00986 mGenotypes_[gen->getName()] = gen;
00987 return true;
00988 }
00989
00990
00999 bool State::addAlgorithm(AlgorithmP alg)
01000 {
01001 mAlgorithms_[alg->getName()] = alg;
01002 return true;
01003 }
01004
01012 bool State::addOperator(OperatorP op)
01013 {
01014 allUserOps_.push_back(op);
01015 return true;
01016 }
01017
01018
01019
01020
01021
01022
01023
01024 #ifndef _MPI
01025
01031 bool State::run()
01032 {
01033
01034 if(bCommandLine_)
01035 return false;
01036
01037 if(!bInitialized_) {
01038 std::cerr << "Error: Initialization failed!" << std::endl;
01039 return false;
01040 }
01041
01042 if(bBatchStart_) {
01043 ECF_LOG(this, 5, "Batch mode detected: running batch");
01044 runBatch();
01045 return true;
01046 }
01047
01048 startTime_ = time(NULL);
01049 std::string stime = ctime(&startTime_);
01050 ECF_LOG(this, 3, "Start time: " + stime);
01051
01052 startTime_ -= milestoneElapsedTime_;
01053
01054
01055 ECF_LOG(this, 2, "Evaluating initial population...");
01056 algorithm_->initializePopulation(state_);
01057
01058 currentTime_ = time(NULL);
01059 elapsedTime_ = currentTime_ - startTime_;
01060 ECF_LOG(this, 2, "Generation: " + uint2str(context_->generationNo_));
01061 ECF_LOG(this, 2, "Elapsed time: " + uint2str((uint) elapsedTime_));
01062 population_->updateDemeStats();
01063
01064
01065 ECF_LOG(this, 4, "Calling user defined operators...");
01066 for(uint i = 0; i < activeUserOps_.size(); i++)
01067 activeUserOps_[i]->operate(state_);
01068
01069
01070 ECF_LOG(this, 4, "Checking termination conditions...");
01071 for(uint i = 0; i < activeTerminationOps_.size(); i++)
01072 activeTerminationOps_[i]->operate(state_);
01073
01074
01075 while(context_->bTerminate_ == false) {
01076 context_->generationNo_++;
01077 ECF_LOG(this, 5, "Calling the active algorithm");
01078 algorithm_->advanceGeneration(state_);
01079
01080 currentTime_ = time(NULL);
01081 elapsedTime_ = currentTime_ - startTime_;
01082 ECF_LOG(this, 2, "Generation: " + uint2str(context_->generationNo_));
01083 ECF_LOG(this, 2, "Elapsed time: " + uint2str((uint) elapsedTime_));
01084
01085 population_->updateDemeStats();
01086
01087
01088 ECF_LOG(this, 4, "Calling user defined operators...");
01089 for(uint i = 0; i < activeUserOps_.size(); i++)
01090 activeUserOps_[i]->operate(state_);
01091
01092
01093 ECF_LOG(this, 4, "Checking termination conditions...");
01094 for(uint i = 0; i < activeTerminationOps_.size(); i++)
01095 activeTerminationOps_[i]->operate(state_);
01096
01097 if(context_->bTerminate_)
01098 logger_->saveTo(true);
01099 else
01100 logger_->saveTo();
01101
01102 if(bSaveMilestone_ &&
01103 milestoneInterval_ > 0 && context_->generationNo_ % milestoneInterval_ == 0)
01104 saveMilestone();
01105
01106 migration_->operate(state_);
01107 }
01108
01109
01110 XMLNode xHoF;
01111 population_->getHof()->write(xHoF);
01112 char *out = xHoF.createXMLString(true);
01113 ECF_LOG(this, 1, "\nBest of run: \n" + std::string(out));
01114 freeXMLString(out);
01115
01116 logger_->saveTo(true);
01117 if(bSaveMilestone_)
01118 saveMilestone();
01119
01120 logger_->closeLog();
01121
01122 return true;
01123 }
01124
01125
01126 #else // _MPI
01127
01133 bool State::run()
01134 {
01135
01136 if(bCommandLine_)
01137 return false;
01138
01139 if(bBatchStart_) {
01140 runBatch();
01141 return true;
01142 }
01143
01144
01145 if(!bInitialized_) {
01146 std::cerr << "Error: Initialization failed!" << std::endl;
01147 logger_->saveTo();
01148 if(comm_->isInitialized())
01149 comm_->finalize();
01150 return false;
01151 }
01152
01153 startTime_ = time(NULL);
01154 std::string stime = ctime(&startTime_);
01155 ECF_LOG(this, 3, "Start time: " + stime);
01156
01157 startTime_ -= milestoneElapsedTime_;
01158
01159
01160
01161
01162 if(comm_->getCommRank() == 0) {
01163 ECF_LOG(this, 2, "Evaluating initial population...");
01164 }
01165
01166
01167 algorithm_->initializePopulation(state_);
01168 comm_->synchronize();
01169
01170 if(comm_->getCommRank() == 0) {
01171
01172 if(isImplicitParallel())
01173 algorithm_->initializeImplicit(state_);
01174 }
01175
01176
01177 while(context_->bTerminate_ == false) {
01178
01179 currentTime_ = time(NULL);
01180 elapsedTime_ = currentTime_ - startTime_;
01181 if(comm_->getCommGlobalRank() == 0) {
01182 ECF_LOG(this, 2, "Generation: " + uint2str(context_->generationNo_));
01183 ECF_LOG(this, 2, "Elapsed time: " + uint2str((uint) elapsedTime_));
01184 }
01185
01186
01187 if(comm_->getCommRank() == 0) {
01188 population_->updateDemeStats();
01189
01190 if(bSaveMilestone_ && milestoneInterval_ > 0 && context_->generationNo_ % milestoneInterval_ == 0)
01191 saveMilestone();
01192 }
01193
01194
01195 if(comm_->getCommGlobalRank() == 0) {
01196 ECF_LOG(this, 4, "Checking termination conditions...");
01197 for(uint i = 0; i < activeTerminationOps_.size(); i++)
01198 activeTerminationOps_[i]->operate(state_);
01199
01200 for(uint i = 1; i < population_->getNoDemes(); i++)
01201 comm_->sendTerminateMessage(comm_->getDemeMaster(i), context_->bTerminate_);
01202 }
01203
01204 else if(comm_->getCommRank() == 0)
01205 context_->bTerminate_ = comm_->recvTerminateMessage(0);
01206
01207
01208 algorithm_->bcastTermination(state_);
01209
01210
01211 if(comm_->getCommRank() == 0) {
01212 migration_->operate(state_);
01213 }
01214
01215
01216 ECF_LOG(this, 4, "Calling user defined operators...");
01217 for(uint i = 0; i < activeUserOps_.size(); i++)
01218 activeUserOps_[i]->operate(state_);
01219
01220 if(context_->bTerminate_ == true) {
01221 logger_->saveTo(true);
01222 break;
01223 }
01224
01225 logger_->saveTo();
01226
01227 context_->generationNo_++;
01228 ECF_LOG(this, 5, "Calling the active algorithm");
01229 algorithm_->advanceGeneration(state_);
01230 }
01231
01232 logger_->setLogFrequency(1);
01233 if(comm_->getCommGlobalRank() == 0) {
01234
01235 XMLNode xHoF;
01236 population_->getHof()->write(xHoF);
01237 std::string out = xHoF.createXMLString(true);
01238 ECF_LOG(this, 1, "\nBest of run: \n" + out);
01239
01240 logger_->saveTo(true);
01241 }
01242
01243 if(comm_->getCommRank() == 0 && bSaveMilestone_)
01244 saveMilestone();
01245
01246 logger_->saveTo(true);
01247
01248
01249 comm_->finalize();
01250
01251 return true;
01252 }
01253 #endif // _MPI