ECF 1.5
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
65#ifdef _MPI
66 // paralel algorithms
67 alg = static_cast<AlgorithmP> (new AlgSGenGpea);
68 this->mAlgorithms_[alg->getName()] = alg;
69 alg = static_cast<AlgorithmP> (new AlgAEliGpea);
70 this->mAlgorithms_[alg->getName()] = alg;
71 alg = static_cast<AlgorithmP> (new AlgAEliGpea2);
72 this->mAlgorithms_[alg->getName()] = alg;
73#endif
74
75 // genotypes
76 GenotypeP gen = static_cast<GenotypeP> (new BitString::BitString);
77 this->mGenotypes_[gen->getName()] = gen;
78 gen = static_cast<GenotypeP> (new Binary::Binary);
79 this->mGenotypes_[gen->getName()] = gen;
80 gen = static_cast<GenotypeP> (new Tree::Tree);
81 this->mGenotypes_[gen->getName()] = gen;
82 gen = static_cast<GenotypeP> (new Permutation::Permutation);
83 this->mGenotypes_[gen->getName()] = gen;
84 gen = static_cast<GenotypeP> (new FloatingPoint::FloatingPoint);
85 this->mGenotypes_[gen->getName()] = gen;
86 gen = static_cast<GenotypeP> (new Tree::APGenotype);
87 this->mGenotypes_[gen->getName()] = gen;
88// gen = static_cast<GenotypeP> (new cart::Cartesian);
89// this->mGenotypes_[gen->getName()] = gen;
90
91 // termination operators
92 OperatorP op = static_cast<OperatorP> (new TermStagnationOp);
93 this->allTerminationOps_.push_back(op);
94 op = static_cast<OperatorP> (new TermMaxGenOp);
95 this->allTerminationOps_.push_back(op);
96 op = static_cast<OperatorP> (new TermFitnessValOp);
97 this->allTerminationOps_.push_back(op);
98 op = static_cast<OperatorP> (new TermMaxTimeOp);
99 this->allTerminationOps_.push_back(op);
100 op = static_cast<OperatorP> (new TermMaxEvalOp);
101 this->allTerminationOps_.push_back(op);
102
103 setRandomizer(static_cast<RandomizerP> (new SimpleRandomizer));
104 this->registry_ = static_cast<RegistryP> (new Registry);
105 this->logger_ = static_cast<LoggerP> (new Logger);
106 this->comm_ = static_cast<CommunicatorP> (new Comm::Communicator);
107 this->migration_ = static_cast<MigrationP> (new Migration);
108}
109
110
115void State::registerParameters()
116{
117 // State parameters
118 registry_->registerEntry("milestone.interval", (voidP) (new uint(0)), ECF::UINT,
119 "milestone saving interval in generations; 0: save only at the end (default: 0)");
120 registry_->registerEntry("milestone.filename", (voidP) (new std::string("milestone.txt")), ECF::STRING,
121 "milestone file (if stated) stores all the population (default: none)");
122 registry_->registerEntry("batch.repeats", (voidP) (new uint(0)), ECF::UINT,
123 "number of independent runs to perform (default: 1)");
124 registry_->registerEntry("batch.singlemilestone", (voidP) (new uint(0)), ECF::UINT,
125 "use only one milestone file for all the batch runs (1) or one for each run (0) (default: 0)");
126 registry_->registerEntry("batch.statsfile", (voidP) (new std::string("")), ECF::STRING,
127 "output batch end of run stats in a single file (default: none)");
128
129 // milestone data
130 registry_->registerEntry("milestone.generation_", (voidP) (new uint(0)), ECF::UINT);
131 registry_->registerEntry("milestone.elapsedtime_", (voidP) (new uint(0)), ECF::UINT);
132 registry_->registerEntry("batch.remaining_", (voidP) (new uint(0)), ECF::UINT);
133 registry_->registerEntry("batch.logfile_", (voidP) (new std::string("")), ECF::STRING);
134
135 ECF_LOG(this, 4, "Registering parameters: algorithms, operators");
136
137 // call registerParameters() methods:
138 alg_iter itAlg;
139 for(itAlg = mAlgorithms_.begin(); itAlg != mAlgorithms_.end(); ++itAlg)
140 itAlg->second->registerParameters(state_);
141
142 // register common implicit parallel parameters (defined in Algorithm base class)
143 mAlgorithms_.begin()->second->registerParallelParameters(state_);
144
145 // register termination operators' parameters
146 for(uint i = 0; i < allTerminationOps_.size(); i++)
147 allTerminationOps_[i]->registerParameters(state_);
148
149 // user-defined operators
150 for(uint i = 0; i < allUserOps_.size(); i++)
151 allUserOps_[i]->registerParameters(state_);
152
153 mutation_->registerParameters(state_);
154 crossover_->registerParameters(state_);
155 randomizer_->registerParameters(state_);
156 population_->registerParameters(state_);
157 logger_->registerParameters(state_);
158 migration_->registerParameters(state_);
159 evalOp_->registerParameters(state_);
160}
161
162
167void State::readParameters()
168{
169 ECF_LOG(this, 4, "Rading parameters from the Registry");
170
171 // milestone saving data
172 if(registry_->isModified("milestone.filename"))
173 bSaveMilestone_ = true;
174 else
175 bSaveMilestone_ = false;
176
177 voidP sptr = registry_->getEntry("milestone.interval");
178 milestoneInterval_ = *((uint*) sptr.get());
179
180 sptr = registry_->getEntry("milestone.filename");
181 milestoneFilename_ = *((std::string*) sptr.get());
182
183 // milestone loading data
184 if(registry_->isModified("milestone.generation_"))
185 bLoadMilestone_ = true;
186 else
187 bLoadMilestone_ = false;
188
189 sptr = registry_->getEntry("milestone.generation_");
190 milestoneGeneration_ = *((uint*) sptr.get());
191
192 sptr = registry_->getEntry("milestone.elapsedtime_");
193 milestoneElapsedTime_ = *((uint*) sptr.get());
194
195 // batch running data
196 sptr = registry_->getEntry("batch.repeats");
197 batchRepeats_ = *((uint*) sptr.get());
198
199 sptr = registry_->getEntry("batch.remaining_");
200 batchRemaining_ = *((uint*) sptr.get());
201
202 sptr = registry_->getEntry("batch.statsfile");
203 batchStatsFile_ = *((std::string*) sptr.get());
204
205 sptr = registry_->getEntry("batch.logfile_");
206 batchLogFile_ = *((std::string*) sptr.get());
207
208 sptr = registry_->getEntry("batch.singlemilestone");
209 bBatchSingleMilestone_ = (*((uint*) sptr.get()) % 2) ? true:false;
210
211 if(registry_->isModified("batch.repeats") && batchRepeats_ > 1)
212 bBatchStart_ = true;
213 else
214 bBatchStart_ = false;
215}
216
217
221void State::dumpParameters(std::string fileName, bool addClear)
222{
223 XMLNode xMainNode = XMLNode::createXMLTopNode("ECF");
224 xMainNode.addAttribute("version", ECF_VERSION.c_str());
225 xMainNode.addClear("ECF parameter dump - list of all parameters", "<!-- ", " -->");
226
227 this->state_ = this->getState(); // obtain a sptr to this
228 // register all parameters (except genotypes which are normally parsed from config)
229 this->registerParameters();
230
231 // register parameters for all the genotypes
232 for(gen_iter itGen = mGenotypes_.begin(); itGen != mGenotypes_.end(); ++itGen) {
233 itGen->second->setGenotypeId(0);
234 itGen->second->registerParameters(state_);
235
236 // register all crx operators
237 std::vector<CrossoverOpP> crx = itGen->second->getCrossoverOp();
238 for(uint iOp = 0; iOp < crx.size(); iOp++) {
239 crx[iOp]->myGenotype_ = itGen->second;
240 crx[iOp]->registerParameters(state_);
241 }
242
243 // register all mutation operators
244 std::vector<MutationOpP> mut = itGen->second->getMutationOp();
245 for(uint iOp = 0; iOp < mut.size(); iOp++) {
246 mut[iOp]->myGenotype_ = itGen->second;
247 mut[iOp]->registerParameters(state_);
248 }
249 }
250
251 // get all parameters
252 XMLNode xRegistry;
253 this->registry_->dumpEntries(xRegistry);
254
255 // create Algorithm node
256 XMLNode xAlgorithms = XMLNode::createXMLTopNode(NODE_ALGORITHM);
257 xMainNode.addChild(xAlgorithms);
258
259 // extract all algorithms
260 alg_iter itAlg;
261 for(itAlg = mAlgorithms_.begin(); itAlg != mAlgorithms_.end(); ++itAlg) {
262
263 // get algorithm name, create subnode
264 std::string algorithmName = itAlg->first;
265 XMLNode xAlgorithm = XMLNode::createXMLTopNode(algorithmName.c_str());
266 xAlgorithms.addChild(xAlgorithm);
267
268 // iterate over all entries
269 for(int i = 0; i < xRegistry.nChildNode(); i++) {
270 XMLNode child = xRegistry.getChildNode(i);
271 std::string key = child.getAttributeValue();
272 // compare to selected Algorithm
273 if(key.compare(0, algorithmName.size(), algorithmName) == 0) {
274 // copy entry, delete the original
275 XMLNode xEntry = child.deepCopy();
276 child.deleteNodeContent();
277 i--;
278
279 // remove algorithm name
280 std::string key = xEntry.getAttribute("key");
281 key.erase(0, algorithmName.length() + 1);
282 xEntry.updateAttribute(key.c_str(), NULL, "key");
283 xAlgorithm.addChild(xEntry);
284
285 // optional: copy description attribute to XML comment
286 std::string desc = xEntry.getAttribute("desc");
287 if(addClear && desc != "") {
288 xAlgorithm.addClear(desc.c_str(), "<!-- ", " -->");
289 }
290 if(addClear)
291 xEntry.deleteAttribute("desc");
292 }
293 }
294 }
295
296 // create Genotype node
297 XMLNode xGenotypes = XMLNode::createXMLTopNode(NODE_GENOTYPE);
298 xMainNode.addChild(xGenotypes);
299
300 // extract all genotypes
301 for(gen_iter itGen = mGenotypes_.begin(); itGen != mGenotypes_.end(); ++itGen) {
302
303 // get genotype name, create subnode
304 std::string genotypeName = itGen->first;
305 XMLNode xGenotype = XMLNode::createXMLTopNode(genotypeName.c_str());
306 xGenotypes.addChild(xGenotype);
307
308 // iterate over all entries
309 for(int i = 0; i < xRegistry.nChildNode(); i++) {
310 XMLNode child = xRegistry.getChildNode(i);
311 std::string key = child.getAttributeValue();
312 // compare to selected Algorithm
313 if(key.compare(0, genotypeName.size(), genotypeName) == 0) {
314 // copy entry, delete the original
315 XMLNode xEntry = child.deepCopy();
316 child.deleteNodeContent();
317 i--;
318
319 // remove algorithm name
320 std::string key = xEntry.getAttribute("key");
321 key.erase(0, genotypeName.length() + 1);
322 xEntry.updateAttribute(key.c_str(), NULL, "key");
323 xGenotype.addChild(xEntry);
324
325 // optional: copy description attribute to XML comment
326 std::string desc = xEntry.getAttribute("desc");
327 if(addClear && desc != "") {
328 xGenotype.addClear(desc.c_str(), "<!-- ", " -->");
329 }
330 if(addClear)
331 xEntry.deleteAttribute("desc");
332 }
333 }
334 }
335
336 // optional: copy description for all registry entries
337 if(addClear) {
338 XMLNode xRegClear = XMLNode::createXMLTopNode(NODE_REGISTRY);
339 for(int i = 0; i < xRegistry.nChildNode(); i++) {
340 XMLNode xEntry = xRegistry.getChildNode(i);
341 XMLNode xE2 = xEntry.deepCopy();
342 std::string desc = xEntry.getAttribute("desc");
343 xE2.deleteAttribute("desc");
344 xRegClear.addChild(xE2);
345 if(desc != "")
346 xRegClear.addClear(desc.c_str(), "<!-- ", " -->");
347 }
348 xMainNode.addChild(xRegClear);
349 }
350 else
351 // add remaining Registry entries
352 xMainNode.addChild(xRegistry);
353
354 // user request
355 if(addClear)
356 xMainNode.writeToFile(fileName.c_str());
357 // GUI request
358 else {
359 std::string output(xMainNode.createXMLString());
360 std::cout << output;
361 }
362}
363
364
365
371bool State::parseConfig(std::string filename)
372{
373 std::ifstream fin(filename.c_str());
374 if (!fin) {
375 throw std::string("Error opening file " + filename);
376 }
377 std::cout << "Parsing configuration file: " << filename << std::endl;
378
379 std::string xmlFile, temp;
380 while (!fin.eof()) {
381 getline(fin, temp);
382 xmlFile += "\n" + temp;
383 }
384
385 XMLResults results;
386 xConfig_ = XMLNode::parseString(xmlFile.c_str(), "ECF", &results);
387 if (results.error != eXMLErrorNone) {
388 std::cout << "Configuration file: " << XMLNode::getError(results.error);
389 std::cout << " (line " << results.nLine << ", col " << results.nColumn << ")" << std::endl;
390 throw("");
391 }
392
393 if (xConfig_.isEmpty())
394 return false;
395
396 int n = xConfig_.nChildNode();
397 for (int i = 0; i < n; ++i) {
398 XMLNode child = xConfig_.getChildNode(i);
399 std::string name = child.getName();
400 bool ok = true;
401
402 if (name == NODE_REGISTRY)
403 ok &= registry_->readEntries(child);
404 else if (name == NODE_ALGORITHM)
405 ok &= parseAlgorithmNode(child);
406 else if (name == NODE_GENOTYPE)
407 ok &= parseGenotypeNode(child);
408 else if (name == NODE_POPULATION)
409 continue;
410 else
411 std::cout << "Unknown node: " << name << std::endl;
412
413 if (!ok)
414 throw "";
415 }
416
417 return true;
418}
419
420
426bool State::parseAlgorithmNode(XMLNode node)
427{
428 int n = node.nChildNode();
429 if (n > 1)
430 std::cout << "Warning: multiple Algorithm nodes found! (using the first one)" << std::endl;
431
432 XMLNode child = node.getChildNode(0);
433 alg_iter alg = mAlgorithms_.find(child.getName());
434 if (alg == mAlgorithms_.end()) {
435 throw std::string("Error: unknown Algorithm : ") + child.getName();
436 }
437
438 algorithm_ = alg->second;
439 bAlgorithmSet_ = true;
440
441 if (! registry_->readEntries(child, child.getName()))
442 return false;
443
444 return true;
445}
446
447
453bool State::parseGenotypeNode(XMLNode node)
454{
455 int n = node.nChildNode();
456 for (int i = 0; i < n; ++i) {
457 XMLNode child = node.getChildNode(i);
458 gen_iter gen = mGenotypes_.find(child.getName());
459 if (gen == mGenotypes_.end()) {
460 throw std::string("Error: unknown Genotype : ") + child.getName();
461 }
462
463 uint genotypeId = (uint)genotype_.size();
464 gen->second->setGenotypeId(genotypeId);
465 gen->second->registerParameters(state_);
466 setGenotype(gen->second);
467
468 if (!registry_->readEntries(child, child.getName(), genotypeId))
469 return false;
470 }
471
472 return true;
473}
474
475
482bool State::initializeComponents(int argc, char **argv)
483{
484 try {
485 // initialize evolutionary context
486 context_->initialize();
487
488 if(!bBatchStart_)
489 logger_->initialize(state_);
490 randomizer_->initialize(state_);
491
492 // initialize single instance of active genotypes
493 // (active genotypes - the ones that the individuals are made of, which is defined in the configuration file)
494 // State keeps a single uninitialized object of all active Genotypes
495 ECF_LOG(this, 4, "Initializing active genotypes...");
496 for(uint i = 0; i < genotype_.size(); i++) {
497 GenotypeP copy = (GenotypeP) genotype_[i]->copy();
498 bInitialized_ &= copy->initialize(state_);
499 }
500 if(!bInitialized_) {
501 throw "Error: Genotype initialization failed!";
502 }
503
504 // MPI communicator
505 bInitialized_ &= comm_->initialize(state_, argc, argv);
506
507 // damo algoritmu pointer na operator evaluacije i pointere na repozitorij krizanja i mutacije
508 ECF_LOG(this, 4, "Initializing population and algorithm...");
509 algorithm_->evalOp_ = this->evalOp_;
510 algorithm_->crossover_ = crossover_;
511 algorithm_->mutation_ = mutation_;
512 algorithm_->state_ = state_;
513 algorithm_->initialize(state_);
514
515 population_->initialize(state_);
516 algorithm_->initializeParallel(state_); // provjera impl. paralelizacije (nakon population_->initialize zbog podjele procesa po demovima)
517
518 ECF_LOG(this, 4, "Initializing genetic operators...");
519 mutation_->initialize(state_);
520 crossover_->initialize(state_);
521 migration_->initialize(state_);
522
523 // initialize termination ops
524 ECF_LOG(this, 4, "Initializing termination operators...");
525 activeTerminationOps_.clear();
526 for(uint i = 0; i < allTerminationOps_.size(); i++)
527 if(allTerminationOps_[i]->initialize(state_))
528 activeTerminationOps_.push_back(allTerminationOps_[i]);
529 // if no term operators are configured, activate default (the first)
530 if(activeTerminationOps_.empty())
531 activeTerminationOps_.push_back(allTerminationOps_[0]);
532
533 // initialize user ops
534 ECF_LOG(this, 4, "Initializing user defined operators...");
535 activeUserOps_.clear();
536 for(uint i = 0; i < allUserOps_.size(); i++)
537 if(allUserOps_[i]->initialize(state_))
538 activeUserOps_.push_back(allUserOps_[i]);
539
540 // evaluation op. initializes last
541 ECF_LOG(this, 4, "Initializing evaluation operator...");
542 if(!evalOp_->initialize(state_))
543 throw "Error: Evaluation operator initialization failed!";
544
545 // generate one individual
546 ECF_LOG(this, 4, "Generating test individual...");
547 individual_ = (IndividualP) (new Individual(state_));
548
549 } // try
550
551 catch(std::string& msg) {
552 std::cout << msg << std::endl;
553 bInitialized_ = false;
554 }
555 catch(const char* msg) {
556 std::cout << msg << std::endl;
557 bInitialized_ = false;
558 }
559 catch(...) {
560 std::cout << "Unknown error in initialization!" << std::endl;
561 bInitialized_ = false;
562 }
563
564 return bInitialized_;
565}
566
567
570{
571 try {
572 if(!fitness_) {
573 context_->evaluatedIndividual = individual_;
574 fitness_ = evalOp_->evaluate(individual_);
575 }
576
577 }
578 catch(...) {
579 std::cout << "Error in evaluation operator!" << std::endl;
580 }
581
582 return fitness_;
583}
584
585
592bool State::runBatch()
593{
594 bBatchStart_ = false;
595 bBatchMode_ = true;
596
597 bool bUseLog = registry_->isModified("log.filename");
598
599 // are we restoring from a milestone file
600 if(!bLoadMilestone_)
601 batchRemaining_ = batchRepeats_;
602 uint numerals = 1 + (uint) (log((double) batchRepeats_) / log((double) 10.));
603
604 // get logfile name and extension
605 std::string logFileName = *(std::string*) registry_->getEntry("log.filename").get();
606 std::string logFileExt = "";
607 if(bLoadMilestone_)
608 logFileName = batchLogFile_;
609 else
610 batchLogFile_ = logFileName;
611
612 if(logFileName.find_last_of(".") != std::string::npos) {
613 logFileExt = logFileName.substr(logFileName.find_last_of("."));
614 logFileName = logFileName.substr(0, logFileName.find_last_of("."));
615 }
616
617 // get milestone name and extension
618 std::string milestoneName = *(std::string*) registry_->getEntry("milestone.filename").get();
619 std::string milestoneExt = "";
620 if(milestoneName.find_last_of(".") != std::string::npos) {
621 milestoneExt = milestoneName.substr(milestoneName.find_last_of("."));
622 milestoneName = milestoneName.substr(0, milestoneName.find_last_of("."));
623 }
624
625 // (re)open stats file, if defined
626 std::ofstream statsFile;
627 if(registry_->isModified("batch.statsfile")) {
628 if(bLoadMilestone_)
629 statsFile.open(batchStatsFile_.c_str(), std::ios_base::app);
630 else {
631 statsFile.open(batchStatsFile_.c_str());
632 statsFile << "runId\tfit_min\tfit_max\tfit_avg\tfit_std\t#evals\ttime\tgen\n";
633 }
634 if(!statsFile) {
635 ECF_LOG_ERROR(this, "Error: can't open batch statsfile (" + batchStatsFile_ + ")!");
636 return false;
637 }
638 statsFile.close();
639 bBatchWriteStats_ = true;
640 }
641
642 uint runId = batchRepeats_ - batchRemaining_ + 1;
643
644 // perform algorithm runs
645 for(; runId <= batchRepeats_; runId++) {
646 // set current logfile
647 if(bUseLog) {
648 std::stringstream ss;
649 ss << std::setw(numerals) << std::setfill('0') << runId;
650 std::string currentLogName = logFileName + "_" + ss.str() + logFileExt;
651 registry_->modifyEntry("log.filename", (voidP) new std::string(currentLogName));
652 }
653
654 // set current milestone
655 if(!bBatchSingleMilestone_) {
656 std::stringstream ss;
657 ss << std::setw(numerals) << std::setfill('0') << runId;
658 milestoneFilename_ = milestoneName + "_" + ss.str() + milestoneExt;
659 }
660
661 // run
662 bInitialized_ = true;
663 if(!initializeComponents(argc_, argv_))
664 break;
665 ECF_LOG(this, 1, "Running in batch mode: run " + uint2str(runId) + "/" + uint2str(batchRepeats_));
666 run();
667 batchRemaining_--;
668
669 // write stats (PECF: only master process)
670 if(comm_->getCommGlobalRank() == 0) {
671 if(bBatchWriteStats_) {
672 statsFile.open(batchStatsFile_.c_str(), std::ios_base::app);
673 std::vector<double> stats = population_->getStats()->getStats();
674 statsFile << runId << '\t';
675 statsFile << stats[ECF::FIT_LOW] << '\t' << stats[ECF::FIT_HIGH] << '\t' << stats[ECF::FIT_AVG] << '\t' << stats[ECF::FIT_DEV] << '\t';
676 statsFile << stats[ECF::STAT_EVAL] << '\t' << stats[ECF::STAT_TIME] << '\t' << getGenerationNo() << '\n';
677 statsFile.close();
678 }
679 }
680 }
681
682 // ugly workabout for MPI_Finalize, which may only be called once
683 // (shouldn't be called at the end of a single run)
684 bBatchMode_ = false;
685 comm_->finalize();
686
687 if(bInitialized_)
688 std::cout << "Batch mode end (" << batchRepeats_ << " runs concluded)." << std::endl;
689
690 if(statsFile)
691 statsFile.close();
692 return true;
693}
694
695
696
707bool State::initialize(int argc, char **argv)
708{
709 this->state_ = this->getState(); // obtain a sptr to this
710
711 genotype_.clear();
712 mutation_->operators.clear();
713 crossover_->operators.clear();
714
715 bInitialized_ = false;
716 argc_ = argc;
717 argv_ = argv;
718 std::string config_file;
719
720 try {
721
722 std::cout << "-- ECF, version " << ECF_VERSION << " --" << std::endl;
723
724 if(!bEvaluatorSet_) {
725 throw "Error: no EvaluateOp defined!";
726 }
727
728 if (argc > 1) {
729 // parse arguments: return success if command line option is recognized
730 if(parseCommandLine(argc, argv))
731 return false;
732
733 // otherwise, assume configuration file name as argument
734 config_file = argv[1];
735 }
736
737 registerParameters();
738
739 if (config_file != "") {
740 parseConfig(config_file);
741 }
742 else {
743 std::cout << "Warning: no configuration file given." << std::endl;
744 std::cout << "Example usage: <ECF_executable> <parameter_file>" << std::endl;
745 }
746
747 // use the default algorithm
748 if (!bAlgorithmSet_)
749 algorithm_ = mAlgorithms_.find("SteadyStateTournament")->second;
750
751 if(!bGenotypeSet_) {
752 throw "Error: no Genotype defined!";
753 }
754
755 readParameters();
756
757 // set init flag, then test with each component initialization
758 bInitialized_ = true;
759
760 initializeComponents(argc, argv);
761
762 // if multiple runs, milestone will get parsed in State::run()
763 if (bBatchStart_)
764 return true;
765
766 if(bLoadMilestone_)
767 loadMilestone();
768
769 ECF_LOG(this, 4, "Initialization complete.");
770
771 } // try
772
773 catch(std::string& msg) {
774 std::cout << msg << std::endl;
775 }
776 catch(const char* msg) {
777 std::cout << msg << std::endl;
778 }
779 catch(...) {
780 std::cout << "Unknown error in initialization!" << std::endl;
781 }
782
783 return bInitialized_;
784}
785
786
787
793bool State::parseCommandLine(int argc, char** argv)
794{
795 // read all arguments
796 std::vector< std::string > arg;
797 for(int i = 0; i < argc; i++)
798 arg.push_back(argv[i]);
799
800 bCommandLine_ = true;
801
802 // GUI related arguments
803 if(arg[1] == "-gui") {
804 if(argc > 3 && arg[2] == "-pardump")
805 dumpParameters(arg[3], false);
806 }
807
808 // dump all parameters
809 else if(arg[1] == "-pardump") {
810 if(argc < 3) {
811 std::cout << "No output file given for parameter dump! (usage: <executable> -pardump <filename>)" << std::endl;
812 }
813 else {
814 std::cout << "Exporting complete parameter list to \'" << arg[2] << "\'...\n";
815 dumpParameters(arg[2]);
816 }
817 }
818
819 // display cmd arguments
820 else if(arg[1].substr(0,2) == "-h" || arg[1].substr(0,3) == "--h") {
821 std::cout << "Current command line arguments:\n";
822 std::cout << "\t<parameter_file> run ECF with given parameter file\n";
823 std::cout << "\t-pardump <file> dump all parameters in a given file\n";
824 std::cout << "\t-h, -help display this help\n";
825 }
826
827 else
828 bCommandLine_ = false;
829
830 return bCommandLine_;
831}
832
833
834
839{ return algorithm_->isImplicitParallel(); }
840
841
846{ return algorithm_->isParallel(); }
847
848
853void State::write(XMLNode& xState)
854{
855 registry_->modifyEntry("milestone.generation_", (voidP) (new uint(getGenerationNo())));
856 registry_->modifyEntry("milestone.elapsedtime_", (voidP) (new time_t(elapsedTime_)));
857 registry_->modifyEntry("batch.remaining_", (voidP) (new uint(batchRemaining_)));
858 if(batchLogFile_ != "")
859 registry_->modifyEntry("batch.logfile_", (voidP) (new std::string(batchLogFile_)));
860 else
861 registry_->modifyEntry("batch.logfile_", (voidP) (new std::string("*")));
862}
863
864
869void State::saveMilestone()
870{
871 XMLNode xMainNode = XMLNode::createXMLTopNode("ECF");
872 xMainNode.addAttribute("milestone", ctime(&currentTime_));
873
874 XMLNode xMilestone;
875 this->write(xMilestone);
876 xMainNode.addChild(xMilestone);
877
878 XMLNode xNode = this->xConfig_.getChildNode(NODE_ALGORITHM);
879 xNode = xNode.deepCopy();
880 xMainNode.addChild(xNode);
881 xNode = this->xConfig_.getChildNode(NODE_GENOTYPE);
882 xNode = xNode.deepCopy();
883 xMainNode.addChild(xNode);
884
885 this->registry_->write(xNode);
886 xMainNode.addChild(xNode);
887
888 // save population
889 XMLNode xPopulation;
890 population_->write(xPopulation);
891 xMainNode.addChild(xPopulation);
892
893#ifdef _MPI
894 if(comm_->getCommGlobalRank() != 0)
895 return;
896#endif
897
898 xMainNode.writeToFile(milestoneFilename_.c_str());
899}
900
901
906void State::loadMilestone()
907{
908 ECF_LOG(this, 4, "Loading population and evolutionary context from milestone...");
909 XMLNode xPopulation = xConfig_.getChildNode("Population");
910 population_->read(xPopulation);
911
912 context_->generationNo_ = milestoneGeneration_;
913}
914
915
916
917//
918// setting components
919//
920
930uint State::setGenotype(GenotypeP genotype)
931{
932 genotype_.push_back((GenotypeP) genotype->copy());
933 uint index = (uint) genotype_.size() - 1;
934 genotype_[index]->setGenotypeId(index);
935 genotype->setGenotypeId(index);
936
937 genotype_[index]->registerParameters(state_);
938
939 // read genotype's operators and register their parameters
940 crossover_->operators.push_back(genotype_[index]->getCrossoverOp());
941 for(uint iOp = 0; iOp < crossover_->operators[index].size(); iOp++) {
942 crossover_->operators[index][iOp]->myGenotype_ = genotype_[index];
943 crossover_->operators[index][iOp]->registerParameters(state_);
944 }
945
946 mutation_->operators.push_back(genotype_[index]->getMutationOp());
947 for(uint iOp = 0; iOp < mutation_->operators[index].size(); iOp++) {
948 mutation_->operators[index][iOp]->myGenotype_ = genotype_[index];
949 mutation_->operators[index][iOp]->registerParameters(state_);
950 }
951
952 bGenotypeSet_ = true;
953 return index;
954}
955
957void State::setAlgorithm(AlgorithmP algorithm)
958{
959 algorithm_ = algorithm;
960 bAlgorithmSet_ = true;
961}
962
963
969void State::setEvalOp(EvaluateOpP eval)
970{
971 evalOp_ = eval;
972 bEvaluatorSet_ = true;
973}
974
975
982{
983 evalOp_ = (EvaluateOpP) eval;
984 bEvaluatorSet_ = true;
985}
986
987
988//
989// adding components
990//
991
1000bool State::addGenotype(GenotypeP gen)
1001{
1002 mGenotypes_[gen->getName()] = gen;
1003 return true;
1004}
1005
1006
1015bool State::addAlgorithm(AlgorithmP alg)
1016{
1017 mAlgorithms_[alg->getName()] = alg;
1018 return true;
1019}
1020
1028bool State::addOperator(OperatorP op)
1029{
1030 allUserOps_.push_back(op);
1031 return true;
1032}
1033
1034
1035
1036//
1037// run methods
1038//
1039
1040#ifndef _MPI
1048{
1049 // command line only (no evolution)
1050 if(bCommandLine_)
1051 return false;
1052
1053 if(!bInitialized_) {
1054 std::cout << "Error: Initialization failed!" << std::endl;
1055 return false;
1056 }
1057
1058 if(bBatchStart_) {
1059 ECF_LOG(this, 5, "Batch mode detected: running batch");
1060 runBatch();
1061 return true;
1062 }
1063
1064 startTime_ = time(NULL);
1065 std::string stime = ctime(&startTime_);
1066 ECF_LOG(this, 3, "Start time: " + stime);
1067 // adjust with previous runtime (from milestone)
1068 startTime_ -= milestoneElapsedTime_;
1069
1070 // evaluate initial population
1071 ECF_LOG(this, 2, "Evaluating initial population...");
1072 algorithm_->initializePopulation(state_);
1073
1074 currentTime_ = time(NULL);
1075 elapsedTime_ = currentTime_ - startTime_;
1076 ECF_LOG(this, 2, "Generation: " + uint2str(context_->generationNo_));
1077 ECF_LOG(this, 2, "Elapsed time: " + uint2str((uint) elapsedTime_));
1078 population_->updateDemeStats();
1079
1080 // call user-defined operators
1081 ECF_LOG(this, 4, "Calling user defined operators...");
1082 for(uint i = 0; i < activeUserOps_.size(); i++)
1083 activeUserOps_[i]->operate(state_);
1084
1085 // termination ops
1086 ECF_LOG(this, 4, "Checking termination conditions...");
1087 for(uint i = 0; i < activeTerminationOps_.size(); i++)
1088 activeTerminationOps_[i]->operate(state_);
1089
1090 // run the algorithm
1091 while(context_->bTerminate_ == false) {
1092 context_->generationNo_++;
1093 ECF_LOG(this, 5, "Calling the active algorithm");
1094 algorithm_->advanceGeneration(state_);
1095
1096 currentTime_ = time(NULL);
1097 elapsedTime_ = currentTime_ - startTime_;
1098 ECF_LOG(this, 2, "Generation: " + uint2str(context_->generationNo_));
1099 ECF_LOG(this, 2, "Elapsed time: " + uint2str((uint) elapsedTime_));
1100
1101 population_->updateDemeStats();
1102
1103 // call user-defined operators
1104 ECF_LOG(this, 4, "Calling user defined operators...");
1105 for(uint i = 0; i < activeUserOps_.size(); i++)
1106 activeUserOps_[i]->operate(state_);
1107
1108 // termination ops
1109 ECF_LOG(this, 4, "Checking termination conditions...");
1110 for(uint i = 0; i < activeTerminationOps_.size(); i++)
1111 activeTerminationOps_[i]->operate(state_);
1112
1113 if(context_->bTerminate_)
1114 logger_->saveTo(true);
1115 else
1116 logger_->saveTo();
1117
1118 if(bSaveMilestone_ &&
1119 milestoneInterval_ > 0 && context_->generationNo_ % milestoneInterval_ == 0)
1120 saveMilestone();
1121
1122 migration_->operate(state_);
1123 }
1124
1125 // output HallOfFame
1126 XMLNode xHoF;
1127 population_->getHof()->write(xHoF);
1128 char *out = xHoF.createXMLString(true);
1129 ECF_LOG(this, 1, "\nBest of run: \n" + std::string(out));
1130 freeXMLString(out);
1131
1132 logger_->saveTo(true);
1133 if(bSaveMilestone_)
1134 saveMilestone();
1135
1136 logger_->closeLog();
1137
1138 return true;
1139}
1140
1141
1142#else // _MPI
1149bool State::run()
1150{
1151 // command line only (no evolution)
1152 if(bCommandLine_)
1153 return false;
1154
1155 if(bBatchStart_) {
1156 runBatch();
1157 return true;
1158 }
1159
1160 // TODO: perform AND_reduce with bInitialized on all processes
1161 if(!bInitialized_) {
1162 std::cout << "Error: Initialization failed!" << std::endl;
1163 logger_->saveTo();
1164 if(comm_->isInitialized())
1165 comm_->finalize();
1166 return false;
1167 }
1168
1169 startTime_ = time(NULL);
1170 std::string stime = ctime(&startTime_);
1171 ECF_LOG(this, 3, "Start time: " + stime);
1172 // adjust with previous runtime (from milestone)
1173 startTime_ -= milestoneElapsedTime_;
1174
1175 // in PECF, every process works with deme '0'
1176 // 'deme masters' - processes with index 0 in local communicator
1177 // only deme masters know of whole population
1178 if(comm_->getCommRank() == 0) {
1179 ECF_LOG(this, 2, "Evaluating initial population...");
1180 }
1181
1182 // every process participates in the initial population evaluation
1183 algorithm_->initializePopulation(state_);
1184 comm_->synchronize();
1185
1186 if(comm_->getCommRank() == 0) {
1187 // dodatna inicijalizacija za implicitni paralelizam - mozda promijeniti...
1188 if(isImplicitParallel())
1189 algorithm_->initializeImplicit(state_);
1190 }
1191
1192 // run the algorithm
1193 while(context_->bTerminate_ == false) {
1194
1195 currentTime_ = time(NULL);
1196 elapsedTime_ = currentTime_ - startTime_;
1197 if(comm_->getCommGlobalRank() == 0) {
1198 ECF_LOG(this, 2, "Generation: " + uint2str(context_->generationNo_));
1199 ECF_LOG(this, 2, "Elapsed time: " + uint2str((uint) elapsedTime_));
1200 }
1201
1202 // deme masters initiate population statistics and HoF update
1203 if(comm_->getCommRank() == 0) {
1204 population_->updateDemeStats();
1205
1206 if(bSaveMilestone_ && milestoneInterval_ > 0 && context_->generationNo_ % milestoneInterval_ == 0)
1207 saveMilestone();
1208 }
1209
1210 // global process 0 checks termination condition and signals deme masters
1211 if(comm_->getCommGlobalRank() == 0) {
1212 ECF_LOG(this, 4, "Checking termination conditions...");
1213 for(uint i = 0; i < activeTerminationOps_.size(); i++)
1214 activeTerminationOps_[i]->operate(state_);
1215
1216 for(uint i = 1; i < population_->getNoDemes(); i++)
1217 comm_->sendTerminateMessage(comm_->getDemeMaster(i), context_->bTerminate_);
1218 }
1219 // deme masters receive info
1220 else if(comm_->getCommRank() == 0)
1221 context_->bTerminate_ = comm_->recvTerminateMessage(0);
1222
1223 // deme masters signal workers of evolution continuation
1224 algorithm_->bcastTermination(state_);
1225
1226 // deme masters call migration operator
1227 if(comm_->getCommRank() == 0) {
1228 migration_->operate(state_);
1229 }
1230
1231 // call user-defined operators
1232 ECF_LOG(this, 4, "Calling user defined operators...");
1233 for(uint i = 0; i < activeUserOps_.size(); i++)
1234 activeUserOps_[i]->operate(state_);
1235
1236 if(context_->bTerminate_ == true) {
1237 logger_->saveTo(true);
1238 break;
1239 }
1240
1241 logger_->saveTo();
1242
1243 context_->generationNo_++;
1244 ECF_LOG(this, 5, "Calling the active algorithm");
1245 algorithm_->advanceGeneration(state_);
1246 }
1247
1248 logger_->setLogFrequency(1);
1249 if(comm_->getCommGlobalRank() == 0) {
1250 // output HallOfFame
1251 XMLNode xHoF;
1252 population_->getHof()->write(xHoF);
1253 std::string out = xHoF.createXMLString(true);
1254 ECF_LOG(this, 1, "\nBest of run: \n" + out);
1255
1256 logger_->saveTo(true);
1257 }
1258
1259 if(comm_->getCommRank() == 0 && bSaveMilestone_)
1260 saveMilestone();
1261
1262 logger_->saveTo(true);
1263
1264 // communicator
1265 comm_->finalize();
1266
1267 return true;
1268}
1269#endif // _MPI
Asynchronous elimination global parallel algorithm (outdated version)
Definition: AlgAEliGPEA2.h:10
Asynchronous elimination global parallel algorithm.
Definition: AlgAEliGPEA.h:12
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.
Definition: Communicator.h:43
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.
Definition: FloatingPoint.h:39
new algorithm, in development
Genetic annealing algorithm (see e.g. http://citeseerx.ist.psu.edu/viewdoc/summary?...
Individual class - inherits a vector of Genotype objects.
Definition: Individual.h:12
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:42
Generational algorithm with roulette wheel selection operator.
A simple randomizer that uses in-built random number generator.
void setAlgorithm(AlgorithmP)
Set the desired algorithm (overrides the current choice)
Definition: State.cpp:957
FitnessP getFitnessObject()
get one initial Fitness object (create on demand)
Definition: State.cpp:569
bool addGenotype(GenotypeP gen)
Add user-defined or user customized genotype. (The genotype can then be specified and used in config ...
Definition: State.cpp:1000
void setEvalOp(EvaluateOpP)
Set user defined evaluation operator.
Definition: State.cpp:969
bool addAlgorithm(AlgorithmP alg)
Add user-defined or user customized algorithm. (It can then be specified and used in config file....
Definition: State.cpp:1015
bool run()
Driver of the evolution process - serial version.
Definition: State.cpp:1047
bool isImplicitParallel()
Is the algorithm executed implicitly parallel.
Definition: State.cpp:838
bool initialize(int, char **)
Initialize the whole system.
Definition: State.cpp:707
uint setGenotype(GenotypeP)
Set a genotype to be used in individuals.
Definition: State.cpp:930
bool isAlgorithmParallel()
Is current algorithm parallel.
Definition: State.cpp:845
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:1028
uint getGenerationNo()
get current generation number
Definition: State.h:148
void setRandomizer(RandomizerP randomizer)
set Randomizer to be used
Definition: State.h:124
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.
Definition: TermMaxEvalOp.h:9
Termination operator: terminates on a given number of generations.
Definition: TermMaxGenOp.h:9
Termination operator: terminates on a given elapsed time.
Definition: TermMaxTimeOp.h:9
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
XCS classifier system.
Definition: AlgXCS.h:30
Definition: nodes.h:92