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