• 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     alg = static_cast<AlgorithmP> (new EvolutionStrategy);
00059     this->mAlgorithms_[alg->getName()] = alg;
00060 
00061 #ifdef _MPI
00062     // paralel algorithms
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     // genotypes
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 //  gen = static_cast<GenotypeP> (new cart::Cartesian);
00083 //  this->mGenotypes_[gen->getName()] = gen;
00084 
00085     // termination operators
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     // State parameters
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     // milestone data
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     // call registerParameters() methods:
00132     alg_iter itAlg;
00133     for(itAlg = mAlgorithms_.begin(); itAlg != mAlgorithms_.end(); ++itAlg)
00134         itAlg->second->registerParameters(state_);
00135 
00136     // register common implicit parallel parameters (defined in Algorithm base class)
00137     mAlgorithms_.begin()->second->registerParallelParameters(state_);
00138 
00139     // register termination operators' parameters
00140     for(uint i = 0; i < allTerminationOps_.size(); i++)
00141         allTerminationOps_[i]->registerParameters(state_);
00142 
00143     // user-defined operators
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     // milestone saving data
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     // milestone loading data
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     // batch running data
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(); // obtain a sptr to this
00222     // register all parameters (except genotypes which are normally parsed from config)
00223     this->registerParameters();
00224 
00225     // register parameters for all the genotypes
00226     for(gen_iter itGen = mGenotypes_.begin(); itGen != mGenotypes_.end(); ++itGen) {
00227         itGen->second->setGenotypeId(0);
00228         itGen->second->registerParameters(state_);
00229 
00230         // register all crx operators
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         // register all mutation operators
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     // get all parameters
00246     XMLNode xRegistry;
00247     this->registry_->dumpEntries(xRegistry);
00248 
00249     // create Algorithm node
00250     XMLNode xAlgorithms = XMLNode::createXMLTopNode(NODE_ALGORITHM);
00251     xMainNode.addChild(xAlgorithms);
00252 
00253     // extract all algorithms
00254     alg_iter itAlg;
00255     for(itAlg = mAlgorithms_.begin(); itAlg != mAlgorithms_.end(); ++itAlg) {
00256         
00257         // get algorithm name, create subnode
00258         std::string algorithmName = itAlg->first;
00259         XMLNode xAlgorithm = XMLNode::createXMLTopNode(algorithmName.c_str());
00260         xAlgorithms.addChild(xAlgorithm);
00261 
00262         // iterate over all entries
00263         for(int i = 0; i < xRegistry.nChildNode(); i++) {
00264             XMLNode child = xRegistry.getChildNode(i);
00265             std::string key = child.getAttributeValue();
00266             // compare to selected Algorithm
00267             if(key.compare(0, algorithmName.size(), algorithmName) == 0) {
00268                 // copy entry, delete the original
00269                 XMLNode xEntry = child.deepCopy();
00270                 child.deleteNodeContent();
00271                 i--;
00272 
00273                 // remove algorithm name
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                 // optional: copy description attribute to XML comment
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     // create Genotype node
00291     XMLNode xGenotypes = XMLNode::createXMLTopNode(NODE_GENOTYPE);
00292     xMainNode.addChild(xGenotypes);
00293 
00294     // extract all genotypes
00295     for(gen_iter itGen = mGenotypes_.begin(); itGen != mGenotypes_.end(); ++itGen) {
00296         
00297         // get genotype name, create subnode
00298         std::string genotypeName = itGen->first;
00299         XMLNode xGenotype = XMLNode::createXMLTopNode(genotypeName.c_str());
00300         xGenotypes.addChild(xGenotype);
00301 
00302         // iterate over all entries
00303         for(int i = 0; i < xRegistry.nChildNode(); i++) {
00304             XMLNode child = xRegistry.getChildNode(i);
00305             std::string key = child.getAttributeValue();
00306             // compare to selected Algorithm
00307             if(key.compare(0, genotypeName.size(), genotypeName) == 0) {
00308                 // copy entry, delete the original
00309                 XMLNode xEntry = child.deepCopy();
00310                 child.deleteNodeContent();
00311                 i--;
00312 
00313                 // remove algorithm name
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                 // optional: copy description attribute to XML comment
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     // optional: copy description for all registry entries
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         // add remaining Registry entries
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         // initialize evolutionary context
00473         context_->initialize();
00474 
00475         logger_->initialize(state_);
00476         randomizer_->initialize(state_);
00477 
00478         // initialize single instance of active genotypes
00479         // (active genotypes - the ones that the individuals are made of, which is defined in the configuration file)
00480         // State keeps a single uninitialized object of all active Genotypes
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         // MPI communicator
00491         bInitialized_ &= comm_->initialize(state_, argc, argv);
00492 
00493         // damo algoritmu pointer na operator evaluacije i pointere na repozitorij krizanja i mutacije
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_); // provjera impl. paralelizacije (nakon population_->initialize zbog podjele procesa po demovima)
00503 
00504         ECF_LOG(this, 4, "Initializing genetic operators...");
00505         mutation_->initialize(state_);
00506         crossover_->initialize(state_);
00507         migration_->initialize(state_);
00508 
00509         // initialize termination ops
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         // if no term operators are configured, activate default (the first)
00516         if(activeTerminationOps_.empty())
00517             activeTerminationOps_.push_back(allTerminationOps_[0]);
00518 
00519         // initialize user ops
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         // evaluation op. initializes last
00527         ECF_LOG(this, 4, "Initializing evaluation operator...");
00528         if(!evalOp_->initialize(state_))
00529             throw "Error: Evaluation operator initialization failed!";
00530 
00531         // generate one individual
00532         ECF_LOG(this, 4, "Generating test individual...");
00533         individual_ = (IndividualP) (new Individual(state_));
00534 
00535     } // try
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     // are we restoring from a milestone file
00586     if(!bLoadMilestone_)
00587         batchRemaining_ = batchRepeats_;
00588     uint numerals = 1 + (uint) (log((double) batchRepeats_) / log((double) 10.));
00589 
00590     // get logfile name and extension
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     // get milestone name and extension
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     // (re)open stats file, if defined
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     // perform algorithm runs
00631     for(; runId <= batchRepeats_; runId++) {
00632         // set current logfile
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         // set current milestone
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         // run
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         // write stats (PECF: only master process)
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     // ugly workabout for MPI_Finalize, which may only be called once
00669     // (shouldn't be called at the end of a single run)
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(); // obtain a sptr to this
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             // parse arguments: return success if command line option is recognized
00716             if(parseCommandLine(argc, argv))
00717                 return false;
00718 
00719             // otherwise, assume configuration file name as argument
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         // use the default algorithm
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         // set init flag, then test with each component initialization
00744         bInitialized_ = true;
00745 
00746         // if multiple runs, components will get initialized with State::run()
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     } // try
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     // read all arguments
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     // GUI related arguments
00789     if(arg[1] == "-gui") {
00790         if(argc > 3 && arg[2] == "-pardump")
00791             dumpParameters(arg[3], false);
00792     }
00793 
00794     // dump all parameters
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     // display cmd arguments
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(&currentTime_));
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     // save population
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 // setting components
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     // read genotype's operators and register their parameters
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 // adding components
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 // run methods
01022 //
01023 
01024 #ifndef _MPI
01025 
01031 bool State::run()
01032 {
01033     // command line only (no evolution)
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     // adjust with previous runtime (from milestone)
01052     startTime_ -= milestoneElapsedTime_;
01053 
01054     // evaluate initial population
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     // call user-defined operators
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     // termination ops
01070     ECF_LOG(this, 4, "Checking termination conditions...");
01071     for(uint i = 0; i < activeTerminationOps_.size(); i++)
01072         activeTerminationOps_[i]->operate(state_);
01073 
01074     // run the algorithm
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         // call user-defined operators
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         // termination ops
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     // output HallOfFame
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     // command line only (no evolution)
01136     if(bCommandLine_)
01137         return false;
01138 
01139     if(bBatchStart_) {
01140         runBatch();
01141         return true;
01142     }
01143 
01144     // TODO: perform AND_reduce with bInitialized on all processes
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     // adjust with previous runtime (from milestone)
01157     startTime_ -= milestoneElapsedTime_;
01158 
01159     // in PECF, every process works with deme '0'
01160     // 'deme masters' - processes with index 0 in local communicator
01161     // only deme masters know of whole population
01162     if(comm_->getCommRank() == 0) {
01163         ECF_LOG(this, 2, "Evaluating initial population...");
01164     }
01165 
01166     // every process participates in the initial population evaluation
01167     algorithm_->initializePopulation(state_);
01168     comm_->synchronize();
01169 
01170     if(comm_->getCommRank() == 0) {
01171         // dodatna inicijalizacija za implicitni paralelizam - mozda promijeniti...
01172         if(isImplicitParallel())
01173             algorithm_->initializeImplicit(state_);
01174     }
01175 
01176     // run the algorithm
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         // deme masters initiate population statistics and HoF update
01187         if(comm_->getCommRank() == 0) {
01188             population_->updateDemeStats();
01189 
01190             if(bSaveMilestone_ && milestoneInterval_ > 0 && context_->generationNo_ % milestoneInterval_ == 0)
01191                 saveMilestone();
01192         }
01193 
01194         // global process 0 checks termination condition and signals deme masters
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         // deme masters receive info
01204         else if(comm_->getCommRank() == 0)
01205             context_->bTerminate_ = comm_->recvTerminateMessage(0);
01206 
01207         // deme masters signal workers of evolution continuation
01208         algorithm_->bcastTermination(state_);
01209 
01210         // deme masters call migration operator
01211         if(comm_->getCommRank() == 0) {
01212             migration_->operate(state_);
01213         }
01214 
01215         // call user-defined operators
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         // output HallOfFame
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     // communicator
01249     comm_->finalize();
01250 
01251     return true;
01252 }
01253 #endif // _MPI

Generated on Tue Nov 4 2014 13:04:31 for ECF by  doxygen 1.7.1