ECF 1.5
GEPChromosome.cpp
1#include "GEPChromosome.h"
2namespace GEPChromosome{
3 // mandatory: define name, other things as needed
5 Genotype::name_ = "GEPChromosome";
6 usesERC = false;
7 dcLength = 0;
8 staticLink = false;
9 }
10
11 // mandatory: must provide copy method
12 GEPChromosome* GEPChromosome::copy(){
13 GEPChromosome *newObject = new GEPChromosome(*this);
14 return newObject;
15 }
16
17 // optional: declare crx operators (if not, no crossover will be performed)
18 std::vector<CrossoverOpP> GEPChromosome::getCrossoverOp()
19 {
20 std::vector<CrossoverOpP> crx;
21 crx.push_back(static_cast<CrossoverOpP> (new GEPChromosomeCrsOnePoint));
22 crx.push_back(static_cast<CrossoverOpP> (new GEPChromosomeCrsTwoPoint));
23 crx.push_back(static_cast<CrossoverOpP> (new GEPChromosomeCrsGene));
24 return crx;
25 }
26
27 // optional: declare mut operators (if not, no mutation will be performed)
28 std::vector<MutationOpP> GEPChromosome::getMutationOp()
29 {
30 std::vector<MutationOpP> mut;
31 mut.push_back(static_cast<MutationOpP> (new GEPChromosomeMutOp));
32 mut.push_back(static_cast<MutationOpP> (new GEPChromosomeMutGauss));
33 return mut;
34 }
35
36 // optional: register any parameters
37 void GEPChromosome::registerParameters(StateP state)
38 {
39 registerParameter(state, "headlength", (voidP)(new uint(1)), ECF::UINT);
40 registerParameter(state, "genes", (voidP)(new uint(1)), ECF::UINT);
41 registerParameter(state, "functionset", (voidP)(new std::string), ECF::STRING);
42 registerParameter(state, "terminalset", (voidP)(new std::string), ECF::STRING);
43 registerParameter(state, "linkingfunctions", (voidP)(new std::string), ECF::STRING);
44 registerParameter(state, "linklength", (voidP)(new uint(1)), ECF::UINT);
45 }
46
47 void GEPChromosome::generateChromosome(){
49 for (uint i = 0; i < genes; i++){
50 // Generate random primitives for the head (Functions + Terminals)
51 for (uint j = 0; j < headLength; j++) {
52 node = new Tree::Node();
53 node->setPrimitive(primitiveSet_->getRandomPrimitive());
54 this->push_back(static_cast<Tree::NodeP>(node));
55 }
56 // Generate random terminals for the tail
57 for (uint j = 0; j < tailLength; j++) {
58 node = new Tree::Node();
59 node->setPrimitive(primitiveSet_->getRandomTerminal());
60 this->push_back(static_cast<Tree::NodeP>(node));
61 }
62 // Generate ERCs for the Dc domain
63 for (uint j = 0; j < dcLength; j++){
64 node = new Tree::Node();
65 node->setPrimitive(ercSet_->getRandomTerminal());
66 this->push_back(static_cast<Tree::NodeP>(node));
67 }
68 }
69 // Set the homeotic gene (this controls the linking functions)
70 for (uint i = 0; i < linkHeadLength; i++){
71 node = new Tree::Node();
72 node->setPrimitive(linkFunctionSet_->getRandomPrimitive());
73 this->push_back(static_cast<Tree::NodeP>(node));
74 }
75 for (uint i = 0; i < linkTailLength; i++){
76 node = new Tree::Node();
77 node->setPrimitive(linkFunctionSet_->getRandomTerminal());
78 this->push_back(static_cast<Tree::NodeP>(node));
79 }
80 }
81
82 // mandatory: build initial genotype structure
83 bool GEPChromosome::initialize(StateP state)
84 {
85 // 'homegep' is a Gep instance kept in the State;
86 // we use it to link the PrimitiveSet to it and store the parameters
87 GEPChromosome* homegep = (GEPChromosome*)state->getGenotypes()[genotypeId_].get();
88 state_ = state;
89
90 // if we are the first one to initialize
91 if (!homegep->primitiveSet_){
92 initializeFirst(homegep);
93 }
94 // in any case, read parameters from from hometree
95 this->primitiveSet_ = homegep->primitiveSet_;
96 this->linkFunctionSet_ = homegep->linkFunctionSet_;
97 this->ercSet_ = homegep->ercSet_;
98 this->headLength = homegep->headLength;
99 this->genes = homegep->genes;
100 this->tailLength = homegep->tailLength;
101 this->dcLength = homegep->dcLength;
102 this->geneLength = homegep->geneLength;
103 this->linkHeadLength = homegep->linkHeadLength;
104 this->linkTailLength = homegep->linkTailLength;
105 // generate the chromosome
106 generateChromosome();
107
108 return true;
109 }
110
111 void GEPChromosome::initializeFirst(GEPChromosome* home){
112
113 // create and link PrimitiveSet to the hometree
114 if (home == NULL){
115 return;
116 }
117 home->primitiveSet_ = static_cast<Tree::PrimitiveSetP> (new Tree::PrimitiveSet);
118 home->primitiveSet_->initialize(state_);
119 this->primitiveSet_ = home->primitiveSet_;
120
121 home->linkFunctionSet_ = static_cast<Tree::PrimitiveSetP> (new Tree::PrimitiveSet);
122 home->linkFunctionSet_->initialize(state_);
123 this->linkFunctionSet_ = home->linkFunctionSet_;
124
125 home->ercSet_ = static_cast<Tree::PrimitiveSetP> (new Tree::PrimitiveSet);
126 home->ercSet_->initialize(state_);
127 this->ercSet_ = home->ercSet_;
128
129 // read number of genes, store in hometree
130 voidP sptr = getParameterValue(state_, "genes");
131 home->genes = *((uint*)sptr.get());
132
133 if (home->genes < 1) {
134 ECF_LOG_ERROR(state_, "Gep genotype: number of genes must be >=1");
135 }
136
137 // add user defined functions to primitiveSet
138
139 for (int i = 0; i < (int)userFunctions_.size(); i++) {
140 primitiveSet_->mAllPrimitives_[userFunctions_[i]->getName()] = userFunctions_[i];
141 }
142
143 uint maxArg = 0;
144 uint tmpArg = 0;
145 // read function set from the configuration
146 sptr = getParameterValue(state_, "functionset");
147 std::stringstream names;
148 std::string name;
149 names << *((std::string*) sptr.get());
150 while (names >> name) {
151 if (!primitiveSet_->addFunction(name)) {
152 ECF_LOG_ERROR(state_, "Error: unknown function in function set (\'" + name + "\')!");
153 throw("");
154 }
155 tmpArg = primitiveSet_->getPrimitiveByName(name)->getNumberOfArguments();
156 if (tmpArg > maxArg)
157 maxArg = tmpArg;
158 }
159 // read Gep head length, store in hometree
160 sptr = getParameterValue(state_, "headlength");
161 home->headLength = *((uint*)sptr.get());
162
163 if (home->headLength < 1) {
164 ECF_LOG_ERROR(state_, "Gep genotype: length of head must be >= 1");
165 }
166
167 // now we can tell how long tail must be
168 home->tailLength = home->headLength * (maxArg - 1) + 1;
169 home->geneLength = home->headLength + home->tailLength;
170
171 if (primitiveSet_->getFunctionSetSize() == 0) {
172 ECF_LOG_ERROR(state_, "Tree genotype: empty function set!");
173 throw("");
174 }
175
176 // create and link the linking function set
177 // Mono-genic chromosomes should have a constant homeotic gene for the sake of simplicity (i.e., their homeotic gene shall always be "0")
178 // Multi-genic chromosomes can evolve their homeotic gene by default, unless a static linking configuration is specified (TO-DO)
179
180 uint linkMaxArg = 0;
181 uint linkTmpArg = 0;
182 std::stringstream linkNames;
183 // read linking function set from the configuration
184 sptr = getParameterValue(state_, "linkingfunctions");
185 linkNames << *((std::string*) sptr.get());
186 while (linkNames >> name) {
187 if (!linkFunctionSet_->addFunction(name)) {
188 ECF_LOG_ERROR(state_, "Error: unknown function in linking function set (\'" + name + "\')!");
189 throw("");
190 }
191 linkTmpArg = linkFunctionSet_->getPrimitiveByName(name)->getNumberOfArguments();
192 if (linkTmpArg > linkMaxArg)
193 linkMaxArg = linkTmpArg;
194 }
195 // read homeotic gene head length, store in hometree
196 sptr = getParameterValue(state_, "linklength");
197 home->linkHeadLength = *((uint*)sptr.get());
198
199 if (home->linkHeadLength < 1) {
200 ECF_LOG_ERROR(state_, "Gep genotype: length of linking function gene head must be >= 1");
201 }
202
203 // now we can tell how long tail must be
204 home->linkTailLength = home->linkHeadLength * (linkMaxArg - 1) + 1;
205
206 if (linkFunctionSet_->getFunctionSetSize() == 0) {
207 ECF_LOG_ERROR(state_, "GEP genotype: empty linking function set!");
208 }
209 // Add "terminals" to the linking function set. These will be a prefix + integers from [0, # of genes]
210 for (uint i = 0; i < home->genes; i++){
211 Tree::PrimitiveP geneTerminals = (Tree::PrimitiveP)(new Tree::Primitives::Terminal);
212 std::string geneTermStr = GEP_GENE_PREFIX;
213 geneTermStr += uint2str(i);
214 geneTerminals->setName(geneTermStr);
215 geneTerminals->initialize(state_);
216 linkFunctionSet_->addTerminal(geneTerminals);
217 }
218 // set default terminal type
219 Tree::Primitives::terminal_type currentType = Tree::Primitives::Double;
220 Tree::type_iter typeIter;
221
222 // read terminal set from the configuration
223
224 std::stringstream tNames;
225 sptr = getParameterValue(state_, "terminalset");
226 tNames << *((std::string*) sptr.get());
227
228 while (tNames >> name) {
229 // read current terminal type (if set)
230 typeIter = primitiveSet_->mTypeNames_.find(name);
231 if (typeIter != primitiveSet_->mTypeNames_.end()) {
232 currentType = typeIter->second;
233 continue;
234 }
235
236 // see if it's a user-defined terminal
237 /*
238 uint iTerminal = 0;
239 for (; iTerminal < userTerminals_.size(); iTerminal++)
240 if (userTerminals_[iTerminal]->getName() == name)
241 break;
242 if (iTerminal < userTerminals_.size()) {
243 primitiveSet_->addTerminal(userTerminals_[iTerminal]);
244 continue;
245 }
246 */
247 // read ERC definition (if set)
248 // ERC's are defined as interval [x y] or set {a b c}
249 // If ERCs are requested by the user, we add the placeholder terminal '?' to primitiveSet_
250 // We then add any ERCs to ercSet_
251
252 if (name[0] == '[' || name[0] == '{') {
253
254 //if this is the first ERC range we encounter, add the placeholder and switch on the ERC flag
255 if (!usesERC){
256 usesERC = true;
257 Tree::PrimitiveP placeholder = (Tree::PrimitiveP) (new Tree::Primitives::Terminal);
258 placeholder->setName("?");
259 primitiveSet_->addTerminal(placeholder);
260 // If ERCs are used, the length of the Dc domain is the same as the tail length
261 home->dcLength = home->tailLength;
262 home->geneLength += home->dcLength;
263 }
264
265 std::string ercValues = "";
266
267 // name this ERC (ERC's name is its value!)
268 Tree::PrimitiveP erc;
269 switch (currentType) {
270 case Tree::Primitives::Double:
271 erc = (Tree::PrimitiveP)(new Tree::Primitives::ERCD);
272 ercValues = DBL_PREFIX;
273 break;
274 case Tree::Primitives::Int:
275 erc = (Tree::PrimitiveP)(new Tree::Primitives::ERC<int>);
276 ercValues = INT_PREFIX;
277 break;
278 case Tree::Primitives::Bool:
279 erc = (Tree::PrimitiveP)(new Tree::Primitives::ERC<bool>);
280 ercValues = BOOL_PREFIX;
281 break;
282 case Tree::Primitives::Char:
283 erc = (Tree::PrimitiveP)(new Tree::Primitives::ERC<char>);
284 ercValues = CHR_PREFIX;
285 break;
286 case Tree::Primitives::String:
287 erc = (Tree::PrimitiveP)(new Tree::Primitives::ERC<std::string>);
288 ercValues = STR_PREFIX;
289 break;
290 }
291
292 while (name[name.size() - 1] != ']' && name[name.size() - 1] != '}') {
293 ercValues += " " + name;
294 tNames >> name;
295 }
296 ercValues += " " + name;
297 erc->setName(ercValues);
298 erc->initialize(state_);
299 ercSet_->addTerminal(erc);
300
301 continue;
302 }
303
304 //read terminal of current type
305 Tree::PrimitiveP terminal;
306 switch (currentType)
307 {
308 case Tree::Primitives::Double:
309 terminal = (Tree::PrimitiveP) (new Tree::Primitives::Terminal); break;
310 case Tree::Primitives::Int:
311 terminal = (Tree::PrimitiveP) (new Tree::Primitives::TerminalT<int>); break;
312 case Tree::Primitives::Bool:
313 terminal = (Tree::PrimitiveP) (new Tree::Primitives::TerminalT<bool>); break;
314 case Tree::Primitives::Char:
315 terminal = (Tree::PrimitiveP) (new Tree::Primitives::TerminalT<char>); break;
316 case Tree::Primitives::String:
317 terminal = (Tree::PrimitiveP) (new Tree::Primitives::TerminalT<std::string>); break;
318 }
319
320 // if the 'name' can be identified as a value of the 'currentType', then it's a _constant terminal_ (of that value)
321 // otherwise, it's a regular terminal with 'name'
322 std::istringstream ss(name);
323 switch (currentType)
324 {
325 case Tree::Primitives::Double:
326 double dblValue;
327 ss >> dblValue;
328 if (ss.fail() == false)
329 terminal->setValue(&dblValue);
330 break;
331 case Tree::Primitives::Int:
332 int intValue;
333 ss >> intValue;
334 if (ss.fail() == false)
335 terminal->setValue(&intValue);
336 break;
337 case Tree::Primitives::Bool:
338 bool boolValue;
339 ss >> boolValue;
340 if (name == "true")
341 boolValue = true;
342 else if (name == "false")
343 boolValue = false;
344 if (ss.fail() == false || name == "true" || name == "false") {
345 if (boolValue)
346 name = "true";
347 else
348 name = "false";
349 terminal->setValue(&boolValue);
350 }
351 break;
352 case Tree::Primitives::Char:
353 char charValue;
354 ss >> charValue;
355 if (ss.fail() == false)
356 terminal->setValue(&charValue);
357 break;
358 case Tree::Primitives::String:
359 std::string stringValue;
360 ss >> stringValue;
361 if (ss.fail() == false)
362 terminal->setValue(&stringValue);
363 break;
364 }
365 terminal->setName(name);
366 primitiveSet_->addTerminal(terminal);
367
368 }
369
370 if (primitiveSet_->getTerminalSetSize() == 0) {
371 ECF_LOG_ERROR(state_, "Tree: Empty terminal set!");
372 throw("");
373 }
374
375 }
376
377 // mandatory: write to XMLNode
378 void GEPChromosome::write(XMLNode &xGEPChromosome)
379 {
380 xGEPChromosome = XMLNode::createXMLTopNode("GEPChromosome");
381 std::stringstream sValue;
382 sValue << genes;
383 xGEPChromosome.addAttribute("genes", sValue.str().c_str());
384 sValue.str("");
385 sValue << headLength;
386 xGEPChromosome.addAttribute("headLength",sValue.str().c_str());
387 sValue.str("");
388 sValue << tailLength;
389 xGEPChromosome.addAttribute("tailLength", sValue.str().c_str());
390 sValue.str("");
391 sValue << linkHeadLength;
392 xGEPChromosome.addAttribute("linkLength", sValue.str().c_str());
393 for (uint g = 0; g < genes; g++){
394 sValue.str("");
395 XMLNode xGene = XMLNode::createXMLTopNode("Gene");
396 for (uint i = 0; i < this->geneLength; i++) {
397 sValue << this->at(g*(this->geneLength)+i)->primitive_->getName() << " ";
398 }
399 xGene.addText(sValue.str().c_str());
400 xGEPChromosome.addChild(xGene);
401 }
402 // print homeotic gene
403 sValue.str("");
404 XMLNode xCell = XMLNode::createXMLTopNode("Cell");
405 uint cellOffset = this->genes * this->geneLength;
406 for (uint i = 0; i < this->linkHeadLength + this->linkTailLength; i++) {
407 sValue << this->at(cellOffset + i)->primitive_->getName() << " ";
408 }
409 xCell.addText(sValue.str().c_str());
410 xGEPChromosome.addChild(xCell);
411 }
412
413 // read from XMLNode
414 // mandatory if running parallel ECF or reading population from a milestone file
415 void GEPChromosome::read(XMLNode& xGEPChromosome)
416 {
417 this->clear();
418 //this->primitiveSet_ = static_cast<Tree::PrimitiveSetP> (new Tree::PrimitiveSet);
419 //this->primitiveSet_->initialize(state_);
420 XMLCSTR genesStr = xGEPChromosome.getAttribute("genes");
421 uint size = str2uint(genesStr);
422
423 XMLCSTR hlenStr = xGEPChromosome.getAttribute("headLength");
424 uint headlen = str2uint(hlenStr);
425
426 XMLCSTR tlenStr = xGEPChromosome.getAttribute("linkLength");
427 uint linklen = str2uint(tlenStr);
428 // loop over genes
429 for (uint i = 0; i <= size; i++){
430 XMLNode xGene = xGEPChromosome.getChildNode(i);
431 XMLCSTR tree = xGene.getText();
432 std::stringstream stream;
433 stream << tree;
434
435 if (i < size){
436 std::vector<Tree::PrimitiveP>& primitives = primitiveSet_->primitives_;
437 std::string primitiveStr;
438 uint position = 0;
439
440 for (uint iNode = 0; iNode < this->geneLength; iNode++) {
441 stream >> primitiveStr;
442 Tree::Node* node = new Tree::Node();
443
444 // 'regular' primitives
445 Tree::PrimitiveP prim = primitiveSet_->getPrimitiveByName(primitiveStr);
446 if (prim != Tree::PrimitiveP()) {
447 node->setPrimitive(prim);
448 this->push_back(static_cast<Tree::NodeP>(node));
449 continue;
450 }
451 // ERCs
452 // (TODO: include user defined ERC types)
453 Tree::PrimitiveP erc;
454 std::string prefix = primitiveStr.substr(0, 2);
455 std::string value = primitiveStr.substr(2);
456 std::stringstream ss;
457 ss << value;
458 if (prefix == DBL_PREFIX) {
459 erc = (Tree::PrimitiveP)(new Tree::Primitives::ERCD);
460 double v;
461 ss >> v;
462 erc->setValue(&v);
463 }
464 else if (prefix == INT_PREFIX) {
465 erc = (Tree::PrimitiveP)(new Tree::Primitives::ERC<int>);
466 int v;
467 ss >> v;
468 erc->setValue(&v);
469 }
470 else if (prefix == BOOL_PREFIX) {
471 erc = (Tree::PrimitiveP)(new Tree::Primitives::ERC<bool>);
472 bool v;
473 ss >> v;
474 erc->setValue(&v);
475 }
476 else if (prefix == CHR_PREFIX) {
477 erc = (Tree::PrimitiveP)(new Tree::Primitives::ERC<char>);
478 char v;
479 ss >> v;
480 erc->setValue(&v);
481 }
482 else if (prefix == STR_PREFIX) {
483 erc = (Tree::PrimitiveP)(new Tree::Primitives::ERC<std::string>);
484 std::string v;
485 ss >> v;
486 erc->setValue(&v);
487 }
488 else {
489 ECF_LOG_ERROR(state_, "GEPChromosome genotype: undefined primitive (" + primitiveStr + ")!");
490 throw("");
491 }
492 erc->setName(primitiveStr);
493 node->primitive_ = erc;
494 this->push_back(static_cast<Tree::NodeP>(node));
495 }
496 }
497 else{ // Deal with the "Cell" gene
498 std::vector<Tree::PrimitiveP>& primitives = linkFunctionSet_->primitives_;
499 std::string primitiveStr;
500 uint position = 0;
501
502 for (uint iNode = 0; iNode < this->linkHeadLength+this->linkTailLength; iNode++) {
503 stream >> primitiveStr;
504 Tree::Node* node = new Tree::Node();
505 // 'regular' primitives
506 Tree::PrimitiveP prim = linkFunctionSet_->getPrimitiveByName(primitiveStr);
507 if (prim != Tree::PrimitiveP()) { // if it is a linking function
508 node->setPrimitive(prim);
509 this->push_back(static_cast<Tree::NodeP>(node));
510 continue;
511 }
512 else{
513 ECF_LOG_ERROR(state_, "GEPChromosome genotype: undefined primitive (" + primitiveStr + ") for the Cell gene!");
514 throw("");
515 }
516 }
517 }
518 }
519 }
520
521 Tree::Tree* GEPChromosome::toTree(uint gene){
522 ECF_LOG(this->state_, 5, "Performing GEP -> Tree conversion...");
523
524 Tree::Tree* tree = new Tree::Tree();
525 // Copy primitive set
526 tree->primitiveSet_ = this->primitiveSet_;
527
528 uint geneOffset = gene*(this->geneLength);
529 uint ercIdx = geneOffset + this->headLength + this->tailLength;
530 uint ercCount = 0;
531 // Get root node arity
532 //geneOffset = 0;
533 uint i = geneOffset;
534 uint nArgs = this->at(i++)->primitive_->getNumberOfArguments();
535 // Get tree level indices
536 std::vector<uint> idx;
537 int level = 0;
538 uint nextLevelStart = 1 + geneOffset;
539 idx.push_back(geneOffset);
540 while (nArgs > 0){
541 uint lvlArity = 0;
542 idx.push_back(nextLevelStart);
543 for (uint j = 0; j < nArgs; j++){
544 lvlArity += this->at(nextLevelStart++)->primitive_->getNumberOfArguments();
545 }
546 nArgs = lvlArity;
547 }
548 //Read the gene and annotate the locations of the constants (needed later)
549 std::vector<int> constants(this->size(), -99999);
550 if (this->dcLength > 0){
551 for (uint c = geneOffset; c < geneOffset + this->headLength + this->tailLength; c++){
552 if (this->at(c)->primitive_->getName() == "?"){
553 constants[c] = ercCount++;
554 }
555 }
556 }
557 // Translate expression
558 // Helper array to store the per-level arguments needed
559 std::vector<uint> args(idx.size(), 0);
560 // Iterate while root node hasn't completed
561 std::vector<bool> visited(this->size(), false);
562 while (idx.at(0) == geneOffset){
563 // Read and this node to GP expression, if it hasn't been visited yet
564 if (!visited.at(idx.at(level))){
565 Tree::NodeP GEPnode = static_cast<Tree::NodeP> (new Tree::Node(this->at(idx.at(level))));
566 // If it is an ERC placeholder, replace with the next ERC
567 if (GEPnode->primitive_->getName() == "?"){
568 GEPnode = static_cast<Tree::NodeP> (new Tree::Node(this->at(ercIdx+constants.at(idx.at(level)))));
569 }
570 args[level] = GEPnode->primitive_->getNumberOfArguments();
571 // Push node into Tree representation
572 Tree::NodeP node = static_cast<Tree::NodeP> (new Tree::Node(GEPnode));
573 tree->addNode(node);
574 visited.at(idx.at(level)) = true;
575 }
576 // If operator still needs children, go down one level and read the necessary arguments
577 if (args.at(level) > 0){
578 level++;
579 }
580 // If it is a terminal or a satisfied operator, go up one level and increase reading index
581 else{
582 idx[level]++;
583 level--;
584 // Decrease needed arguments
585 if (level >= 0) args[level]--;
586 }
587 }
588 // Update the size and depth of each tree node
589 tree->update();
590 // Print tree
591 XMLNode xInd;
592 tree->write(xInd);
593 char *s = xInd.createXMLString();
594 ECF_LOG(this->state_, 5, "Tree conversion result: \n" + std::string(s));
595 freeXMLString(s);
596 return tree;
597 }
598
599 Tree::Tree* GEPChromosome::makeCellTree(){
600 ECF_LOG(this->state_, 5, "Performing GEP -> Tree conversion at the cell level...");
601
602 Tree::Tree* tree = new Tree::Tree();
603 // Copy primitive set
604 tree->primitiveSet_ = this->linkFunctionSet_;
605
606 uint geneOffset = this->genes*(this->geneLength);
607 // Get root node arity
608 uint i = geneOffset;
609 uint nArgs = this->at(i++)->primitive_->getNumberOfArguments();
610 // Get tree level indices
611 std::vector<uint> idx;
612 int level = 0;
613 uint nextLevelStart = 1 + geneOffset;
614 idx.push_back(geneOffset);
615 while (nArgs > 0){
616 uint lvlArity = 0;
617 idx.push_back(nextLevelStart);
618 for (uint j = 0; j < nArgs; j++){
619 lvlArity += this->at(nextLevelStart++)->primitive_->getNumberOfArguments();
620 }
621 nArgs = lvlArity;
622 }
623 // Translate expression
624 // Helper array to store the per-level arguments needed
625 std::vector<uint> args(idx.size(), 0);
626 // Iterate while root node hasn't completed
627 std::vector<bool> visited(this->size(), false);
628 while (idx.at(0) == geneOffset){
629 // Read and this node to GP expression, if it hasn't been visited yet
630 if (!visited.at(idx.at(level))){
631 Tree::NodeP GEPnode = static_cast<Tree::NodeP> (new Tree::Node(this->at(idx.at(level))));
632 args[level] = GEPnode->primitive_->getNumberOfArguments();
633 // Push node into Tree representation
634 Tree::NodeP node = static_cast<Tree::NodeP> (new Tree::Node(GEPnode));
635 tree->addNode(node);
636 visited.at(idx.at(level)) = true;
637 }
638 // If operator still needs children, go down one level and read the necessary arguments
639 if (args.at(level) > 0){
640 level++;
641 }
642 // If it is a terminal or a satisfied operator, go up one level and increase reading index
643 else{
644 idx[level]++;
645 level--;
646 // Decrease needed arguments
647 if (level >= 0) args[level]--;
648 }
649 }
650 // Update the size and depth of each tree node
651 tree->update();
652 // Print tree
653 XMLNode xInd;
654 tree->write(xInd);
655 char *s = xInd.createXMLString();
656 ECF_LOG(this->state_, 5, "Tree conversion result: \n" + std::string(s));
657 freeXMLString(s);
658 return tree;
659 }
660 void GEPChromosome::assemble(){
661 this->subtrees.clear();
662 this->cellTree = this->makeCellTree();
663 for (uint i = 0; i < this->genes; i++){
664 Tree::Tree *subtree = this->toTree(i);
665 this->subtrees.push_back(subtree);
666 }
667 }
668
669 void GEPChromosome::execute(void *result){
670 // Obtain the cell tree structure
671 //Tree::Tree *tree = this->cellTree();
672 // Translate and execute all the gene subtrees
673 // TODO: detect which genes are actually used so as to not evaluate unneeded ones
674 double tmp = 0;
675 for (uint i = 0; i < this->genes; i++){
676 Tree::Tree *subtree = this->subtrees.at(i);
677 subtree->execute(&tmp);
678 // Set the terminal values according to the subtrees
679 this->cellTree->setTerminalValue(GEP_GENE_PREFIX + uint2str(i), &tmp);
680 }
681 // Finally, translate the cell tree and store the result
682 this->cellTree->execute(result);
683 }
684
691 void GEPChromosome::setTerminalValue(std::string name, void* value)
692 {
693 Tree::PrimitiveP term = primitiveSet_->getTerminalByName(name);
694 if (term == Tree::PrimitiveP()) {
695 ECF_LOG_ERROR(state_, "GEPChromosome genotype: invalid terminal name referenced in setTerminalValue()!");
696 throw("");
697 }
698
699 term->setValue(value);
700 }
701}
702
GEPChromosome genotype: gene crx operator. Selects a gene number and swaps it between both parents.
GEPChromosome genotype: one point crx operator. Selects a crossing point from which to exchange genet...
GEPChromosome genotype: two point crx operator. Selects two crossing points between which to exchange...
GEPChromosome class - implements genotype as a Gene Expression Programming chromosome.
Definition: GEPChromosome.h:33
GEPChromosome genotype: standard normal distribution noise mutation operator. Applicable only on ephe...
GEPChromosome genotype: node replacement mutation operator. Tries to replace the selected primitive w...
std::string name_
genotype's name
Definition: Genotype.h:109
Node base class (Tree genotype)
Definition: Node.h:20
Primitive set class: collects all Tree Primitives.
Definition: PrimitiveSet.h:18
Ephemereal random constant (ERC) node of type double (Tree genotype).
Definition: Terminal.h:189
Ephemereal random constant (ERC) node class (Tree genotype).
Definition: Terminal.h:86
Terminal tree node class (Tree genotype).
Definition: Terminal.h:16
Tree class - implements genotype as a tree.
Definition: Tree_c.h:29
void write(XMLNode &)
Write genotype data to XMLNode.
Definition: Tree.cpp:535
void update()
Calculate depth and subtree sizes of each node in the tree.
Definition: Tree.cpp:435
void execute(void *)
Execute current tree.
Definition: Tree.cpp:362
Definition: nodes.h:92