• Main Page
  • Classes
  • Files
  • File List

D:/Radagast_D/Projekt/ECF_trunk/ECF/tree/Tree.cpp

00001 #include "../ECF_base.h"
00002 #include "Tree.h"
00003 #include <iostream>
00004 #include <sstream>
00005 #include <cmath>
00006 #include <sstream>
00007 
00008 // operators
00009 #include "TreeMutPermutation.h"
00010 #include "TreeMutGauss.h"
00011 #include "TreeMutNodeReplace.h"
00012 #include "TreeMutNodeComplement.h"
00013 #include "TreeMutHoist.h"
00014 #include "TreeMutShrink.h"
00015 #include "TreeMutSubtree.h"
00016 #include "TreeCrxSimple.h"
00017 #include "TreeCrxUniform.h"
00018 #include "TreeCrxContextPreserved.h"
00019 #include "TreeCrxSizeFair.h"
00020 #include "TreeCrxOnePoint.h"
00021 
00022 
00023 namespace Tree
00024 {
00025 
00026 Tree::Tree(void)
00027 {
00028     name_ = "Tree";
00029     startDepth_ = 0;
00030 }
00031 
00032 
00033 Tree::~Tree(void)
00034 {   }
00035 
00036 
00037 Tree* Tree::copy()
00038 {
00039     Tree *newObject = new Tree(*this);
00040 
00041     // create new nodes, copy primitives if necessary
00042     for(int i = 0; i < (int) this->size(); i++) {
00043         (*newObject)[i] = (NodeP) (new Node((*this)[i]));
00044     }
00045     return newObject;
00046 }
00047 
00048 
00049 std::vector<CrossoverOpP> Tree::getCrossoverOp()
00050 {
00051     std::vector<CrossoverOpP> crx;
00052     crx.push_back((CrossoverOpP) (new TreeCrxSimple));
00053     crx.push_back((CrossoverOpP) (new TreeCrxContextPreserved));
00054     crx.push_back((CrossoverOpP) (new TreeCrxUniform));
00055     crx.push_back((CrossoverOpP) (new TreeCrxSizeFair));
00056     crx.push_back((CrossoverOpP) (new TreeCrxOnePoint));
00057     return crx;
00058 }
00059 
00060 
00061 std::vector<MutationOpP> Tree::getMutationOp()
00062 {
00063     std::vector<MutationOpP> mut;
00064     mut.push_back((MutationOpP) (new TreeMutPermutation));
00065     mut.push_back((MutationOpP) (new TreeMutGauss));
00066     mut.push_back((MutationOpP) (new TreeMutNodeReplace));
00067     mut.push_back((MutationOpP) (new TreeMutNodeComplement));
00068     mut.push_back((MutationOpP) (new TreeMutHoist));
00069     mut.push_back((MutationOpP) (new TreeMutShrink));
00070     mut.push_back((MutationOpP) (new TreeMutSubtree));
00071     
00072     return mut;
00073 }
00074 
00075 
00081 bool Tree::addFunction(PrimitiveP func)
00082 {
00083     userFunctions_.push_back(func);
00084     return true;
00085 }
00086 
00087 
00093 bool Tree::addTerminal(PrimitiveP term)
00094 {
00095     userTerminals_.push_back(term);
00096     return true;
00097 }
00098 
00099 
00100 void Tree::registerParameters(StateP state)
00101 {
00102     registerParameter(state, "maxdepth", (voidP) (new uint(5)), ECF::UINT);
00103     registerParameter(state, "mindepth", (voidP) (new uint(1)), ECF::UINT);
00104     registerParameter(state, "initmaxdepth", (voidP) (new uint(5)), ECF::UINT);
00105     registerParameter(state, "initmindepth", (voidP) (new uint(1)), ECF::UINT);
00106     registerParameter(state, "functionset", (voidP) (new std::string), ECF::STRING);
00107     registerParameter(state, "terminalset", (voidP) (new std::string), ECF::STRING);
00108 }
00109 
00110 
00111 bool Tree::initialize(StateP state)
00112 {
00113     Tree* hometree = (Tree*) state->getGenotypes()[genotypeId_].get();
00114     state_ = state;
00115 
00116     // if we are the first one to initialize
00117     if(!hometree->primitiveSet_) 
00118         initializeFirst(hometree);
00119 
00120     // read from hometree
00121     this->primitiveSet_ = hometree->primitiveSet_;
00122     initMaxDepth_ = hometree->initMaxDepth_;
00123     initMinDepth_ = hometree->initMinDepth_;
00124     maxDepth_ = hometree->maxDepth_;
00125     minDepth_ = hometree->minDepth_;
00126 
00127     if(state->getRandomizer()->getRandomInteger(0, 1) % 2 == 0)
00128         fullBuild(primitiveSet_);
00129     else
00130         growBuild(primitiveSet_);
00131 
00132     return true;
00133 }
00134 
00135 
00140 void Tree::initializeFirst(Tree* hometree)
00141 {
00142     hometree->primitiveSet_ = (PrimitiveSetP) (new PrimitiveSet);
00143     hometree->primitiveSet_->initialize(state_);
00144     this->primitiveSet_ = hometree->primitiveSet_;
00145 
00146     // add user defined functions to primitiveSet
00147     for(int i = 0; i < (int) userFunctions_.size(); i++) {
00148         primitiveSet_->mPrimitives_[userFunctions_[i]->getName()] = userFunctions_[i];
00149     }
00150 
00151     voidP sptr = getParameterValue(state_, "functionset");
00152     std::stringstream names;
00153     std::string name;
00154     names << *((std::string*) sptr.get());
00155     while(names >> name) {
00156         if(!primitiveSet_->addFunction(name)) {
00157             state_->getLogger()->log(1, "Error: unknown function in function set (\'" + name + "\')!");
00158             throw("");
00159         }
00160     }
00161     if(primitiveSet_->getFunctionSetSize() == 0) {
00162         state_->getLogger()->log(1, "Tree genotype: empty function set!");
00163         throw("");
00164     }
00165 
00166     Primitives::terminal_type currentType = Primitives::Double;
00167     type_iter typeIter;
00168 
00169     std::stringstream tNames;
00170     sptr = getParameterValue(state_, "terminalset");
00171     tNames << *((std::string*) sptr.get());
00172 
00173     while(tNames >> name)
00174     {
00175         // read current terminal type (if set)
00176         typeIter = primitiveSet_->mTypeNames_.find(name);
00177         if(typeIter != primitiveSet_->mTypeNames_.end()) {
00178             currentType = typeIter->second;
00179             continue;
00180         }
00181 
00182         // see if it's a user-defined terminal 
00183         uint iTerminal = 0;
00184         for(; iTerminal < userTerminals_.size(); iTerminal++)
00185             if(userTerminals_[iTerminal]->getName() == name)
00186                 break;
00187         if(iTerminal < userTerminals_.size()) {
00188             primitiveSet_->addTerminal(userTerminals_[iTerminal]);
00189             continue;
00190         }
00191 
00192 
00193         // read ERC definition (if set)
00194         if(name[0] == '[' || name[0] == '{') {
00195 
00196             std::string ercValues = "";
00197 
00198             PrimitiveP erc;
00199             switch(currentType) {
00200                 case Primitives::Double:
00201                     erc = (PrimitiveP) (new Primitives::ERCD); 
00202                     ercValues = DBL_PREFIX;
00203                     break;
00204                 case Primitives::Int:
00205                     erc = (PrimitiveP) (new Primitives::ERC<int>); 
00206                     ercValues = INT_PREFIX;
00207                     break;
00208                 case Primitives::Bool:
00209                     erc = (PrimitiveP) (new Primitives::ERC<bool>); 
00210                     ercValues = BOOL_PREFIX;
00211                     break;
00212                 case Primitives::Char:
00213                     erc = (PrimitiveP) (new Primitives::ERC<char>); 
00214                     ercValues = CHR_PREFIX;
00215                     break;
00216                 case Primitives::String:
00217                     erc = (PrimitiveP) (new Primitives::ERC<std::string>); 
00218                     ercValues = STR_PREFIX;
00219                     break;
00220             }
00221 
00222             while(name[name.size() - 1] != ']' && name[name.size() - 1] != '}') {
00223                 ercValues += " " + name;
00224                 tNames >> name;
00225             }
00226             ercValues += " " + name;
00227 
00228             // ERC ocekuje "D_ [<value> <value> ...]" kao ime prije initialize()
00229             erc->setName(ercValues);
00230             erc->initialize(state_);
00231             primitiveSet_->addTerminal(erc);
00232 
00233             continue;
00234         } 
00235 
00236 
00237         // otherwise, read terminal of current type
00238         PrimitiveP terminal;
00239         switch(currentType)
00240         {
00241             case Primitives::Double:
00242                 terminal = (PrimitiveP) (new Primitives::Terminal); break;
00243             case Primitives::Int:
00244                 terminal = (PrimitiveP) (new Primitives::TerminalT<int>); break;
00245             case Primitives::Bool:
00246                 terminal = (PrimitiveP) (new Primitives::TerminalT<bool>); break;
00247             case Primitives::Char:
00248                 terminal = (PrimitiveP) (new Primitives::TerminalT<char>); break;
00249             case Primitives::String:
00250                 terminal = (PrimitiveP) (new Primitives::TerminalT<std::string>); break;
00251         }
00252 
00253         // ako se 'name' moze prevesti u value tipa currentType
00254         // onda je to konstantni terminal istoga imena i iste vrijednosti
00255         // inace, obicni terminal zadanog imena
00256         std::istringstream ss(name);
00257         switch(currentType)
00258         {
00259             case Primitives::Double:
00260                 double dblValue;
00261                 ss >> dblValue;
00262                 if(ss.fail() == false) 
00263                     terminal->setValue(&dblValue);
00264                 break;
00265             case Primitives::Int:
00266                 int intValue;
00267                 ss >> intValue;
00268                 if(ss.fail() == false) 
00269                     terminal->setValue(&intValue);
00270                 break;
00271             case Primitives::Bool:
00272                 bool boolValue;
00273                 ss >> boolValue;
00274                 if(name == "true")
00275                     boolValue = true;
00276                 else if(name == "false")
00277                     boolValue = false;
00278                 if(ss.fail() == false || name == "true" || name == "false") {
00279                     if(boolValue)
00280                         name = "true";
00281                     else
00282                         name = "false";
00283                     terminal->setValue(&boolValue);
00284                 }
00285                 break;
00286             case Primitives::Char:
00287                 char charValue;
00288                 ss >> charValue;
00289                 if(ss.fail() == false) 
00290                     terminal->setValue(&charValue);
00291                 break;
00292             case Primitives::String:
00293                 std::string stringValue;
00294                 ss >> stringValue;
00295                 if(ss.fail() == false) 
00296                     terminal->setValue(&stringValue);
00297                 break;
00298         }
00299         terminal->setName(name);
00300         primitiveSet_->addTerminal(terminal);
00301         
00302     }
00303 
00304 
00305     if(primitiveSet_->getTerminalSetSize() == 0) {
00306         state_->getLogger()->log(1, "Tree: Empty terminal set!");
00307         throw("");
00308     }
00309 
00310     // read tree depth constraints, store in hometree
00311     sptr = getParameterValue(state_, "maxdepth");
00312     hometree->maxDepth_ = *((uint*) sptr.get());
00313     sptr = getParameterValue(state_, "mindepth");
00314     hometree->minDepth_ = *((uint*) sptr.get());
00315     if(hometree->maxDepth_ < hometree->minDepth_ || hometree->maxDepth_ < 1) {
00316         state_->getLogger()->log(1, "Tree genotype: invalid values for max and min tree depth!");
00317         throw("");
00318     }
00319 
00320     hometree->initMaxDepth_ = hometree->maxDepth_;
00321     if(isParameterDefined(state_, "initmaxdepth")) {
00322         sptr = getParameterValue(state_, "initmaxdepth");
00323         hometree->initMaxDepth_ = *((uint*) sptr.get());
00324     }
00325     hometree->initMinDepth_ = hometree->minDepth_;
00326     if(isParameterDefined(state_, "initmindepth")) {
00327         sptr = getParameterValue(state_, "initmindepth");
00328         hometree->initMinDepth_ = *((uint*) sptr.get());
00329     }
00330     if(hometree->initMaxDepth_ < hometree->initMinDepth_ || hometree->initMaxDepth_ < 1) {
00331         state_->getLogger()->log(1, "Tree genotype: invalid values for initial max and min tree depth!");
00332         throw("");
00333     }
00334     if(hometree->initMaxDepth_ > hometree->maxDepth_) {
00335         state_->getLogger()->log(1, "Tree genotype: initial max depth cannot be greater than evolution max depth!");
00336         throw("");
00337     }
00338 }
00339 
00340 
00347 void Tree::execute(void *result)
00348 {
00349     iNode_ = 0;
00350     this->at(iNode_)->primitive_->execute(result, *this);
00351 }
00352 
00353 
00354 void Tree::addNode(Node *node)
00355 {
00356     this->push_back(static_cast<NodeP> (node));
00357 }
00358 
00359 
00360 void Tree::addNode(NodeP node)
00361 {
00362     this->push_back(node);
00363 }
00364 
00365 
00366 uint Tree::fullBuild(PrimitiveSetP primitiveSet, int myDepth)
00367 {
00368     Node* node = new Node();
00369     node->depth_ = myDepth;
00370 
00371     if(node->depth_ < this->initMaxDepth_) {
00372         node->setPrimitive(primitiveSet->getRandomFunction());
00373         this->addNode(node);
00374     } else {
00375         node->setPrimitive(primitiveSet->getRandomTerminal());
00376         this->addNode(node);
00377     }
00378 
00379     for(int i = 0; i < node->primitive_->getNumberOfArguments(); i++ ) {
00380         node->size_ += fullBuild(primitiveSet, myDepth + 1);
00381     }
00382 
00383     return node->size_;
00384 }
00385 
00386 
00387 uint Tree::growBuild(PrimitiveSetP primitiveSet, int myDepth)
00388 {
00389     Node* node = new Node();
00390     node->depth_ = myDepth;
00391 
00392     if(node->depth_ < this->initMinDepth_) {
00393         node->setPrimitive(primitiveSet->getRandomFunction());
00394         this->addNode(node);
00395     }
00396     else if(node->depth_ < this->initMaxDepth_) {
00397         node->setPrimitive(primitiveSet->getRandomPrimitive());
00398         this->addNode(node);
00399     }
00400     else {
00401         node->setPrimitive(primitiveSet->getRandomTerminal());
00402         this->addNode(node);
00403     }
00404     
00405     for(int i = 0; i < node->primitive_->getNumberOfArguments(); i++) {
00406         node->size_ += growBuild(primitiveSet, myDepth + 1);
00407     }
00408 
00409     return node->size_;
00410 }
00411 
00412 
00418 void Tree::update()
00419 {
00420     this->at(0)->size_ = setSize(0);
00421 
00422     iNode_ = 0;
00423     for(int i = 0; i < this->at(0)->primitive_->getNumberOfArguments(); i++) {
00424         iNode_++;
00425         setDepth(startDepth_ + 1);
00426     }
00427     this->at(0)->depth_ = startDepth_;
00428 }
00429 
00430 
00434 uint Tree::setSize(int iNode)
00435 {
00436     int myNode = iNode;
00437     int mySize = 1;
00438     for(int i = 0; i < this->at(myNode)->primitive_->getNumberOfArguments(); i++) {
00439         int childSize = setSize(iNode + 1);
00440         mySize += childSize;
00441         iNode += childSize;
00442     }
00443     this->at(myNode)->size_ = mySize;
00444     return mySize;
00445 }
00446 
00447 
00451 void Tree::setDepth(int myDepth)
00452 {
00453     int index = iNode_;
00454     int nArgs = this->at( iNode_ )->primitive_->getNumberOfArguments();
00455     for(int i = 0; i < nArgs; i++) {
00456         iNode_++;
00457         setDepth( myDepth + 1);
00458     }
00459     this->at(index)->depth_ = myDepth;
00460 }
00461 
00462 
00466 void Tree::growBuild(PrimitiveSetP primitiveSet)
00467 {
00468     growBuild(primitiveSet, startDepth_);
00469 }
00470 
00471 
00475 void Tree::fullBuild(PrimitiveSetP primitiveSet)
00476 {
00477     fullBuild(primitiveSet, startDepth_);
00478 }
00479 
00480 
00487 void Tree::setTerminalValue(std::string name, void* value)
00488 {
00489     uint termIndex;
00490     for(termIndex = 0; termIndex < primitiveSet_->terminalSet_.size(); termIndex++) {
00491         if(name == primitiveSet_->terminalSet_.at(termIndex)->getName()) {
00492             break;
00493         }
00494     }
00495 
00496     if(termIndex == primitiveSet_->terminalSet_.size()) {
00497         state_->getLogger()->log(1, "Tree genotype: invalid terminal name referenced in setTerminalValue()!");
00498         throw("");
00499     }
00500 
00501     primitiveSet_->terminalSet_.at(termIndex)->setValue(value);
00502 }
00503 
00504 
00505 void Tree::write(XMLNode& xTree)
00506 {
00507     xTree = XMLNode::createXMLTopNode("Tree");
00508     std::stringstream sValue;
00509     sValue << this->size();
00510     xTree.addAttribute("size", sValue.str().c_str());
00511     
00512     sValue.str("");
00513     for(uint i = 0; i < this->size(); i++) {
00514         sValue << this->at(i)->primitive_->getName() << " ";
00515     }
00516     xTree.addText(sValue.str().c_str());
00517 }
00518 
00519 
00520 void Tree::read(XMLNode& xTree)
00521 {
00522     this->clear();
00523 
00524     XMLCSTR sizeStr = xTree.getAttribute("size");
00525     uint size = str2uint(sizeStr);
00526 
00527     XMLCSTR tree = xTree.getText();
00528     std::stringstream stream;
00529     stream << tree;
00530 
00531     std::vector<PrimitiveP>& primitives = primitiveSet_->primitives_;
00532     std::string primitiveStr;
00533     uint position = 0;
00534 
00535     for(uint iNode = 0; iNode < size; iNode++) {
00536         stream >> primitiveStr;
00537         Node* node = new Node();
00538         uint iPrim;
00539 
00540         // 'regular' primitives
00541         for(iPrim = 0; iPrim < primitiveSet_->primitives_.size(); iPrim++)
00542             if(primitives[iPrim]->getName() == primitiveStr) {
00543                 node->setPrimitive(primitives[iPrim]);
00544                 this->addNode(node);
00545                 break;
00546             }
00547         if(iPrim != primitiveSet_->primitives_.size())
00548             continue;
00549 
00550         // ERCs
00551         // (TODO: include user defined ERC types)
00552         PrimitiveP erc;
00553         std::string prefix = primitiveStr.substr(0, 2);
00554         std::string value = primitiveStr.substr(2);
00555         std::stringstream ss;
00556         ss << value;
00557         if(prefix == DBL_PREFIX) {
00558             erc = (PrimitiveP) (new Primitives::ERCD);
00559             double v;
00560             ss >> v;
00561             erc->setValue(&v);
00562         }
00563         else if(prefix == INT_PREFIX) {
00564             erc = (PrimitiveP) (new Primitives::ERC<int>);
00565             int v;
00566             ss >> v;
00567             erc->setValue(&v);
00568         }
00569         else if(prefix == INT_PREFIX) {
00570             erc = (PrimitiveP) (new Primitives::ERC<int>);
00571             int v;
00572             ss >> v;
00573             erc->setValue(&v);
00574         }
00575         else if(prefix == BOOL_PREFIX) {
00576             erc = (PrimitiveP) (new Primitives::ERC<bool>);
00577             bool v;
00578             ss >> v;
00579             erc->setValue(&v);
00580         }
00581         else if(prefix == CHR_PREFIX) {
00582             erc = (PrimitiveP) (new Primitives::ERC<char>);
00583             char v;
00584             ss >> v;
00585             erc->setValue(&v);
00586         }
00587         else if(prefix == STR_PREFIX) {
00588             erc = (PrimitiveP) (new Primitives::ERC<std::string>);
00589             std::string v;
00590             ss >> v;
00591             erc->setValue(&v);
00592         }
00593         else {
00594             state_->getLogger()->log(1, "Tree genotype: undefined primitive (" + primitiveStr + ")!");
00595             throw("");
00596         }
00597         erc->setName(primitiveStr);
00598         node->primitive_ = erc;
00599         this->addNode(node);
00600     }
00601 
00602     // set node depths and sizes
00603     this->update();
00604 }
00605 
00606 }

Generated on Wed Sep 1 2010 14:31:21 for ECF by  doxygen 1.7.1