ECF 1.7
State.cpp
1#include "ECF.h"
2#include <fstream>
3#include <iomanip>
4#include <time.h>
5
6
13{
14 this->population_ = static_cast<PopulationP> (new Population);
15 this->crossover_ = static_cast<CrossoverP> (new Crossover);
16 this->mutation_ = static_cast<MutationP> (new Mutation);
17 this->context_ = static_cast<EvolutionContextP> (new EvolutionContext);
18
19 XMLNode::setGlobalOptions(XMLNode::char_encoding_legacy); // XML encoding
20
21 bInitialized_ = false;
22 bCommandLine_ = false;
23 bAlgorithmSet_ = false;
24 bGenotypeSet_ = false;
25 bEvaluatorSet_ = false;
26 bLoadMilestone_ = false;
27 bBatchMode_ = false;
28 bBatchStart_ = false;
29 bBatchSingleMilestone_ = false;
30 bBatchWriteStats_ = false;
31
32 // register existing components:
33 // algorithms
34 AlgorithmP alg = static_cast<AlgorithmP> (new SteadyStateTournament);
35 this->mAlgorithms_[alg->getName()] = alg;
36 alg = static_cast<AlgorithmP> (new RouletteWheel);
37 this->mAlgorithms_[alg->getName()] = alg;
38 alg = static_cast<AlgorithmP> (new ParticleSwarmOptimization);
39 this->mAlgorithms_[alg->getName()] = alg;
40 alg = static_cast<AlgorithmP> (new Elimination);
41 this->mAlgorithms_[alg->getName()] = alg;
42 alg = static_cast<AlgorithmP> (new XCS);
43 this->mAlgorithms_[alg->getName()] = alg;
44 alg = static_cast<AlgorithmP> (new RandomSearch);
45 this->mAlgorithms_[alg->getName()] = alg;
46 alg = static_cast<AlgorithmP> (new GeneticAnnealing);
47 this->mAlgorithms_[alg->getName()] = alg;
48 alg = static_cast<AlgorithmP> (new DifferentialEvolution);
49 this->mAlgorithms_[alg->getName()] = alg;
50 alg = static_cast<AlgorithmP> (new ArtificialBeeColony);
51 this->mAlgorithms_[alg->getName()] = alg;
52 alg = static_cast<AlgorithmP> (new GenHookeJeeves);
53 this->mAlgorithms_[alg->getName()] = alg;
54 alg = static_cast<AlgorithmP> (new Clonalg);
55 this->mAlgorithms_[alg->getName()] = alg;
56 alg = static_cast<AlgorithmP> (new OptIA);
57 this->mAlgorithms_[alg->getName()] = alg;
58 alg = static_cast<AlgorithmP> (new EvolutionStrategy);
59 this->mAlgorithms_[alg->getName()] = alg;
60 alg = static_cast<AlgorithmP> (new AlgNSGA2);
61 this->mAlgorithms_[alg->getName()] = alg;
62 alg = static_cast<AlgorithmP> (new CuckooSearch);
63 this->mAlgorithms_[alg->getName()] = alg;
64 alg = static_cast<AlgorithmP> (new AlgGEP);
65 this->mAlgorithms_[alg->getName()] = alg;
66
67#ifdef _MPI
68 // paralel algorithms
69 alg = static_cast<AlgorithmP> (new AlgSGenGpea);
70 this->mAlgorithms_[alg->getName()] = alg;
71 alg = static_cast<AlgorithmP> (new AlgAEliGpea);
72 this->mAlgorithms_[alg->getName()] = alg;
73 alg = static_cast<AlgorithmP> (new AlgAEliGpea2);
74 this->mAlgorithms_[alg->getName()] = alg;
75#endif
76
77 // genotypes
78 GenotypeP gen = static_cast<GenotypeP> (new BitString::BitString);
79 this->mGenotypes_[gen->getName()] = gen;
80 gen = static_cast<GenotypeP> (new Binary::Binary);
81 this->mGenotypes_[gen->getName()] = gen;
82 gen = static_cast<GenotypeP> (new Tree::Tree);
83 this->mGenotypes_[gen->getName()] = gen;
84 gen = static_cast<GenotypeP> (new Permutation::Permutation);
85 this->mGenotypes_[gen->getName()] = gen;
86 gen = static_cast<GenotypeP> (new FloatingPoint::FloatingPoint);
87 this->mGenotypes_[gen->getName()] = gen;
88 gen = static_cast<GenotypeP> (new Tree::APGenotype);
89 this->mGenotypes_[gen->getName()] = gen;
90 gen = static_cast<GenotypeP> (new IntGenotype::IntGenotype);
91 this->mGenotypes_[gen->getName()] = gen;
92 gen = static_cast<GenotypeP> (new GEP::GEPChromosome);
93 this->mGenotypes_[gen->getName()] = gen;
94 gen = static_cast<GenotypeP> (new Cartesian::Cartesian);
95 this->mGenotypes_[gen->getName()] = gen;
96
97 // termination operators
98 OperatorP op = static_cast<OperatorP> (new TermStagnationOp);
99 this->allTerminationOps_.push_back(op);
100 op = static_cast<OperatorP> (new TermMaxGenOp);
101 this->allTerminationOps_.push_back(op);
102 op = static_cast<OperatorP> (new TermFitnessValOp);
103 this->allTerminationOps_.push_back(op);
104 op = static_cast<OperatorP> (new TermMaxTimeOp);
105 this->allTerminationOps_.push_back(op);
106 op = static_cast<OperatorP> (new TermMaxEvalOp);
107 this->allTerminationOps_.push_back(op);
108
109 setRandomizer(static_cast<RandomizerP> (new SimpleRandomizer));
110 this->registry_ = static_cast<RegistryP> (new Registry);
111 this->logger_ = static_cast<LoggerP> (new Logger);
112 this->comm_ = static_cast<CommunicatorP> (new Comm::Communicator);
113 this->migration_ = static_cast<MigrationP> (new Migration);
114}
115
116
121void State::registerParameters()
122{
123 // State parameters
124 registry_->registerEntry("milestone.interval", (voidP) (new uint(0)), ECF::UINT,
125 "milestone saving interval in generations; 0: save only at the end (default: 0)");
126 registry_->registerEntry("milestone.filename", (voidP) (new std::string("milestone.txt")), ECF::STRING,
127 "milestone file (if stated) stores all the population (default: none)");
128 registry_->registerEntry("batch.repeats", (voidP) (new uint(0)), ECF::UINT,
129 "number of independent runs to perform (default: 1)");
130 registry_->registerEntry("batch.singlemilestone", (voidP) (new uint(0)), ECF::UINT,
131 "use only one milestone file for all the batch runs (1) or one for each run (0) (default: 0)");
132 registry_->registerEntry("batch.statsfile", (voidP) (new std::string("")), ECF::STRING,
133 "output batch end of run stats in a single file (default: none)");
134
135 // milestone data
136 registry_->registerEntry("milestone.generation_", (voidP) (new uint(0)), ECF::UINT);
137 registry_->registerEntry("milestone.elapsedtime_", (voidP) (new uint(0)), ECF::UINT);
138 registry_->registerEntry("batch.remaining_", (voidP) (new uint(0)), ECF::UINT);
139 registry_->registerEntry("batch.logfile_", (voidP) (new std::string("")), ECF::STRING);
140
141 ECF_LOG(this, 4, "Registering parameters: algorithms, operators");
142
143 // call registerParameters() methods:
144 alg_iter itAlg;
145 for(itAlg = mAlgorithms_.begin(); itAlg != mAlgorithms_.end(); ++itAlg)
146 itAlg->second->registerParameters(state_);
147
148 // register common implicit parallel parameters (defined in Algorithm base class)
149 mAlgorithms_.begin()->second->registerParallelParameters(state_);
150
151 // register termination operators' parameters
152 for(uint i = 0; i < allTerminationOps_.size(); i++)
153 allTerminationOps_[i]->registerParameters(state_);
154
155 // user-defined operators
156 for(uint i = 0; i < allUserOps_.size(); i++)
157 allUserOps_[i]->registerParameters(state_);
158
159 mutation_->registerParameters(state_);
160 crossover_->registerParameters(state_);
161 randomizer_->registerParameters(state_);
162 population_->registerParameters(state_);
163 logger_->registerParameters(state_);
164 migration_->registerParameters(state_);
165 evalOp_->registerParameters(state_);
166}
167
168
173void State::readParameters()
174{
175 ECF_LOG(this, 4, "Rading parameters from the Registry");
176
177 // milestone saving data
178 if(registry_->isModified("milestone.filename"))
179 bSaveMilestone_ = true;
180 else
181 bSaveMilestone_ = false;
182
183 voidP sptr = registry_->getEntry("milestone.interval");
184 milestoneInterval_ = *((uint*) sptr.get());
185
186 sptr = registry_->getEntry("milestone.filename");
187 milestoneFilename_ = *((std::string*) sptr.get());
188
189 // milestone loading data
190 if(registry_->isModified("milestone.generation_"))
191 bLoadMilestone_ = true;
192 else
193 bLoadMilestone_ = false;
194
195 sptr = registry_->getEntry("milestone.generation_");
196 milestoneGeneration_ = *((uint*) sptr.get());
197
198 sptr = registry_->getEntry("milestone.elapsedtime_");
199 milestoneElapsedTime_ = *((uint*) sptr.get());
200
201 // batch running data
202 sptr = registry_->getEntry("batch.repeats");
203 batchRepeats_ = *((uint*) sptr.get());
204
205 sptr = registry_->getEntry("batch.remaining_");
206 batchRemaining_ = *((uint*) sptr.get());
207
208 sptr = registry_->getEntry("batch.statsfile");
209 batchStatsFile_ = *((std::string*) sptr.get());
210
211 sptr = registry_->getEntry("batch.logfile_");
212 batchLogFile_ = *((std::string*) sptr.get());
213
214 sptr = registry_->getEntry("batch.singlemilestone");
215 bBatchSingleMilestone_ = (*((uint*) sptr.get()) % 2) ? true:false;
216
217 if(registry_->isModified("batch.repeats") && batchRepeats_ > 1)
218 bBatchStart_ = true;
219 else
220 bBatchStart_ = false;
221}
222
223
227void State::dumpParameters(std::string fileName, bool addClear)
228{
229 XMLNode xMainNode = XMLNode::createXMLTopNode("ECF");
230 xMainNode.addAttribute("version", ECF_VERSION.c_str());
231 xMainNode.addClear("ECF parameter dump - list of all parameters", "<!-- ", " -->");
232
233 this->state_ = this->getState(); // obtain a sptr to this
234 // register all parameters (except genotypes which are normally parsed from config)
235 this->registerParameters();
236
237 // register parameters for all the genotypes
238 for(gen_iter itGen = mGenotypes_.begin(); itGen != mGenotypes_.end(); ++itGen) {
239 itGen->second->setGenotypeId(0);
240 itGen->second->registerParameters(state_);
241
242 // register all crx operators
243 std::vector<CrossoverOpP> crx = itGen->second->getCrossoverOp();
244 for(uint iOp = 0; iOp < crx.size(); iOp++) {
245 crx[iOp]->myGenotype_ = itGen->second;
246 crx[iOp]->registerParameters(state_);
247 }
248
249 // register all mutation operators
250 std::vector<MutationOpP> mut = itGen->second->getMutationOp();
251 for(uint iOp = 0; iOp < mut.size(); iOp++) {
252 mut[iOp]->myGenotype_ = itGen->second;
253 mut[iOp]->registerParameters(state_);
254 }
255 }
256
257 // get all parameters
258 XMLNode xRegistry;
259 this->registry_->dumpEntries(xRegistry);
260
261 // create Algorithm node
262 XMLNode xAlgorithms = XMLNode::createXMLTopNode(NODE_ALGORITHM);
263 xMainNode.addChild(xAlgorithms);
264
265 // extract all algorithms
266 alg_iter itAlg;
267 for(itAlg = mAlgorithms_.begin(); itAlg != mAlgorithms_.end(); ++itAlg) {
268
269 // get algorithm name, create subnode
270 std::string algorithmName = itAlg->first;
271 XMLNode xAlgorithm = XMLNode::createXMLTopNode(algorithmName.c_str());
272 xAlgorithms.addChild(xAlgorithm);
273
274 // iterate over all entries
275 for(int i = 0; i < xRegistry.nChildNode(); i++) {
276 XMLNode child = xRegistry.getChildNode(i);
277 std::string key = child.getAttributeValue();
278 // compare to selected Algorithm
279 if(key.compare(0, algorithmName.size(), algorithmName) == 0) {
280 // copy entry, delete the original
281 XMLNode xEntry = child.deepCopy();
282 child.deleteNodeContent();
283 i--;
284
285 // remove algorithm name
286 std::string key = xEntry.getAttribute("key");
287 key.erase(0, algorithmName.length() + 1);
288 xEntry.updateAttribute(key.c_str(), NULL, "key");
289 xAlgorithm.addChild(xEntry);
290
291 // optional: copy description attribute to XML comment
292 std::string desc = xEntry.getAttribute("desc");
293 if(addClear && desc != "") {
294 xAlgorithm.addClear(desc.c_str(), "<!-- ", " -->");
295 }
296 if(addClear)
297 xEntry.deleteAttribute("desc");
298 }
299 }
300 }
301
302 // create Genotype node
303 XMLNode xGenotypes = XMLNode::createXMLTopNode(NODE_GENOTYPE);
304 xMainNode.addChild(xGenotypes);
305
306 // extract all genotypes
307 for(gen_iter itGen = mGenotypes_.begin(); itGen != mGenotypes_.end(); ++itGen) {
308
309 // get genotype name, create subnode
310 std::string genotypeName = itGen->first;
311 XMLNode xGenotype = XMLNode::createXMLTopNode(genotypeName.c_str());
312 xGenotypes.addChild(xGenotype);
313
314 // iterate over all entries
315 for(int i = 0; i < xRegistry.nChildNode(); i++) {
316 XMLNode child = xRegistry.getChildNode(i);
317 std::string key = child.getAttributeValue();
318 // compare to selected Algorithm
319 if(key.compare(0, genotypeName.size(), genotypeName) == 0) {
320 // copy entry, delete the original
321 XMLNode xEntry = child.deepCopy();
322 child.deleteNodeContent();
323 i--;
324
325 // remove algorithm name
326 std::string key = xEntry.getAttribute("key");
327 key.erase(0, genotypeName.length() + 1);
328 xEntry.updateAttribute(key.c_str(), NULL, "key");
329 xGenotype.addChild(xEntry);
330
331 // optional: copy description attribute to XML comment
332 std::string desc = xEntry.getAttribute("desc");
333 if(addClear && desc != "") {
334 xGenotype.addClear(desc.c_str(), "<!-- ", " -->");
335 }
336 if(addClear)
337 xEntry.deleteAttribute("desc");
338 }
339 }
340 }
341
342 // optional: copy description for all registry entries
343 if(addClear) {
344 XMLNode xRegClear = XMLNode::createXMLTopNode(NODE_REGISTRY);
345 for(int i = 0; i < xRegistry.nChildNode(); i++) {
346 XMLNode xEntry = xRegistry.getChildNode(i);
347 XMLNode xE2 = xEntry.deepCopy();
348 std::string desc = xEntry.getAttribute("desc");
349 xE2.deleteAttribute("desc");
350 xRegClear.addChild(xE2);
351 if(desc != "")
352 xRegClear.addClear(desc.c_str(), "<!-- ", " -->");
353 }
354 xMainNode.addChild(xRegClear);
355 }
356 else
357 // add remaining Registry entries
358 xMainNode.addChild(xRegistry);
359
360 // user request
361 if(addClear)
362 xMainNode.writeToFile(fileName.c_str());
363 // GUI request
364 else {
365 std::string output(xMainNode.createXMLString());
366 std::cout << output;
367 }
368}
369
370
371
377bool State::parseConfig(std::string filename)
378{
379 std::ifstream fin(filename.c_str());
380 if (!fin) {
381 throw std::string("Error opening file " + filename);
382 }
383 std::cout << "Parsing configuration file: " << filename << std::endl;
384
385 std::string xmlFile, temp;
386 while (!fin.eof()) {
387 getline(fin, temp);
388 xmlFile += "\n" + temp;
389 }
390
391 XMLResults results;
392 xConfig_ = XMLNode::parseString(xmlFile.c_str(), "ECF", &results);
393 if (results.error != eXMLErrorNone) {
394 std::cout << "Configuration file: " << XMLNode::getError(results.error);
395 std::cout << " (line " << results.nLine << ", col " << results.nColumn << ")" << std::endl;
396 throw("");
397 }
398
399 if (xConfig_.isEmpty())
400 return false;
401
402 int n = xConfig_.nChildNode();
403 for (int i = 0; i < n; ++i) {
404 XMLNode child = xConfig_.getChildNode(i);
405 std::string name = child.getName();
406 bool ok = true;
407
408 if (name == NODE_REGISTRY)
409 ok &= registry_->readEntries(child);
410 else if (name == NODE_ALGORITHM)
411 ok &= parseAlgorithmNode(child);
412 else if (name == NODE_GENOTYPE)
413 ok &= parseGenotypeNode(child);
414 else if (name == NODE_POPULATION)
415 continue;
416 else
417 std::cout << "Unknown node: " << name << std::endl;
418
419 if (!ok)
420 throw "";
421 }
422
423 return true;
424}
425
426
432bool State::parseAlgorithmNode(XMLNode node)
433{
434 int n = node.nChildNode();
435 if (n > 1)
436 std::cout << "Warning: multiple Algorithm nodes found! (using the first one)" << std::endl;
437
438 XMLNode child = node.getChildNode(0);
439 alg_iter alg = mAlgorithms_.find(child.getName());
440 if (alg == mAlgorithms_.end()) {
441 throw std::string("Error: unknown Algorithm : ") + child.getName();
442 }
443
444 algorithm_ = alg->second;
445 bAlgorithmSet_ = true;
446
447 if (! registry_->readEntries(child, child.getName()))
448 return false;
449
450 return true;
451}
452
453
459bool State::parseGenotypeNode(XMLNode node)
460{
461 int n = node.nChildNode();
462 for (int i = 0; i < n; ++i) {
463 XMLNode child = node.getChildNode(i);
464 gen_iter gen = mGenotypes_.find(child.getName());
465 if (gen == mGenotypes_.end()) {
466 throw std::string("Error: unknown Genotype : ") + child.getName();
467 }
468
469 uint genotypeId = (uint)genotype_.size();
470 gen->second->setGenotypeId(genotypeId);
471 gen->second->registerParameters(state_);
472 setGenotype(gen->second);
473
474 if (!registry_->readEntries(child, child.getName(), genotypeId))
475 return false;
476 }
477
478 return true;
479}
480
481
488bool State::initializeComponents(int argc, char **argv)
489{
490 try {
491 // initialize evolutionary context
492 context_->initialize();
493
494 if(!bBatchStart_)
495 logger_->initialize(state_);
496 randomizer_->initialize(state_);
497
498 // initialize single instance of active genotypes
499 // (active genotypes - the ones that the individuals are made of, which is defined in the configuration file)
500 // State keeps a single uninitialized object of all active Genotypes
501 ECF_LOG(this, 4, "Initializing active genotypes...");
502 for(uint i = 0; i < genotype_.size(); i++) {
503 GenotypeP copy = (GenotypeP) genotype_[i]->copy();
504 bInitialized_ &= copy->initialize(state_);
505 }
506 if(!bInitialized_) {
507 throw "Error: Genotype initialization failed!";
508 }
509
510 // MPI communicator
511 bInitialized_ &= comm_->initialize(state_, argc, argv);
512
513 // damo algoritmu pointer na operator evaluacije i pointere na repozitorij krizanja i mutacije
514 ECF_LOG(this, 4, "Initializing population and algorithm...");
515 algorithm_->evalOp_ = this->evalOp_;
516 algorithm_->crossover_ = crossover_;
517 algorithm_->mutation_ = mutation_;
518 algorithm_->state_ = state_;
519 algorithm_->initialize(state_);
520
521 population_->initialize(state_);
522 algorithm_->initializeParallel(state_); // provjera impl. paralelizacije (nakon population_->initialize zbog podjele procesa po demovima)
523
524 ECF_LOG(this, 4, "Initializing genetic operators...");
525 mutation_->initialize(state_);
526 crossover_->initialize(state_);
527 migration_->initialize(state_);
528
529 // initialize termination ops
530 ECF_LOG(this, 4, "Initializing termination operators...");
531 activeTerminationOps_.clear();
532 for(uint i = 0; i < allTerminationOps_.size(); i++)
533 if(allTerminationOps_[i]->initialize(state_))
534 activeTerminationOps_.push_back(allTerminationOps_[i]);
535 // if no term operators are configured, activate default (the first)
536 if(activeTerminationOps_.empty())
537 activeTerminationOps_.push_back(allTerminationOps_[0]);
538
539 // initialize user ops
540 ECF_LOG(this, 4, "Initializing user defined operators...");
541 activeUserOps_.clear();
542 for(uint i = 0; i < allUserOps_.size(); i++)
543 if(allUserOps_[i]->initialize(state_))
544 activeUserOps_.push_back(allUserOps_[i]);
545
546 // evaluation op. initializes last
547 ECF_LOG(this, 4, "Initializing evaluation operator...");
548 if(!evalOp_->initialize(state_))
549 throw "Error: Evaluation operator initialization failed!";
550
551 // generate one individual
552 ECF_LOG(this, 4, "Generating test individual...");
553 individual_ = (IndividualP) (new Individual(state_));
554
555 } // try
556
557 catch(std::string& msg) {
558 std::cout << msg << std::endl;
559 bInitialized_ = false;
560 }
561 catch(const char* msg) {
562 std::cout << msg << std::endl;
563 bInitialized_ = false;
564 }
565 catch(...) {
566 std::cout << "Unknown error in initialization!" << std::endl;
567 bInitialized_ = false;
568 }
569
570 return bInitialized_;
571}
572
573
576{
577 try {
578 if(!fitness_) {
579 context_->evaluatedIndividual = individual_;
580 fitness_ = evalOp_->evaluate(individual_);
581 }
582
583 }
584 catch(...) {
585 std::cout << "Error in evaluation operator!" << std::endl;
586 }
587
588 return fitness_;
589}
590
591
598bool State::runBatch()
599{
600 bBatchStart_ = false;
601 bBatchMode_ = true;
602
603 bool bUseLog = registry_->isModified("log.filename");
604
605 // are we restoring from a milestone file
606 if(!bLoadMilestone_)
607 batchRemaining_ = batchRepeats_;
608 uint numerals = 1 + (uint) (log((double) batchRepeats_) / log((double) 10.));
609
610 // get logfile name and extension
611 std::string logFileName = *(std::string*) registry_->getEntry("log.filename").get();
612 std::string logFileExt = "";
613 if(bLoadMilestone_)
614 logFileName = batchLogFile_;
615 else
616 batchLogFile_ = logFileName;
617
618 if(logFileName.find_last_of(".") != std::string::npos) {
619 logFileExt = logFileName.substr(logFileName.find_last_of("."));
620 logFileName = logFileName.substr(0, logFileName.find_last_of("."));
621 }
622
623 // get milestone name and extension
624 std::string milestoneName = *(std::string*) registry_->getEntry("milestone.filename").get();
625 std::string milestoneExt = "";
626 if(milestoneName.find_last_of(".") != std::string::npos) {
627 milestoneExt = milestoneName.substr(milestoneName.find_last_of("."));
628 milestoneName = milestoneName.substr(0, milestoneName.find_last_of("."));
629 }
630
631 // (re)open stats file, if defined
632 std::ofstream statsFile;
633 if(registry_->isModified("batch.statsfile")) {
634 if(bLoadMilestone_)
635 statsFile.open(batchStatsFile_.c_str(), std::ios_base::app);
636 else {
637 statsFile.open(batchStatsFile_.c_str());
638 statsFile << "runId\tfit_min\tfit_max\tfit_avg\tfit_std\t#evals\ttime\tgen\n";
639 }
640 if(!statsFile) {
641 ECF_LOG_ERROR(this, "Error: can't open batch statsfile (" + batchStatsFile_ + ")!");
642 return false;
643 }
644 statsFile.close();
645 bBatchWriteStats_ = true;
646 }
647
648 uint runId = batchRepeats_ - batchRemaining_ + 1;
649
650 // perform algorithm runs
651 for(; runId <= batchRepeats_; runId++) {
652 // set current logfile
653 if(bUseLog) {
654 std::stringstream ss;
655 ss << std::setw(numerals) << std::setfill('0') << runId;
656 std::string currentLogName = logFileName + "_" + ss.str() + logFileExt;
657 registry_->modifyEntry("log.filename", (voidP) new std::string(currentLogName));
658 }
659
660 // set current milestone
661 if(!bBatchSingleMilestone_) {
662 std::stringstream ss;
663 ss << std::setw(numerals) << std::setfill('0') << runId;
664 milestoneFilename_ = milestoneName + "_" + ss.str() + milestoneExt;
665 }
666
667 // run
668 bInitialized_ = true;
669 if(!initializeComponents(argc_, argv_))
670 break;
671 ECF_LOG(this, 1, "Running in batch mode: run " + uint2str(runId) + "/" + uint2str(batchRepeats_));
672 run();
673 batchRemaining_--;
674
675 // write stats (PECF: only master process)
676 if(comm_->getCommGlobalRank() == 0) {
677 if(bBatchWriteStats_) {
678 statsFile.open(batchStatsFile_.c_str(), std::ios_base::app);
679 std::vector<double> stats = population_->getStats()->getStats();
680 statsFile << runId << '\t';
681 statsFile << stats[ECF::FIT_LOW] << '\t' << stats[ECF::FIT_HIGH] << '\t' << stats[ECF::FIT_AVG] << '\t' << stats[ECF::FIT_DEV] << '\t';
682 statsFile << stats[ECF::STAT_EVAL] << '\t' << stats[ECF::STAT_TIME] << '\t' << getGenerationNo() << '\n';
683 statsFile.close();
684 }
685 }
686 }
687
688 // ugly workabout for MPI_Finalize, which may only be called once
689 // (shouldn't be called at the end of a single run)
690 bBatchMode_ = false;
691 comm_->finalize();
692
693 if(bInitialized_)
694 std::cout << "Batch mode end (" << batchRepeats_ << " runs concluded)." << std::endl;
695
696 if(statsFile)
697 statsFile.close();
698 return true;
699}
700
701
702
713bool State::initialize(int argc, char **argv)
714{
715 this->state_ = this->getState(); // obtain a sptr to this
716
717 genotype_.clear();
718 mutation_->operators.clear();
719 crossover_->operators.clear();
720
721 bInitialized_ = false;
722 argc_ = argc;
723 argv_ = argv;
724 std::string config_file;
725
726 try {
727
728 std::cout << "-- ECF, version " << ECF_VERSION << " --" << std::endl;
729
730 if(!bEvaluatorSet_) {
731 throw "Error: no EvaluateOp defined!";
732 }
733
734 if (argc > 1) {
735 // parse arguments: return success if command line option is recognized
736 if(parseCommandLine(argc, argv))
737 return false;
738
739 // otherwise, assume configuration file name as argument
740 config_file = argv[1];
741 }
742
743 registerParameters();
744
745 if (config_file != "") {
746 parseConfig(config_file);
747 }
748 else {
749 std::cout << "Warning: no configuration file given." << std::endl;
750 std::cout << "Example usage: <ECF_executable> <parameter_file>" << std::endl;
751 }
752
753 // use the default algorithm
754 if (!bAlgorithmSet_)
755 algorithm_ = mAlgorithms_.find("SteadyStateTournament")->second;
756
757 if(!bGenotypeSet_) {
758 throw "Error: no Genotype defined!";
759 }
760
761 readParameters();
762
763 // set init flag, then test with each component initialization
764 bInitialized_ = true;
765
766 initializeComponents(argc, argv);
767
768 // if multiple runs, milestone will get parsed in State::run()
769 if (bBatchStart_)
770 return true;
771
772 if(bLoadMilestone_)
773 loadMilestone();
774
775 ECF_LOG(this, 4, "Initialization complete.");
776
777 } // try
778
779 catch (const std::exception& e)
780 {
781 std::cout << "Initialization exception: " << e.what();
782 }
783 catch(const std::string& msg) {
784 std::cout << msg << std::endl;
785 }
786 catch(const char* msg) {
787 std::cout << msg << std::endl;
788 }
789 catch(...) {
790 std::cout << "Unknown error in initialization!" << std::endl;
791 }
792
793 return bInitialized_;
794}
795
796
797
803bool State::parseCommandLine(int argc, char** argv)
804{
805 // read all arguments
806 std::vector< std::string > arg;
807 for(int i = 0; i < argc; i++)
808 arg.push_back(argv[i]);
809
810 bCommandLine_ = true;
811
812 // GUI related arguments
813 if(arg[1] == "-gui") {
814 if(argc > 3 && arg[2] == "-pardump")
815 dumpParameters(arg[3], false);
816 }
817
818 // dump all parameters
819 else if(arg[1] == "-pardump") {
820 if(argc < 3) {
821 std::cout << "No output file given for parameter dump! (usage: <executable> -pardump <filename>)" << std::endl;
822 }
823 else {
824 std::cout << "Exporting complete parameter list to \'" << arg[2] << "\'...\n";
825 dumpParameters(arg[2]);
826 }
827 }
828
829 // display cmd arguments
830 else if(arg[1].substr(0,2) == "-h" || arg[1].substr(0,3) == "--h") {
831 std::cout << "Current command line arguments:\n";
832 std::cout << "\t<parameter_file> run ECF with given parameter file\n";
833 std::cout << "\t-pardump <file> dump all parameters in a given file\n";
834 std::cout << "\t-h, -help display this help\n";
835 }
836
837 else
838 bCommandLine_ = false;
839
840 return bCommandLine_;
841}
842
843
844
849{ return algorithm_->isImplicitParallel(); }
850
851
856{ return algorithm_->isParallel(); }
857
858
863void State::write(XMLNode& xState)
864{
865 registry_->modifyEntry("milestone.generation_", (voidP) (new uint(getGenerationNo())));
866 registry_->modifyEntry("milestone.elapsedtime_", (voidP) (new time_t(elapsedTime_)));
867 registry_->modifyEntry("batch.remaining_", (voidP) (new uint(batchRemaining_)));
868 if(batchLogFile_ != "")
869 registry_->modifyEntry("batch.logfile_", (voidP) (new std::string(batchLogFile_)));
870 else
871 registry_->modifyEntry("batch.logfile_", (voidP) (new std::string("*")));
872}
873
874
879void State::saveMilestone()
880{
881 XMLNode xMainNode = XMLNode::createXMLTopNode("ECF");
882 xMainNode.addAttribute("milestone", ctime(&currentTime_));
883
884 XMLNode xMilestone;
885 this->write(xMilestone);
886 xMainNode.addChild(xMilestone);
887
888 XMLNode xNode = this->xConfig_.getChildNode(NODE_ALGORITHM);
889 xNode = xNode.deepCopy();
890 xMainNode.addChild(xNode);
891 xNode = this->xConfig_.getChildNode(NODE_GENOTYPE);
892 xNode = xNode.deepCopy();
893 xMainNode.addChild(xNode);
894
895 this->registry_->write(xNode);
896 xMainNode.addChild(xNode);
897
898 // save population
899 XMLNode xPopulation;
900 population_->write(xPopulation);
901 xMainNode.addChild(xPopulation);
902
903#ifdef _MPI
904 if(comm_->getCommGlobalRank() != 0)
905 return;
906#endif
907
908 xMainNode.writeToFile(milestoneFilename_.c_str());
909}
910
911
916void State::loadMilestone()
917{
918 ECF_LOG(this, 4, "Loading population and evolutionary context from milestone...");
919 XMLNode xPopulation = xConfig_.getChildNode("Population");
920 population_->read(xPopulation);
921
922 context_->generationNo_ = milestoneGeneration_;
923}
924
925
926
927//
928// setting components
929//
930
940uint State::setGenotype(GenotypeP genotype)
941{
942 genotype_.push_back((GenotypeP) genotype->copy());
943 uint index = (uint) genotype_.size() - 1;
944 genotype_[index]->setGenotypeId(index);
945 genotype->setGenotypeId(index);
946
947 genotype_[index]->registerParameters(state_);
948
949 // read genotype's operators and register their parameters
950 crossover_->operators.push_back(genotype_[index]->getCrossoverOp());
951 for(uint iOp = 0; iOp < crossover_->operators[index].size(); iOp++) {
952 crossover_->operators[index][iOp]->myGenotype_ = genotype_[index];
953 crossover_->operators[index][iOp]->registerParameters(state_);
954 }
955
956 mutation_->operators.push_back(genotype_[index]->getMutationOp());
957 for(uint iOp = 0; iOp < mutation_->operators[index].size(); iOp++) {
958 mutation_->operators[index][iOp]->myGenotype_ = genotype_[index];
959 mutation_->operators[index][iOp]->registerParameters(state_);
960 }
961
962 bGenotypeSet_ = true;
963 return index;
964}
965
967void State::setAlgorithm(AlgorithmP algorithm)
968{
969 algorithm_ = algorithm;
970 bAlgorithmSet_ = true;
971}
972
973
979void State::setEvalOp(EvaluateOpP eval)
980{
981 evalOp_ = eval;
982 bEvaluatorSet_ = true;
983}
984
985
992{
993 evalOp_ = (EvaluateOpP) eval;
994 bEvaluatorSet_ = true;
995}
996
997
998//
999// adding components
1000//
1001
1010bool State::addGenotype(GenotypeP gen)
1011{
1012 mGenotypes_[gen->getName()] = gen;
1013 return true;
1014}
1015
1016
1025bool State::addAlgorithm(AlgorithmP alg)
1026{
1027 mAlgorithms_[alg->getName()] = alg;
1028 return true;
1029}
1030
1038bool State::addOperator(OperatorP op)
1039{
1040 allUserOps_.push_back(op);
1041 return true;
1042}
1043
1044
1045
1046//
1047// run methods
1048//
1049
1050#ifndef _MPI
1058{
1059 // command line only (no evolution)
1060 if(bCommandLine_)
1061 return false;
1062
1063 if(!bInitialized_) {
1064 std::cout << "Error: Initialization failed!" << std::endl;
1065 return false;
1066 }
1067
1068 if(bBatchStart_) {
1069 ECF_LOG(this, 5, "Batch mode detected: running batch");
1070 runBatch();
1071 return true;
1072 }
1073
1074 try {
1075 startTime_ = time(NULL);
1076 std::string stime = ctime(&startTime_);
1077 ECF_LOG(this, 3, "Start time: " + stime);
1078 // adjust with previous runtime (from milestone)
1079 startTime_ -= milestoneElapsedTime_;
1080
1081 // evaluate initial population
1082 ECF_LOG(this, 2, "Evaluating initial population...");
1083 algorithm_->initializePopulation(state_);
1084
1085 currentTime_ = time(NULL);
1086 elapsedTime_ = currentTime_ - startTime_;
1087 ECF_LOG(this, 2, "Generation: " + uint2str(context_->generationNo_));
1088 ECF_LOG(this, 2, "Elapsed time: " + uint2str((uint)elapsedTime_));
1089 population_->updateDemeStats();
1090
1091 // call user-defined operators
1092 ECF_LOG(this, 5, "Calling user defined operators...");
1093 for (uint i = 0; i < activeUserOps_.size(); i++)
1094 activeUserOps_[i]->operate(state_);
1095
1096 // termination ops
1097 ECF_LOG(this, 5, "Checking termination conditions...");
1098 for (uint i = 0; i < activeTerminationOps_.size(); i++)
1099 activeTerminationOps_[i]->operate(state_);
1100
1101 // run the algorithm
1102 while (context_->bTerminate_ == false) {
1103 context_->generationNo_++;
1104 ECF_LOG(this, 5, "Calling the active algorithm");
1105 algorithm_->advanceGeneration(state_);
1106
1107 currentTime_ = time(NULL);
1108 elapsedTime_ = currentTime_ - startTime_;
1109 ECF_LOG(this, 2, "Generation: " + uint2str(context_->generationNo_));
1110 ECF_LOG(this, 2, "Elapsed time: " + uint2str((uint)elapsedTime_));
1111
1112 population_->updateDemeStats();
1113
1114 IndividualP bestInd = this->getPopulation()->getHof()->getBest().at(0);
1115 ECF_LOG(this, 4, "Current best:\n" + bestInd->toString());
1116
1117 // call user-defined operators
1118 ECF_LOG(this, 5, "Calling user defined operators...");
1119 for (uint i = 0; i < activeUserOps_.size(); i++)
1120 activeUserOps_[i]->operate(state_);
1121
1122 // termination ops
1123 ECF_LOG(this, 5, "Checking termination conditions...");
1124 for (uint i = 0; i < activeTerminationOps_.size(); i++)
1125 activeTerminationOps_[i]->operate(state_);
1126
1127 if (context_->bTerminate_)
1128 logger_->saveTo(true);
1129 else
1130 logger_->saveTo();
1131
1132 if (bSaveMilestone_ &&
1133 milestoneInterval_ > 0 && context_->generationNo_ % milestoneInterval_ == 0)
1134 saveMilestone();
1135
1136 migration_->operate(state_);
1137 }
1138
1139 // output HallOfFame
1140 XMLNode xHoF;
1141 population_->getHof()->write(xHoF);
1142 char* out = xHoF.createXMLString(true);
1143 ECF_LOG(this, 1, "\nBest of run: \n" + std::string(out));
1144 freeXMLString(out);
1145
1146 logger_->saveTo(true);
1147 if (bSaveMilestone_)
1148 saveMilestone();
1149
1150 logger_->closeLog();
1151 }
1152 catch (const std::exception& e)
1153 {
1154 std::cout << "Runtime exception: " << e.what();
1155 }
1156 catch (...)
1157 {
1158 cout << "Unkown error in algorithm run!";
1159 }
1160
1161 return true;
1162}
1163
1164
1165#else // _MPI
1172bool State::run()
1173{
1174 // command line only (no evolution)
1175 if(bCommandLine_)
1176 return false;
1177
1178 if(bBatchStart_) {
1179 runBatch();
1180 return true;
1181 }
1182
1183 // TODO: perform AND_reduce with bInitialized on all processes
1184 if(!bInitialized_) {
1185 std::cout << "Error: Initialization failed!" << std::endl;
1186 logger_->saveTo();
1187 if(comm_->isInitialized())
1188 comm_->finalize();
1189 return false;
1190 }
1191
1192 startTime_ = time(NULL);
1193 std::string stime = ctime(&startTime_);
1194 ECF_LOG(this, 3, "Start time: " + stime);
1195 // adjust with previous runtime (from milestone)
1196 startTime_ -= milestoneElapsedTime_;
1197
1198 // in PECF, every process works with deme '0'
1199 // 'deme masters' - processes with index 0 in local communicator
1200 // only deme masters know of whole population
1201 if(comm_->getCommRank() == 0) {
1202 ECF_LOG(this, 2, "Evaluating initial population...");
1203 }
1204
1205 // every process participates in the initial population evaluation
1206 algorithm_->initializePopulation(state_);
1207 comm_->synchronize();
1208
1209 if(comm_->getCommRank() == 0) {
1210 // dodatna inicijalizacija za implicitni paralelizam - mozda promijeniti...
1211 if(isImplicitParallel())
1212 algorithm_->initializeImplicit(state_);
1213 }
1214
1215 // run the algorithm
1216 while(context_->bTerminate_ == false) {
1217
1218 currentTime_ = time(NULL);
1219 elapsedTime_ = currentTime_ - startTime_;
1220 if(comm_->getCommGlobalRank() == 0) {
1221 ECF_LOG(this, 2, "Generation: " + uint2str(context_->generationNo_));
1222 ECF_LOG(this, 2, "Elapsed time: " + uint2str((uint) elapsedTime_));
1223 }
1224
1225 // deme masters initiate population statistics and HoF update
1226 if(comm_->getCommRank() == 0) {
1227 population_->updateDemeStats();
1228
1229 if(bSaveMilestone_ && milestoneInterval_ > 0 && context_->generationNo_ % milestoneInterval_ == 0)
1230 saveMilestone();
1231 }
1232
1233 // global process 0 checks termination condition and signals deme masters
1234 if(comm_->getCommGlobalRank() == 0) {
1235 ECF_LOG(this, 4, "Checking termination conditions...");
1236 for(uint i = 0; i < activeTerminationOps_.size(); i++)
1237 activeTerminationOps_[i]->operate(state_);
1238
1239 for(uint i = 1; i < population_->getNoDemes(); i++)
1240 comm_->sendTerminateMessage(comm_->getDemeMaster(i), context_->bTerminate_);
1241 }
1242 // deme masters receive info
1243 else if(comm_->getCommRank() == 0)
1244 context_->bTerminate_ = comm_->recvTerminateMessage(0);
1245
1246 // deme masters signal workers of evolution continuation
1247 algorithm_->bcastTermination(state_);
1248
1249 // deme masters call migration operator
1250 if(comm_->getCommRank() == 0) {
1251 migration_->operate(state_);
1252 }
1253
1254 // call user-defined operators
1255 ECF_LOG(this, 4, "Calling user defined operators...");
1256 for(uint i = 0; i < activeUserOps_.size(); i++)
1257 activeUserOps_[i]->operate(state_);
1258
1259 if(context_->bTerminate_ == true) {
1260 logger_->saveTo(true);
1261 break;
1262 }
1263
1264 logger_->saveTo();
1265
1266 context_->generationNo_++;
1267 ECF_LOG(this, 5, "Calling the active algorithm");
1268 algorithm_->advanceGeneration(state_);
1269 }
1270
1271 logger_->setLogFrequency(1);
1272 if(comm_->getCommGlobalRank() == 0) {
1273 // output HallOfFame
1274 XMLNode xHoF;
1275 population_->getHof()->write(xHoF);
1276 std::string out = xHoF.createXMLString(true);
1277 ECF_LOG(this, 1, "\nBest of run: \n" + out);
1278
1279 logger_->saveTo(true);
1280 }
1281
1282 if(comm_->getCommRank() == 0 && bSaveMilestone_)
1283 saveMilestone();
1284
1285 logger_->saveTo(true);
1286
1287 // communicator
1288 comm_->finalize();
1289
1290 return true;
1291}
1292#endif // _MPI
Asynchronous elimination global parallel algorithm (outdated version).
Asynchronous elimination global parallel algorithm.
Definition AlgAEliGPEA.h:12
Generational algorithm with roulette wheel selection operator and unique operators and chromosome rep...
Definition AlgGEP.h:35
Synchronous generational global parallel algorithm.
Definition AlgSGenGPEA.h:11
Artificial Bee Colony algorithm (see e.g. http://www.scholarpedia.org/article/Artificial_bee_colony_a...
Binary class - implements genotype as a vector of binary coded real values with variable interval and...
Definition Binary.h:38
BitString class - implements genotype as a series of bits.
Definition BitString.h:24
Clonal Selection Algorithm (see e.g. http://en.wikipedia.org/wiki/Clonal_Selection_Algorithm).
Definition AlgClonalg.h:25
Communicator class for interprocess communication.
Crossover class - handles crossover of individuals (as opposed to CrossoverOp class that crosses geno...
Definition Crossover.h:57
Cuckoo search (CS) optimization algorithm (see http://en.wikipedia.org/wiki/Cuckoo_search).
Differential evolution (DE) optimization algorithm (see e.g. http://en.wikipedia.org/wiki/Differentia...
Elimination (generation gap) algorithm with roulette wheel elimination selection operator.
Evaluation base class.
Definition EvaluateOp.h:17
Evolutionary context class.
Definition Context.h:12
(mu/rho +/, lambda) - Evolution Strategy (ES) algorithm.
FloatingPoint class - implements genotype as a vector of floating point values.
GEPChromosome class - implements genotype as a Gene Expression Programming chromosome.
new algorithm, in development
Genetic annealing algorithm (see e.g. http://citeseerx.ist.psu.edu/viewdoc/summary?...
IntGenotype class - implements genotype as a vector of int values.
Definition IntGenotype.h:28
Logging class - handles screen output and file logging.
Definition Logger.h:33
Migration class - handles individual migration between demes.
Definition Migration.h:11
Mutation class - handles mutation of individuals (as opposed to MutationOp class that mutates genotyp...
Definition Mutation.h:55
Optimization Immune Algorithm (opt-IA, see e.g. http://www.artificial-immune-systems....
Definition AlgOptIA.h:23
Particle swarm optimization algorithm (see e.g. http://en.wikipedia.org/wiki/Particle_swarm_optimizat...
Permutation class - implements genotype as a vector of indices 0..(n-1) (permutation of indices).
Definition Permutation.h:37
Population class - inherits a vector of Deme objects.
Definition Population.h:15
Random search algorithm.
Repository for all the system parameters.
Definition Registry.h:43
Generational algorithm with roulette wheel selection operator.
A simple randomizer that uses in-built random number generator.
PopulationP getPopulation()
get Population
Definition State.h:187
void setAlgorithm(AlgorithmP)
Set the desired algorithm (overrides the current choice).
Definition State.cpp:967
FitnessP getFitnessObject()
get one initial Fitness object (create on demand)
Definition State.cpp:575
bool addGenotype(GenotypeP gen)
Add user-defined or user customized genotype. (The genotype can then be specified and used in config ...
Definition State.cpp:1010
void setEvalOp(EvaluateOpP)
Set user defined evaluation operator.
Definition State.cpp:979
bool addAlgorithm(AlgorithmP alg)
Add user-defined or user customized algorithm. (It can then be specified and used in config file....
Definition State.cpp:1025
bool run()
Driver of the evolution process - serial version.
Definition State.cpp:1057
bool isImplicitParallel()
Is the algorithm executed implicitly parallel.
Definition State.cpp:848
bool initialize(int, char **)
Initialize the whole system.
Definition State.cpp:713
uint setGenotype(GenotypeP)
Set a genotype to be used in individuals.
Definition State.cpp:940
bool isAlgorithmParallel()
Is current algorithm parallel.
Definition State.cpp:855
State()
Construct the one and only State object.
Definition State.cpp:12
bool addOperator(OperatorP op)
Add user-defined operator. (Its parameters can now be specified and used in config file....
Definition State.cpp:1038
uint getGenerationNo()
get current generation number
Definition State.h:147
void setRandomizer(RandomizerP randomizer)
set Randomizer to be used
Definition State.h:123
Steady state algorithm with tournament elimination operator.
Termination operator: terminates on a given fitness value.
Termination operator: terminates on a given number of fitness evaluations.
Termination operator: terminates on a given number of generations.
Definition TermMaxGenOp.h:9
Termination operator: terminates on a given elapsed time.
Termination operator: terminates when no improvement occurs in best individual for a given number of ...
Analytical Programing genotype class - implements genotype as a vector of floating point values that ...
Definition APGenotype.h:50
Tree class - implements genotype as a tree.
Definition Tree_c.h:29
Definition AlgXCS.h:30