diff --git a/eo/gp/eoParseTree.h b/eo/gp/eoParseTree.h index 5aa4bcf4..7bac6125 100644 --- a/eo/gp/eoParseTree.h +++ b/eo/gp/eoParseTree.h @@ -26,8 +26,11 @@ public : { pruneTree(_size); } + eoParseTree(eoRnd& _rnd) + : EO(), parse_tree(_rnd()) + {} - void pruneTree(unsigned _size) + virtual void pruneTree(unsigned _size) { if (_size < 1) return; @@ -86,7 +89,6 @@ std::istream& operator>>(std::istream& is, eoParseTree& eot) } - template class eoGpDepthInitializer : public eoRnd< eoParseTree::Type > { @@ -125,7 +127,7 @@ class eoGpDepthInitializer : public eoRnd< eoParseTree::Type > vector::iterator it; for (it = initializor.begin(); it != initializor.end(); ++it) { - if (it->arity() > 1) + if (it->arity() > 0) break; } @@ -150,6 +152,8 @@ class eoGpDepthInitializer : public eoRnd< eoParseTree::Type > what_it = initializor.begin() + last_terminal + rng.random(initializor.size() - last_terminal); } + what_it->randomize(); + sequence.push_front(*what_it); for (int i = 0; i < what_it->arity(); ++i) diff --git a/eo/gp/node_pool.h b/eo/gp/node_pool.h index 35cc4ab2..f541d5f0 100644 --- a/eo/gp/node_pool.h +++ b/eo/gp/node_pool.h @@ -75,13 +75,18 @@ template class Node_alloc { public : - Node_alloc() {}; - + T* allocate(void) { T* t = static_cast(mem.allocate()); t = new (t) T; - //t->T(); // call constructor; + return t; + } + + T* construct(const T& org) + { + T* t = static_cast(mem.allocate()); + t = new (t) T(org); return t; } @@ -95,6 +100,7 @@ private : static MemPool mem; }; + template class Standard_alloc { @@ -108,6 +114,19 @@ public : return new T [arity]; } + + T* construct(size_t arity, T* org) + { + if (arity == 0) + return 0; + + T* t new T [arity]; + + for (int i = 0; i < arity; ++i) + { + t = T(org[i]); + } + } void deallocate(T* t, size_t arity = 1) { @@ -130,6 +149,11 @@ public : return new T;// [arity]; } + T* construct(const T& org) + { + return new T(org); + } + void deallocate(T* t) { delete t; @@ -181,6 +205,50 @@ public : return t; } + T* construct(size_t arity, T* org) + { + T* t; + + switch(arity) + { + + case 0 : return 0; + case 1 : + { + t = static_cast(mem1.allocate()); + new (t) T(*org); + break; + } + case 2 : + { + t = static_cast(mem2.allocate()); + new (t) T(*org); + new (&t[1]) T(org[1]); + break; + } + case 3 : + { + t = static_cast(mem3.allocate()); + new (t) T(*org); + new (&t[1]) T(org[1]); + new (&t[1]) T(org[2]); + break; + } + default : + { + t = new T[arity]; // does call default ctor + for (int i = 0; i < arity; ++i) + { + t[i] = T(org[i]); // constructs now + } + } + } + + return t; + } + + + void deallocate(T* t, size_t arity) { switch(arity) @@ -221,6 +289,7 @@ private : // static (non thread_safe) memory pools template MemPool Node_alloc::mem = sizeof(T); + template MemPool Tree_alloc::mem1 = sizeof(T); template MemPool Tree_alloc::mem2 = sizeof(T) * 2; template MemPool Tree_alloc::mem3 = sizeof(T) * 3; diff --git a/eo/gp/parse_tree.h b/eo/gp/parse_tree.h index cb3b2ec2..e6c50723 100644 --- a/eo/gp/parse_tree.h +++ b/eo/gp/parse_tree.h @@ -4,7 +4,7 @@ /** * Parse_tree and subtree classes - * (c) Maarten Keijzer 1999 + * (c) Maarten Keijzer 1999, 2000 * These classes may be used for educational and * other non-commercial purposes only. Even if I @@ -39,31 +39,39 @@ A parse_tree is evaluated through one of it's apply() members: - 1) parse_tree::apply(void) + 1) parse_tree::apply(RetVal) is the simplest evaluation, it will call - RetVal Node::operator()(subtree::const_iterator) + RetVal Node::operator()(RetVal, subtree::const_iterator) - 2) parse_tree::apply(It values) + (Unfortunately the first RetVal argument is mandatory (although you + might not need it. This is because MSVC does not support member template + functions properly. If it cannot deduce the template arguments (as is + the case in templatizing over return value) you are not allowed to + specify them. calling tree.apply() would result in a syntax + error. That is why you have to call tree.apply(double()) instead.) + + + 2) parse_tree::apply(RetVal v, It values) will call: - RetVal Node::operator()(subtree<... , It values) + RetVal Node::operator()(RetVal, subtree<... , It values) where It is whatever type you desire (most of the time this will be a vector containing the values of your variables); - 3) parse_tree::apply(It values, It2 moreValues) + 3) parse_tree::apply(RetVal, It values, It2 moreValues) will call: - RetVal Node::operator()(subtree<... , It values, It2 moreValues) + RetVal Node::operator()(RetVal, subtree<... , It values, It2 moreValues) although I do not see the immediate use of this, however... - 4) parse_tree::apply(It values, It2 args, It3 adfs) + 4) parse_tree::apply(RetVal, It values, It2 args, It3 adfs) that calls: @@ -77,7 +85,7 @@ possible. Implement the simplest eval as: template - RetVal operator()(It begin) const + RetVal operator()(RetVal dummy, It begin) const ****** Internal Structure ****** @@ -141,6 +149,10 @@ tree.clear(); copy(vec.begin(), vec.end(), back_inserter(tree)); + or from an istream: + + copy(istream_iterator(my_stream), istream_iterator(), back_inserter(tree)); + Note that the back_inserter must be used as there is no resize member in the parse_tree. back_inserter will use the push_back member from the parse_tree @@ -172,11 +184,16 @@ template class parse_tree { public : + class subtree { -// a bit nasty way to use a pool allocator (which would otherwise use slooow new and delete) -#if (defined(__GNUC__) || defined(_MSC_VER)) && !defined(_MT) +/* + a bit nasty way to use a pool allocator (which would otherwise use slooow new and delete) + TODO: use the std::allocator interface +*/ + +#if (defined(__GNUC__) || defined(_MSC_VER)) && !defined(_MT) // not multithreaded Node_alloc node_allocator; Tree_alloc tree_allocator; #else @@ -188,20 +205,28 @@ public : typedef subtree* iterator; typedef const subtree* const_iterator; - //typedef std::vector::const_reverse_iterator const_reverse_iterator; /* Constructors, assignments */ subtree(void) : content(node_allocator.allocate()), args(0), parent(0), _cumulative_size(0), _depth(0), _size(1) {} - subtree(const subtree& s) : content(node_allocator.allocate()), args(0), parent(0), _cumulative_size(0), _depth(0), _size(1) - { copy(s); } + subtree(const subtree& s) + : content(node_allocator.allocate()), + args(0), + parent(0), + _cumulative_size(1), + _depth(1), + _size(1) + { + copy(s); + } + subtree(const T& t) : content(node_allocator.allocate()), args(0), parent(0), _cumulative_size(0), _depth(0), _size(1) { copy(t); } template subtree(It b, It e) : content(node_allocator.allocate()), args(0), parent(0), _cumulative_size(0), _depth(0), _size(1) - { // initialize in prefix way for efficiency reasons + { // initialize in prefix order for efficiency reasons init(b, --e); } @@ -215,10 +240,12 @@ public : return copy(anotherS); } - return copy(s); + copy(s); + updateAfterInsert(); + return *this; } - subtree& operator=(const T& t) { return copy(t); } + subtree& operator=(const T& t) { copy(t); updateAfterInsert(); return *this; } /* Access to the nodes */ @@ -253,20 +280,58 @@ public : /* Evaluation with an increasing amount of user defined arguments */ template - RetVal apply(RetVal v) const { return (*content)(v, begin()); } + void apply(RetVal& v) const { (*content)(v, begin()); } template - RetVal apply(RetVal v, It values) const { return (*content)(v, begin(), values); } + void apply(RetVal& v, It values) const + { + (*content)(v, begin(), values); + } - template - RetVal apply(RetVal v, It values, It2 moreValues) const - { return (*content)(v, begin(), values, moreValues); } + template + void apply_mem_func(RetVal& v, It misc, void (T::* f)(RetVal&, subtree::iterator, It)) + { + (content->*f)(v, begin(), misc); + } + + +/* template + void apply(RetVal& v, It values, It2 moreValues) const + { (*content)(v, begin(), values, moreValues); } template - RetVal apply(RetVal v, It values, It2 moreValues, It3 evenMoreValues) const - { return (*content)(v, begin(), values, moreValues, evenMoreValues); } + void apply(RetVal& v, It values, It2 moreValues, It3 evenMoreValues) const + { (*content)(v, begin(), values, moreValues, evenMoreValues); } +*/ + template + void find_nodes(vector& result, Pred& p) + { + if (p(*content)) + { + result.push_back(this); + } + for (int i = 0; i < arity(); ++i) + { + args[i].find_nodes(result, p); + } + } + + template + void find_nodes(vector& result, Pred& p) const + { + if (p(*content)) + { + result.push_back(this); + } + + for (int i = 0; i < arity(); ++i) + { + args[i].find_nodes(result, p); + } + } + /* Iterators */ iterator begin(void) { return args; } @@ -336,6 +401,8 @@ protected : _cumulative_size += _size; _depth++; + content->updateAfterInsert(); + if (parent) parent->updateAfterInsert(); } @@ -382,46 +449,40 @@ private : return parent->get_root(); } - subtree& copy(const subtree& s) { - int oldArity = arity(); - - disown(); + int old_arity = arity(); - int ar = s.arity(); + int new_arity = s.arity(); - if (ar != oldArity) + if (new_arity != old_arity) { - tree_allocator.deallocate(args, oldArity); + tree_allocator.deallocate(args, old_arity); - args = tree_allocator.allocate(ar); - - //if (ar > 0) - // args = new subtree [ar]; - //else - // args = 0; + args = tree_allocator.allocate(new_arity); } - switch(ar) + switch(new_arity) { - case 3 : args[2].copy(s.args[2]); // no break! - case 2 : args[1].copy(s.args[1]); - case 1 : args[0].copy(s.args[0]); break; + case 3 : args[2].copy(s.args[2]); args[2].parent = this; // no break! + case 2 : args[1].copy(s.args[1]); args[1].parent = this; + case 1 : args[0].copy(s.args[0]); args[0].parent = this; case 0 : break; default : { - for (int i = 0; i < ar; ++i) + for (int i = 0; i < new_arity; ++i) { args[i].copy(s.args[i]); + args[i].parent = this; } } } *content = *s.content; - - adopt(); - updateAfterInsert(); + _size = s._size; + _depth = s._depth; + _cumulative_size = s._cumulative_size; + return *this; } @@ -559,20 +620,38 @@ private : /* Evaluation (application), with an increasing number of user defined arguments */ template - RetVal apply(RetVal v) const - { return _root.apply(v); } + void apply(RetVal& v) const + { _root.apply(v); } template - RetVal apply(RetVal v, It varValues) const - { return _root.apply(v, varValues); } + void apply(RetVal& v, It varValues) const + { _root.apply(v, varValues); } - template - RetVal apply(RetVal v, It varValues, It2 moreValues) const - { return _root.apply(v, varValues, moreValues); } + template + void apply_mem_func(RetVal& v, It misc, void (T::* f)(RetVal&, subtree::iterator, It)) + { + _root.apply_mem_func(v, misc, f); + } + + //template + // void apply(RetVal& v, It varValues, It2 moreValues) const + // { _root.apply(v, varValues, moreValues); } - template - RetVal apply(RetVal v, It varValues, It2 moreValues, It3 evenMoreValues) const - { return _root.apply(v, varValues, moreValues, evenMoreValues); } + //template + // void apply(RetVal& v, It varValues, It2 moreValues, It3 evenMoreValues) const + // { _root.apply(v, varValues, moreValues, evenMoreValues); } + + template + void find_nodes(vector& result, Pred& p) + { + _root.find_nodes(result, p); + } + + template + void find_nodes(vector& result, Pred& p) const + { + _root.find_nodes(p); + } /* Customized Swap */ void swap(parse_tree& other)