1#include "../ECF_base.h"
9#include "TreeMutPermutation.h"
10#include "TreeMutGauss.h"
11#include "TreeMutNodeReplace.h"
12#include "TreeMutNodeComplement.h"
13#include "TreeMutHoist.h"
14#include "TreeMutShrink.h"
15#include "TreeMutSubtree.h"
16#include "TreeCrxSimple.h"
17#include "TreeCrxUniform.h"
18#include "TreeCrxContextPreserved.h"
19#include "TreeCrxSizeFair.h"
20#include "TreeCrxOnePoint.h"
42 for(
int i = 0; i < (int) this->size(); i++) {
43 (*newObject)[i] = (NodeP) (
new Node((*
this)[i]));
49std::vector<CrossoverOpP> Tree::getCrossoverOp()
51 std::vector<CrossoverOpP> crx;
61std::vector<MutationOpP> Tree::getMutationOp()
63 std::vector<MutationOpP> mut;
80bool Tree::addFunction(PrimitiveP func)
82 userFunctions_.push_back(func);
91bool Tree::addTerminal(PrimitiveP term)
93 userTerminals_.push_back(term);
98void Tree::registerParameters(StateP state)
100 registerParameter(state,
"maxdepth", (voidP) (
new uint(5)), ECF::UINT,
101 "maximum tree depth (default: 5)");
102 registerParameter(state,
"mindepth", (voidP) (
new uint(1)), ECF::UINT,
103 "minimum tree depth (default: 1)");
104 registerParameter(state,
"initmaxdepth", (voidP) (
new uint(5)), ECF::UINT,
105 "maximum initial tree depth (default: 5)");
106 registerParameter(state,
"initmindepth", (voidP) (
new uint(1)), ECF::UINT,
107 "minimum initial tree depth (default: 1)");
108 registerParameter(state,
"functionset", (voidP) (
new std::string), ECF::STRING,
109 "set of functional tree elements (mandatory)");
110 registerParameter(state,
"terminalset", (voidP) (
new std::string), ECF::STRING,
111 "set of terminal tree elements (mandatory)");
115bool Tree::initialize(StateP state)
119 Tree* hometree = (
Tree*) state->getGenotypes()[genotypeId_].get();
123 if(!hometree->primitiveSet_)
124 initializeFirst(hometree);
127 this->primitiveSet_ = hometree->primitiveSet_;
128 initMaxDepth_ = hometree->initMaxDepth_;
129 initMinDepth_ = hometree->initMinDepth_;
130 maxDepth_ = hometree->maxDepth_;
131 minDepth_ = hometree->minDepth_;
134 if(state->getRandomizer()->getRandomInteger(0, 1) % 2 == 0)
135 fullBuild(primitiveSet_);
137 growBuild(primitiveSet_);
149void Tree::initializeFirst(
Tree* hometree)
152 hometree->primitiveSet_ = (PrimitiveSetP) (
new PrimitiveSet);
153 hometree->primitiveSet_->initialize(state_);
154 this->primitiveSet_ = hometree->primitiveSet_;
157 for(
int i = 0; i < (int) userFunctions_.size(); i++) {
158 primitiveSet_->mAllPrimitives_[userFunctions_[i]->getName()] = userFunctions_[i];
159 primitiveSet_->mAllPrimitives_[userFunctions_[i]->getName()]->initialize(state_);
163 voidP sptr = getParameterValue(state_,
"functionset");
164 std::stringstream names;
166 names << *((std::string*) sptr.get());
167 while(names >> name) {
168 if(!primitiveSet_->addFunction(name)) {
169 ECF_LOG_ERROR(state_,
"Error: unknown function in function set (\'" + name +
"\')!");
173 if(primitiveSet_->getFunctionSetSize() == 0) {
174 ECF_LOG_ERROR(state_,
"Tree genotype: empty function set!");
179 Primitives::terminal_type currentType = Primitives::Double;
183 std::stringstream tNames;
184 sptr = getParameterValue(state_,
"terminalset");
185 tNames << *((std::string*) sptr.get());
187 while(tNames >> name)
190 typeIter = primitiveSet_->mTypeNames_.find(name);
191 if(typeIter != primitiveSet_->mTypeNames_.end()) {
192 currentType = typeIter->second;
198 for(; iTerminal < userTerminals_.size(); iTerminal++)
199 if(userTerminals_[iTerminal]->getName() == name)
201 if(iTerminal < userTerminals_.size()) {
202 userTerminals_[iTerminal]->initialize(state_);
203 primitiveSet_->addTerminal(userTerminals_[iTerminal]);
210 if(name[0] ==
'[' || name[0] ==
'{') {
212 std::string ercValues =
"";
216 switch(currentType) {
217 case Primitives::Double:
219 ercValues = DBL_PREFIX;
221 case Primitives::Int:
223 ercValues = INT_PREFIX;
225 case Primitives::Bool:
227 ercValues = BOOL_PREFIX;
229 case Primitives::Char:
231 ercValues = CHR_PREFIX;
233 case Primitives::String:
235 ercValues = STR_PREFIX;
239 while(name[name.size() - 1] !=
']' && name[name.size() - 1] !=
'}') {
240 ercValues +=
" " + name;
243 ercValues +=
" " + name;
246 erc->setName(ercValues);
247 erc->initialize(state_);
248 primitiveSet_->addTerminal(erc);
258 case Primitives::Double:
260 case Primitives::Int:
262 case Primitives::Bool:
264 case Primitives::Char:
266 case Primitives::String:
272 std::istringstream ss(name);
275 case Primitives::Double:
278 if(ss.fail() ==
false)
279 terminal->setValue(&dblValue);
281 case Primitives::Int:
284 if(ss.fail() ==
false)
285 terminal->setValue(&intValue);
287 case Primitives::Bool:
292 else if(name ==
"false")
294 if(ss.fail() ==
false || name ==
"true" || name ==
"false") {
299 terminal->setValue(&boolValue);
302 case Primitives::Char:
305 if(ss.fail() ==
false)
306 terminal->setValue(&charValue);
308 case Primitives::String:
309 std::string stringValue;
311 if(ss.fail() ==
false)
312 terminal->setValue(&stringValue);
315 terminal->setName(name);
316 primitiveSet_->addTerminal(terminal);
320 if(primitiveSet_->getTerminalSetSize() == 0) {
321 ECF_LOG_ERROR(state_,
"Tree: Empty terminal set!");
326 sptr = getParameterValue(state_,
"maxdepth");
327 hometree->maxDepth_ = *((uint*) sptr.get());
328 sptr = getParameterValue(state_,
"mindepth");
329 hometree->minDepth_ = *((uint*) sptr.get());
330 if(hometree->maxDepth_ < hometree->minDepth_ || hometree->maxDepth_ < 1) {
331 ECF_LOG_ERROR(state_,
"Tree genotype: invalid values for max and min tree depth!");
335 hometree->initMaxDepth_ = hometree->maxDepth_;
336 if(isParameterDefined(state_,
"initmaxdepth")) {
337 sptr = getParameterValue(state_,
"initmaxdepth");
338 hometree->initMaxDepth_ = *((uint*) sptr.get());
340 hometree->initMinDepth_ = hometree->minDepth_;
341 if(isParameterDefined(state_,
"initmindepth")) {
342 sptr = getParameterValue(state_,
"initmindepth");
343 hometree->initMinDepth_ = *((uint*) sptr.get());
345 if(hometree->initMaxDepth_ < hometree->initMinDepth_ || hometree->initMaxDepth_ < 1) {
346 ECF_LOG_ERROR(state_,
"Tree genotype: invalid values for initial max and min tree depth!");
349 if(hometree->initMaxDepth_ > hometree->maxDepth_) {
350 ECF_LOG_ERROR(state_,
"Tree genotype: initial max depth cannot be greater than evolution max depth!");
362void Tree::execute(
void *result)
365 this->at(iNode_)->primitive_->execute(result, *
this);
371 this->push_back(
static_cast<NodeP
> (
node));
375void Tree::addNode(NodeP
node)
377 this->push_back(
node);
382uint Tree::fullBuild(PrimitiveSetP primitiveSet, uint myDepth)
385 node->depth_ = myDepth;
387 if(
node->depth_ < this->initMaxDepth_) {
388 node->setPrimitive(primitiveSet->getRandomFunction());
391 node->setPrimitive(primitiveSet->getRandomTerminal());
395 for(
int i = 0; i <
node->primitive_->getNumberOfArguments(); i++ ) {
396 node->size_ += fullBuild(primitiveSet, myDepth + 1);
404uint Tree::growBuild(PrimitiveSetP primitiveSet, uint myDepth)
407 node->depth_ = myDepth;
409 if(
node->depth_ < this->initMinDepth_) {
410 node->setPrimitive(primitiveSet->getRandomFunction());
413 else if(
node->depth_ < this->initMaxDepth_) {
414 node->setPrimitive(primitiveSet->getRandomPrimitive());
418 node->setPrimitive(primitiveSet->getRandomTerminal());
422 for(
int i = 0; i <
node->primitive_->getNumberOfArguments(); i++) {
423 node->size_ += growBuild(primitiveSet, myDepth + 1);
437 this->at(0)->size_ = setSize(0);
440 for(
int i = 0; i < this->at(0)->primitive_->getNumberOfArguments(); i++) {
442 setDepth(startDepth_ + 1);
444 this->at(0)->depth_ = startDepth_;
451uint Tree::setSize(uint iNode)
455 for(
int i = 0; i < this->at(myNode)->primitive_->getNumberOfArguments(); i++) {
456 uint childSize = setSize(iNode + 1);
460 this->at(myNode)->size_ = mySize;
468void Tree::setDepth(uint myDepth)
471 int nArgs = this->at( iNode_ )->primitive_->getNumberOfArguments();
472 for(
int i = 0; i < nArgs; i++) {
474 setDepth(myDepth + 1);
476 this->at(index)->depth_ = myDepth;
483void Tree::growBuild(PrimitiveSetP primitiveSet)
485 growBuild(primitiveSet, startDepth_);
492void Tree::fullBuild(PrimitiveSetP primitiveSet)
494 fullBuild(primitiveSet, startDepth_);
504void Tree::setTerminalValue(std::string name,
void* value)
506 PrimitiveP term = primitiveSet_->getTerminalByName(name);
507 if(term == PrimitiveP()) {
508 ECF_LOG_ERROR(state_,
"Tree genotype: invalid terminal name referenced in setTerminalValue()!");
512 term->setValue(value);
522void Tree::getTerminalValue(std::string name,
void* value)
524 PrimitiveP term = primitiveSet_->getTerminalByName(name);
525 if(term == PrimitiveP()) {
526 ECF_LOG_ERROR(state_,
"Tree genotype: invalid terminal name referenced in getTerminalValue()!");
530 term->getValue(value);
535void Tree::write(XMLNode& xTree)
537 xTree = XMLNode::createXMLTopNode(
"Tree");
538 std::stringstream sValue;
539 sValue << this->size();
540 xTree.addAttribute(
"size", sValue.str().c_str());
543 for(uint i = 0; i < this->size(); i++) {
544 sValue << this->at(i)->primitive_->getName() <<
" ";
546 xTree.addText(sValue.str().c_str());
550void Tree::read(XMLNode& xTree)
554 XMLCSTR sizeStr = xTree.getAttribute(
"size");
555 uint size = str2uint(sizeStr);
557 XMLCSTR tree = xTree.getText();
558 std::stringstream stream;
561 std::vector<PrimitiveP>& primitives = primitiveSet_->primitives_;
562 std::string primitiveStr;
565 for(uint iNode = 0; iNode < size; iNode++) {
566 stream >> primitiveStr;
570 PrimitiveP prim = primitiveSet_->getPrimitiveByName(primitiveStr);
571 if(prim != PrimitiveP()) {
572 node->setPrimitive(prim);
580 std::string prefix = primitiveStr.substr(0, 2);
581 std::string value = primitiveStr.substr(2);
582 std::stringstream ss;
584 if(prefix == DBL_PREFIX) {
590 else if(prefix == INT_PREFIX) {
596 else if(prefix == BOOL_PREFIX) {
602 else if(prefix == CHR_PREFIX) {
608 else if(prefix == STR_PREFIX) {
615 ECF_LOG_ERROR(state_,
"Tree genotype: undefined primitive (" + primitiveStr +
")!");
618 erc->setName(primitiveStr);
619 node->primitive_ = erc;
Node base class (Tree genotype)
Primitive set class: collects all Tree Primitives.
Ephemereal random constant (ERC) node of type double (Tree genotype).
Ephemereal random constant (ERC) node class (Tree genotype).
Terminal tree node class (Tree genotype).
Tree genotype: context presevation crx operator. Tries to make crossover at the 'same' point in both ...
Tree genotype: one point crx operator. Tries to select a crossing point in parent tree's common regio...
Tree genotype: simple tree crossover operator (with default 90% bias toward functional node) Referenc...
Tree genotype: size fair crx operator. Reference: http://dces.essex.ac.uk/staff/rpoli/gp-field-guide/...
Tree class - implements genotype as a tree.
Tree genotype: standard normal distribution noise mutation operator. Applicable only on ephemereal ra...
Tree genotype: mutation operator that replaces original tree with a randomly chosen subtree from the ...
Tree genotype: complement node mutation operator. For the operator to succeed, the chosen primitive m...
Tree genotype: node replacement mutation operator. Tries to replace the selected primitive with a dif...
Tree genotype: permutation mutation operator.
Tree genotype: mutation operator that shrinks randomly chosen subtree.
Tree genotype: subtree size-fair mutation operator. This is a 'standard' GP subtree mutation.