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"
39 Tree *newObject =
new Tree(*
this);
42 for(
int i = 0; i < (int) this->size(); i++) {
43 (*newObject)[i] = (NodeP) (
new Node((*
this)[i]));
51 std::vector<CrossoverOpP> crx;
63 std::vector<MutationOpP> mut;
82 userFunctions_.push_back(func);
93 userTerminals_.push_back(term);
101 "maximum tree depth (default: 5)");
103 "minimum tree depth (default: 1)");
105 "maximum initial tree depth (default: 5)");
107 "minimum initial tree depth (default: 1)");
109 "set of functional tree elements (mandatory)");
111 "set of terminal tree elements (mandatory)");
119 Tree* hometree = (Tree*) state->getGenotypes()[
genotypeId_].get();
123 if(!hometree->primitiveSet_)
127 this->primitiveSet_ = hometree->primitiveSet_;
134 if(state->getRandomizer()->getRandomInteger(0, 1) % 2 == 0)
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_);
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;
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:
259 terminal = (PrimitiveP) (
new Primitives::Terminal);
break;
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!");
327 hometree->maxDepth_ = *((uint*) sptr.get());
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_;
338 hometree->initMaxDepth_ = *((uint*) sptr.get());
340 hometree->initMinDepth_ = hometree->minDepth_;
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!");
365 this->at(
iNode_)->primitive_->execute(result, *
this);
369void Tree::addNode(
Node *node)
371 this->push_back(
static_cast<NodeP
> (node));
375void Tree::addNode(NodeP node)
377 this->push_back(node);
387 if(node->
depth_ < this->initMaxDepth_) {
395 for(
int i = 0; i < node->
primitive_->getNumberOfArguments(); i++ ) {
409 if(node->
depth_ < this->initMinDepth_) {
413 else if(node->
depth_ < this->initMaxDepth_) {
422 for(
int i = 0; i < node->
primitive_->getNumberOfArguments(); i++) {
437 this->at(0)->size_ =
setSize(0);
440 for(
int i = 0; i < this->at(0)->primitive_->getNumberOfArguments(); i++) {
455 for(
int i = 0; i < this->at(myNode)->primitive_->getNumberOfArguments(); i++) {
456 uint childSize =
setSize(iNode + 1);
460 this->at(myNode)->size_ = mySize;
471 int nArgs = this->at(
iNode_ )->primitive_->getNumberOfArguments();
472 for(
int i = 0; i < nArgs; i++) {
476 this->at(index)->depth_ = myDepth;
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);
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);
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());
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()) {
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);
voidP getParameterValue(StateP state, std::string name)
Read single parameter value from Registry.
std::string getName()
Return genotype's name (each genotype is uniquely identified with its name).
bool registerParameter(StateP state, std::string name, voidP value, enum ECF::type T, std::string description="")
Register a single parameter.
bool isParameterDefined(StateP state, std::string name)
Check if parameter is defined in the configuration.
uint genotypeId_
this genotype's unique index in individual structure
Node base class (Tree genotype).
void setPrimitive(PrimitiveP primitive)
Set the primitive this node points to (when creating a new tree node). In case of an ephemereal rando...
PrimitiveP primitive_
pointer to the Primitive belonging to this node
uint size_
size of the subtree of this node (including the node)
uint depth_
depth of this node
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/...
bool addFunction(PrimitiveP)
Add user defined function primitive. Must be called prior to initialization (no impact otherwise).
uint startDepth_
start depth of the first node (0 by default)
uint fullBuild(PrimitiveSetP primitiveSet, uint myDepth)
Build Tree using 'full' method.
uint minDepth_
min allowed Tree depth
void getTerminalValue(std::string, void *)
Retrieve a terminal's value.
void setTerminalValue(std::string, void *)
Set a terminal's value.
Tree * copy()
Create an identical copy of the genotype object.
uint initMinDepth_
min allowed Tree depth at initialization (minDepth_ used if not defined)
uint growBuild(PrimitiveSetP primitiveSet, uint myDepth)
Build Tree using 'grow' method.
uint iNode_
current node index (when parsing the tree)
bool addTerminal(PrimitiveP)
Add user defined terminal primitive. Must be called prior to initialization (no impact otherwise).
std::vector< CrossoverOpP > getCrossoverOp()
Create and return a vector of crossover operators.
void setDepth(uint myDepth)
Calculate depth of each node in the tree.
std::vector< MutationOpP > getMutationOp()
Create and return a vector of mutation operators.
void write(XMLNode &)
Write genotype data to XMLNode.
uint initMaxDepth_
max allowed Tree depth at initialization (maxDepth_ used if not defined)
void update()
Calculate depth and subtree sizes of each node in the tree.
void registerParameters(StateP)
Register genotype's parameters (called before Genotype::initialize).
uint setSize(uint)
Calculate subtree sizes of each node in the tree.
void execute(void *)
Execute current tree.
void read(XMLNode &)
Read genotype data from XMLNode.
uint maxDepth_
max allowed Tree depth
virtual void initializeFirst(Tree *hometree)
Performs the first Tree initialization (performed only once for each active Tree Genotype)....
bool initialize(StateP state)
Initialize a genotype object (read parameters, perform sanity check, build data).
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.