• Main Page
  • Modules
  • Classes
  • Files
  • File List

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 
00080 bool Tree::addFunction(PrimitiveP func)
00081 {
00082     userFunctions_.push_back(func);
00083     return true;
00084 }
00085 
00086 
00091 bool Tree::addTerminal(PrimitiveP term)
00092 {
00093     userTerminals_.push_back(term);
00094     return true;
00095 }
00096 
00097 
00098 void Tree::registerParameters(StateP state)
00099 {
00100     registerParameter(state, "maxdepth", (voidP) (new uint(5)), ECF::UINT);
00101     registerParameter(state, "mindepth", (voidP) (new uint(1)), ECF::UINT);
00102     registerParameter(state, "initmaxdepth", (voidP) (new uint(5)), ECF::UINT);
00103     registerParameter(state, "initmindepth", (voidP) (new uint(1)), ECF::UINT);
00104     registerParameter(state, "functionset", (voidP) (new std::string), ECF::STRING);
00105     registerParameter(state, "terminalset", (voidP) (new std::string), ECF::STRING);
00106 }
00107 
00108 
00109 bool Tree::initialize(StateP state)
00110 {
00111     // 'hometree' is a Tree instance kept in the State;
00112     // we use it to link the PrimitiveSet to it and store the parameters
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     // in any case, read parameters from 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     // build tree (TODO: reimplement for ramped-half-and-half)
00128     if(state->getRandomizer()->getRandomInteger(0, 1) % 2 == 0)
00129         fullBuild(primitiveSet_);
00130     else
00131         growBuild(primitiveSet_);
00132 
00133     return true;
00134 }
00135 
00136 
00143 void Tree::initializeFirst(Tree* hometree)
00144 {
00145     // create and link PrimitiveSet to the hometree
00146     hometree->primitiveSet_ = (PrimitiveSetP) (new PrimitiveSet);
00147     hometree->primitiveSet_->initialize(state_);
00148     this->primitiveSet_ = hometree->primitiveSet_;
00149 
00150     // add user defined functions to primitiveSet
00151     for(int i = 0; i < (int) userFunctions_.size(); i++) {
00152         primitiveSet_->mAllPrimitives_[userFunctions_[i]->getName()] = userFunctions_[i];
00153     }
00154 
00155     // read function set from the configuration
00156     voidP sptr = getParameterValue(state_, "functionset");
00157     std::stringstream names;
00158     std::string name;
00159     names << *((std::string*) sptr.get());
00160     while(names >> name) {
00161         if(!primitiveSet_->addFunction(name)) {
00162             ECF_LOG_ERROR(state_, "Error: unknown function in function set (\'" + name + "\')!");
00163             throw("");
00164         }
00165     }
00166     if(primitiveSet_->getFunctionSetSize() == 0) {
00167         ECF_LOG_ERROR(state_, "Tree genotype: empty function set!");
00168         throw("");
00169     }
00170 
00171     // set default terminal type
00172     Primitives::terminal_type currentType = Primitives::Double;
00173     type_iter typeIter;
00174 
00175     // read terminal set from the configuration
00176     std::stringstream tNames;
00177     sptr = getParameterValue(state_, "terminalset");
00178     tNames << *((std::string*) sptr.get());
00179 
00180     while(tNames >> name)
00181     {
00182         // read current terminal type (if set)
00183         typeIter = primitiveSet_->mTypeNames_.find(name);
00184         if(typeIter != primitiveSet_->mTypeNames_.end()) {
00185             currentType = typeIter->second;
00186             continue;
00187         }
00188 
00189         // see if it's a user-defined terminal 
00190         uint iTerminal = 0;
00191         for(; iTerminal < userTerminals_.size(); iTerminal++)
00192             if(userTerminals_[iTerminal]->getName() == name)
00193                 break;
00194         if(iTerminal < userTerminals_.size()) {
00195             primitiveSet_->addTerminal(userTerminals_[iTerminal]);
00196             continue;
00197         }
00198 
00199 
00200         // read ERC definition (if set)
00201         // ERC's are defined as interval [x y] or set {a b c}
00202         if(name[0] == '[' || name[0] == '{') {
00203 
00204             std::string ercValues = "";
00205 
00206             // name this ERC (ERC's name is its value!)
00207             PrimitiveP erc;
00208             switch(currentType) {
00209                 case Primitives::Double:
00210                     erc = (PrimitiveP) (new Primitives::ERCD); 
00211                     ercValues = DBL_PREFIX;
00212                     break;
00213                 case Primitives::Int:
00214                     erc = (PrimitiveP) (new Primitives::ERC<int>); 
00215                     ercValues = INT_PREFIX;
00216                     break;
00217                 case Primitives::Bool:
00218                     erc = (PrimitiveP) (new Primitives::ERC<bool>); 
00219                     ercValues = BOOL_PREFIX;
00220                     break;
00221                 case Primitives::Char:
00222                     erc = (PrimitiveP) (new Primitives::ERC<char>); 
00223                     ercValues = CHR_PREFIX;
00224                     break;
00225                 case Primitives::String:
00226                     erc = (PrimitiveP) (new Primitives::ERC<std::string>); 
00227                     ercValues = STR_PREFIX;
00228                     break;
00229             }
00230 
00231             while(name[name.size() - 1] != ']' && name[name.size() - 1] != '}') {
00232                 ercValues += " " + name;
00233                 tNames >> name;
00234             }
00235             ercValues += " " + name;
00236 
00237             // ERC ocekuje "D_ [<value> <value> ...]" kao ime prije initialize()
00238             erc->setName(ercValues);
00239             erc->initialize(state_);
00240             primitiveSet_->addTerminal(erc);
00241 
00242             continue;
00243         } 
00244 
00245 
00246         // otherwise, read terminal of current type
00247         PrimitiveP terminal;
00248         switch(currentType)
00249         {
00250             case Primitives::Double:
00251                 terminal = (PrimitiveP) (new Primitives::Terminal); break;
00252             case Primitives::Int:
00253                 terminal = (PrimitiveP) (new Primitives::TerminalT<int>); break;
00254             case Primitives::Bool:
00255                 terminal = (PrimitiveP) (new Primitives::TerminalT<bool>); break;
00256             case Primitives::Char:
00257                 terminal = (PrimitiveP) (new Primitives::TerminalT<char>); break;
00258             case Primitives::String:
00259                 terminal = (PrimitiveP) (new Primitives::TerminalT<std::string>); break;
00260         }
00261 
00262         // if the 'name' can be identified as a value of the 'currentType', then it's a _constant terminal_ (of that value)
00263         // otherwise, it's a regular terminal with 'name'
00264         std::istringstream ss(name);
00265         switch(currentType)
00266         {
00267             case Primitives::Double:
00268                 double dblValue;
00269                 ss >> dblValue;
00270                 if(ss.fail() == false) 
00271                     terminal->setValue(&dblValue);
00272                 break;
00273             case Primitives::Int:
00274                 int intValue;
00275                 ss >> intValue;
00276                 if(ss.fail() == false) 
00277                     terminal->setValue(&intValue);
00278                 break;
00279             case Primitives::Bool:
00280                 bool boolValue;
00281                 ss >> boolValue;
00282                 if(name == "true")
00283                     boolValue = true;
00284                 else if(name == "false")
00285                     boolValue = false;
00286                 if(ss.fail() == false || name == "true" || name == "false") {
00287                     if(boolValue)
00288                         name = "true";
00289                     else
00290                         name = "false";
00291                     terminal->setValue(&boolValue);
00292                 }
00293                 break;
00294             case Primitives::Char:
00295                 char charValue;
00296                 ss >> charValue;
00297                 if(ss.fail() == false) 
00298                     terminal->setValue(&charValue);
00299                 break;
00300             case Primitives::String:
00301                 std::string stringValue;
00302                 ss >> stringValue;
00303                 if(ss.fail() == false) 
00304                     terminal->setValue(&stringValue);
00305                 break;
00306         }
00307         terminal->setName(name);
00308         primitiveSet_->addTerminal(terminal);
00309         
00310     }
00311 
00312     if(primitiveSet_->getTerminalSetSize() == 0) {
00313         ECF_LOG_ERROR(state_, "Tree: Empty terminal set!");
00314         throw("");
00315     }
00316 
00317     // read tree depth constraints, store in hometree
00318     sptr = getParameterValue(state_, "maxdepth");
00319     hometree->maxDepth_ = *((uint*) sptr.get());
00320     sptr = getParameterValue(state_, "mindepth");
00321     hometree->minDepth_ = *((uint*) sptr.get());
00322     if(hometree->maxDepth_ < hometree->minDepth_ || hometree->maxDepth_ < 1) {
00323         ECF_LOG_ERROR(state_, "Tree genotype: invalid values for max and min tree depth!");
00324         throw("");
00325     }
00326 
00327     hometree->initMaxDepth_ = hometree->maxDepth_;
00328     if(isParameterDefined(state_, "initmaxdepth")) {
00329         sptr = getParameterValue(state_, "initmaxdepth");
00330         hometree->initMaxDepth_ = *((uint*) sptr.get());
00331     }
00332     hometree->initMinDepth_ = hometree->minDepth_;
00333     if(isParameterDefined(state_, "initmindepth")) {
00334         sptr = getParameterValue(state_, "initmindepth");
00335         hometree->initMinDepth_ = *((uint*) sptr.get());
00336     }
00337     if(hometree->initMaxDepth_ < hometree->initMinDepth_ || hometree->initMaxDepth_ < 1) {
00338         ECF_LOG_ERROR(state_, "Tree genotype: invalid values for initial max and min tree depth!");
00339         throw("");
00340     }
00341     if(hometree->initMaxDepth_ > hometree->maxDepth_) {
00342         ECF_LOG_ERROR(state_, "Tree genotype: initial max depth cannot be greater than evolution max depth!");
00343         throw("");
00344     }
00345 }
00346 
00347 
00354 void Tree::execute(void *result)
00355 {
00356     iNode_ = 0;
00357     this->at(iNode_)->primitive_->execute(result, *this);
00358 }
00359 
00360 
00361 void Tree::addNode(Node *node)
00362 {
00363     this->push_back(static_cast<NodeP> (node));
00364 }
00365 
00366 
00367 void Tree::addNode(NodeP node)
00368 {
00369     this->push_back(node);
00370 }
00371 
00372 
00374 uint Tree::fullBuild(PrimitiveSetP primitiveSet, int myDepth)
00375 {
00376     Node* node = new Node();
00377     node->depth_ = myDepth;
00378 
00379     if(node->depth_ < this->initMaxDepth_) {
00380         node->setPrimitive(primitiveSet->getRandomFunction());
00381         this->addNode(node);
00382     } else {
00383         node->setPrimitive(primitiveSet->getRandomTerminal());
00384         this->addNode(node);
00385     }
00386 
00387     for(int i = 0; i < node->primitive_->getNumberOfArguments(); i++ ) {
00388         node->size_ += fullBuild(primitiveSet, myDepth + 1);
00389     }
00390 
00391     return node->size_;
00392 }
00393 
00394 
00396 uint Tree::growBuild(PrimitiveSetP primitiveSet, int myDepth)
00397 {
00398     Node* node = new Node();
00399     node->depth_ = myDepth;
00400 
00401     if(node->depth_ < this->initMinDepth_) {
00402         node->setPrimitive(primitiveSet->getRandomFunction());
00403         this->addNode(node);
00404     }
00405     else if(node->depth_ < this->initMaxDepth_) {
00406         node->setPrimitive(primitiveSet->getRandomPrimitive());
00407         this->addNode(node);
00408     }
00409     else {
00410         node->setPrimitive(primitiveSet->getRandomTerminal());
00411         this->addNode(node);
00412     }
00413     
00414     for(int i = 0; i < node->primitive_->getNumberOfArguments(); i++) {
00415         node->size_ += growBuild(primitiveSet, myDepth + 1);
00416     }
00417 
00418     return node->size_;
00419 }
00420 
00421 
00427 void Tree::update()
00428 {
00429     this->at(0)->size_ = setSize(0);
00430 
00431     iNode_ = 0;
00432     for(int i = 0; i < this->at(0)->primitive_->getNumberOfArguments(); i++) {
00433         iNode_++;
00434         setDepth(startDepth_ + 1);
00435     }
00436     this->at(0)->depth_ = startDepth_;
00437 }
00438 
00439 
00443 uint Tree::setSize(int iNode)
00444 {
00445     int myNode = iNode;
00446     int mySize = 1;
00447     for(int i = 0; i < this->at(myNode)->primitive_->getNumberOfArguments(); i++) {
00448         int childSize = setSize(iNode + 1);
00449         mySize += childSize;
00450         iNode += childSize;
00451     }
00452     this->at(myNode)->size_ = mySize;
00453     return mySize;
00454 }
00455 
00456 
00460 void Tree::setDepth(int myDepth)
00461 {
00462     int index = iNode_;
00463     int nArgs = this->at( iNode_ )->primitive_->getNumberOfArguments();
00464     for(int i = 0; i < nArgs; i++) {
00465         iNode_++;
00466         setDepth(myDepth + 1);
00467     }
00468     this->at(index)->depth_ = myDepth;
00469 }
00470 
00471 
00475 void Tree::growBuild(PrimitiveSetP primitiveSet)
00476 {
00477     growBuild(primitiveSet, startDepth_);
00478 }
00479 
00480 
00484 void Tree::fullBuild(PrimitiveSetP primitiveSet)
00485 {
00486     fullBuild(primitiveSet, startDepth_);
00487 }
00488 
00489 
00496 void Tree::setTerminalValue(std::string name, void* value)
00497 {
00498     PrimitiveP term = primitiveSet_->getTerminalByName(name);
00499     if(term == PrimitiveP()) {
00500         ECF_LOG_ERROR(state_, "Tree genotype: invalid terminal name referenced in setTerminalValue()!");
00501         throw("");
00502     }
00503 
00504     term->setValue(value);
00505 }
00506 
00507 
00508 void Tree::write(XMLNode& xTree)
00509 {
00510     xTree = XMLNode::createXMLTopNode("Tree");
00511     std::stringstream sValue;
00512     sValue << this->size();
00513     xTree.addAttribute("size", sValue.str().c_str());
00514     
00515     sValue.str("");
00516     for(uint i = 0; i < this->size(); i++) {
00517         sValue << this->at(i)->primitive_->getName() << " ";
00518     }
00519     xTree.addText(sValue.str().c_str());
00520 }
00521 
00522 
00523 void Tree::read(XMLNode& xTree)
00524 {
00525     this->clear();
00526 
00527     XMLCSTR sizeStr = xTree.getAttribute("size");
00528     uint size = str2uint(sizeStr);
00529 
00530     XMLCSTR tree = xTree.getText();
00531     std::stringstream stream;
00532     stream << tree;
00533 
00534     std::vector<PrimitiveP>& primitives = primitiveSet_->primitives_;
00535     std::string primitiveStr;
00536     uint position = 0;
00537 
00538     for(uint iNode = 0; iNode < size; iNode++) {
00539         stream >> primitiveStr;
00540         Node* node = new Node();
00541 
00542         // 'regular' primitives
00543         PrimitiveP prim = primitiveSet_->getPrimitiveByName(primitiveStr);
00544         if(prim != PrimitiveP()) {
00545             node->setPrimitive(prim);
00546             this->addNode(node);
00547             continue;
00548         }
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             ECF_LOG_ERROR(state_, "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 Thu Oct 6 2011 13:41:01 for ECF by  doxygen 1.7.1