• Main Page
  • Modules
  • Classes
  • Files
  • File List

D:/Projekt/ECF_trunk/ECF/State.cpp

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);   // XML encoding
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     // register existing components:
00033     // algorithms
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     // paralel algorithms
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     // genotypes
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 //  gen = static_cast<GenotypeP> (new cart::Cartesian);
00081 //  this->mGenotypes_[gen->getName()] = gen;
00082 
00083     // termination operators
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     // State parameters
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     // milestone data
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     // call registerParameters() methods:
00130     alg_iter itAlg;
00131     for(itAlg = mAlgorithms_.begin(); itAlg != mAlgorithms_.end(); ++itAlg)
00132         itAlg->second->registerParameters(state_);
00133 
00134     // register common implicit parallel parameters (defined in Algorithm base class)
00135     mAlgorithms_.begin()->second->registerParallelParameters(state_);
00136 
00137     // register termination operators' parameters
00138     for(uint i = 0; i < allTerminationOps_.size(); i++)
00139         allTerminationOps_[i]->registerParameters(state_);
00140 
00141     // user-defined operators
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     // milestone saving data
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     // milestone loading data
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     // batch running data
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(); // obtain a sptr to this
00220     // register all parameters (except genotypes which are normally parsed from config)
00221     this->registerParameters();
00222 
00223     // register parameters for all the genotypes
00224     for(gen_iter itGen = mGenotypes_.begin(); itGen != mGenotypes_.end(); ++itGen) {
00225         itGen->second->setGenotypeId(0);
00226         itGen->second->registerParameters(state_);
00227 
00228         // register all crx operators
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         // register all mutation operators
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     // get all parameters
00244     XMLNode xRegistry;
00245     this->registry_->dumpEntries(xRegistry);
00246 
00247     // create Algorithm node
00248     XMLNode xAlgorithms = XMLNode::createXMLTopNode(NODE_ALGORITHM);
00249     xMainNode.addChild(xAlgorithms);
00250 
00251     // extract all algorithms
00252     alg_iter itAlg;
00253     for(itAlg = mAlgorithms_.begin(); itAlg != mAlgorithms_.end(); ++itAlg) {
00254         
00255         // get algorithm name, create subnode
00256         std::string algorithmName = itAlg->first;
00257         XMLNode xAlgorithm = XMLNode::createXMLTopNode(algorithmName.c_str());
00258         xAlgorithms.addChild(xAlgorithm);
00259 
00260         // iterate over all entries
00261         for(int i = 0; i < xRegistry.nChildNode(); i++) {
00262             XMLNode child = xRegistry.getChildNode(i);
00263             std::string key = child.getAttributeValue();
00264             // compare to selected Algorithm
00265             if(key.compare(0, algorithmName.size(), algorithmName) == 0) {
00266                 // copy entry, delete the original
00267                 XMLNode xEntry = child.deepCopy();
00268                 child.deleteNodeContent();
00269                 i--;
00270 
00271                 // remove algorithm name
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                 // optional: copy description attribute to XML comment
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     // create Genotype node
00289     XMLNode xGenotypes = XMLNode::createXMLTopNode(NODE_GENOTYPE);
00290     xMainNode.addChild(xGenotypes);
00291 
00292     // extract all genotypes
00293     for(gen_iter itGen = mGenotypes_.begin(); itGen != mGenotypes_.end(); ++itGen) {
00294         
00295         // get genotype name, create subnode
00296         std::string genotypeName = itGen->first;
00297         XMLNode xGenotype = XMLNode::createXMLTopNode(genotypeName.c_str());
00298         xGenotypes.addChild(xGenotype);
00299 
00300         // iterate over all entries
00301         for(int i = 0; i < xRegistry.nChildNode(); i++) {
00302             XMLNode child = xRegistry.getChildNode(i);
00303             std::string key = child.getAttributeValue();
00304             // compare to selected Algorithm
00305             if(key.compare(0, genotypeName.size(), genotypeName) == 0) {
00306                 // copy entry, delete the original
00307                 XMLNode xEntry = child.deepCopy();
00308                 child.deleteNodeContent();
00309                 i--;
00310 
00311                 // remove algorithm name
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                 // optional: copy description attribute to XML comment
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     // optional: copy description for all registry entries
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         // add remaining Registry entries
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         // initialize evolutionary context
00471         context_->initialize();
00472 
00473         logger_->initialize(state_);
00474         randomizer_->initialize(state_);
00475 
00476         // initialize single instance of active genotypes
00477         // (active genotypes - the ones that the individuals are made of, which is defined in the configuration file)
00478         // State keeps a single uninitialized object of all active Genotypes
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         // MPI communicator
00489         bInitialized_ &= comm_->initialize(state_, argc, argv);
00490 
00491         // damo algoritmu pointer na operator evaluacije i pointere na repozitorij krizanja i mutacije
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_); // provjera impl. paralelizacije (nakon population_->initialize zbog podjele procesa po demovima)
00501 
00502         ECF_LOG(this, 4, "Initializing genetic operators...");
00503         mutation_->initialize(state_);
00504         crossover_->initialize(state_);
00505         migration_->initialize(state_);
00506 
00507         // initialize termination ops
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         // if no term operators are configured, activate default (the first)
00514         if(activeTerminationOps_.empty())
00515             activeTerminationOps_.push_back(allTerminationOps_[0]);
00516 
00517         // initialize user ops
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         // evaluation op. initializes last
00525         ECF_LOG(this, 4, "Initializing evaluation operator...");
00526         if(!evalOp_->initialize(state_))
00527             throw "Error: Evaluation operator initialization failed!";
00528 
00529         // generate one individual
00530         ECF_LOG(this, 4, "Generating test individual...");
00531         individual_ = (IndividualP) (new Individual(state_));
00532 
00533     } // try
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     // are we restoring from a milestone file
00584     if(!bLoadMilestone_)
00585         batchRemaining_ = batchRepeats_;
00586     uint numerals = 1 + (uint) (log((double) batchRepeats_) / log((double) 10.));
00587 
00588     // get logfile name and extension
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     // get milestone name and extension
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     // (re)open stats file, if defined
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     // perform algorithm runs
00629     for(; runId <= batchRepeats_; runId++) {
00630         // set current logfile
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         // set current milestone
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         // run
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         // write stats (PECF: only master process)
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     // ugly workabout for MPI_Finalize, which may only be called once
00666     // (shouldn't be called at the end of a single run)
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(); // obtain a sptr to this
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             // parse arguments: return success if command line option is recognized
00713             if(parseCommandLine(argc, argv))
00714                 return false;
00715 
00716             // otherwise, assume configuration file name as argument
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         // use the default algorithm
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         // set init flag, then test with each component initialization
00741         bInitialized_ = true;
00742 
00743         // if multiple runs, components will get initialized with State::run()
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     } // try
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     // read all arguments
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     // GUI related arguments
00786     if(arg[1] == "-gui") {
00787         if(argc > 3 && arg[2] == "-pardump")
00788             dumpParameters(arg[3], false);
00789     }
00790 
00791     // dump all parameters
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     // display cmd arguments
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(&currentTime_));
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     // save population
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 // setting components
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     // read genotype's operators and register their parameters
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 // adding components
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 // run methods
01019 //
01020 
01021 #ifndef _MPI
01022 
01028 bool State::run()
01029 {
01030     // command line only (no evolution)
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     // adjust with previous runtime (from milestone)
01049     startTime_ -= milestoneElapsedTime_;
01050 
01051     // evaluate initial population
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     // call user-defined operators
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     // termination ops
01067     ECF_LOG(this, 4, "Checking termination conditions...");
01068     for(uint i = 0; i < activeTerminationOps_.size(); i++)
01069         activeTerminationOps_[i]->operate(state_);
01070 
01071     // run the algorithm
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         // call user-defined operators
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         // termination ops
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     // output HallOfFame
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     // command line only (no evolution)
01133     if(bCommandLine_)
01134         return false;
01135 
01136     if(bBatchStart_) {
01137         runBatch();
01138         return true;
01139     }
01140 
01141     // TODO: perform AND_reduce with bInitialized on all processes
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     // adjust with previous runtime (from milestone)
01154     startTime_ -= milestoneElapsedTime_;
01155 
01156     // in PECF, every process works with deme '0'
01157     // 'deme masters' - processes with index 0 in local communicator
01158     // only deme masters know of whole population
01159     if(comm_->getCommRank() == 0) {
01160         ECF_LOG(this, 2, "Evaluating initial population...");
01161     }
01162 
01163     // every process participates in the initial population evaluation
01164     algorithm_->initializePopulation(state_);
01165     comm_->synchronize();
01166 
01167     if(comm_->getCommRank() == 0) {
01168         // dodatna inicijalizacija za implicitni paralelizam - mozda promijeniti...
01169         if(isImplicitParallel())
01170             algorithm_->initializeImplicit(state_);
01171     }
01172 
01173     // run the algorithm
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         // deme masters initiate population statistics and HoF update
01184         if(comm_->getCommRank() == 0) {
01185             population_->updateDemeStats();
01186 
01187             if(bSaveMilestone_ && milestoneInterval_ > 0 && context_->generationNo_ % milestoneInterval_ == 0)
01188                 saveMilestone();
01189         }
01190 
01191         // global process 0 checks termination condition and signals deme masters
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         // deme masters receive info
01201         else if(comm_->getCommRank() == 0)
01202             context_->bTerminate_ = comm_->recvTerminateMessage(0);
01203 
01204         // deme masters signal workers of evolution continuation
01205         algorithm_->bcastTermination(state_);
01206 
01207         // deme masters call migration operator
01208         if(comm_->getCommRank() == 0) {
01209             migration_->operate(state_);
01210         }
01211 
01212         // call user-defined operators
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         // output HallOfFame
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     // communicator
01246     comm_->finalize();
01247 
01248     return true;
01249 }
01250 #endif // _MPI

Generated on Sat Jul 12 2014 07:29:31 for ECF by  doxygen 1.7.1