Upgraded parse_tree a bit...

This commit is contained in:
mac 2000-03-06 15:55:44 +00:00
commit ca4e470092
3 changed files with 213 additions and 61 deletions

View file

@ -26,8 +26,11 @@ public :
{ {
pruneTree(_size); pruneTree(_size);
} }
eoParseTree(eoRnd<Type>& _rnd)
: EO<FType>(), parse_tree<Node>(_rnd())
{}
void pruneTree(unsigned _size) virtual void pruneTree(unsigned _size)
{ {
if (_size < 1) if (_size < 1)
return; return;
@ -86,7 +89,6 @@ std::istream& operator>>(std::istream& is, eoParseTree<FType, Node>& eot)
} }
template <class FType, class Node> template <class FType, class Node>
class eoGpDepthInitializer : public eoRnd< eoParseTree<FType, Node>::Type > class eoGpDepthInitializer : public eoRnd< eoParseTree<FType, Node>::Type >
{ {
@ -125,7 +127,7 @@ class eoGpDepthInitializer : public eoRnd< eoParseTree<FType, Node>::Type >
vector<Node>::iterator it; vector<Node>::iterator it;
for (it = initializor.begin(); it != initializor.end(); ++it) for (it = initializor.begin(); it != initializor.end(); ++it)
{ {
if (it->arity() > 1) if (it->arity() > 0)
break; break;
} }
@ -150,6 +152,8 @@ class eoGpDepthInitializer : public eoRnd< eoParseTree<FType, Node>::Type >
what_it = initializor.begin() + last_terminal + rng.random(initializor.size() - last_terminal); what_it = initializor.begin() + last_terminal + rng.random(initializor.size() - last_terminal);
} }
what_it->randomize();
sequence.push_front(*what_it); sequence.push_front(*what_it);
for (int i = 0; i < what_it->arity(); ++i) for (int i = 0; i < what_it->arity(); ++i)

View file

@ -75,13 +75,18 @@ template<class T>
class Node_alloc class Node_alloc
{ {
public : public :
Node_alloc() {};
T* allocate(void) T* allocate(void)
{ {
T* t = static_cast<T*>(mem.allocate()); T* t = static_cast<T*>(mem.allocate());
t = new (t) T; t = new (t) T;
//t->T(); // call constructor; return t;
}
T* construct(const T& org)
{
T* t = static_cast<T*>(mem.allocate());
t = new (t) T(org);
return t; return t;
} }
@ -95,6 +100,7 @@ private :
static MemPool mem; static MemPool mem;
}; };
template <class T> template <class T>
class Standard_alloc class Standard_alloc
{ {
@ -109,6 +115,19 @@ public :
return new T [arity]; 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) void deallocate(T* t, size_t arity = 1)
{ {
if (arity == 0) if (arity == 0)
@ -130,6 +149,11 @@ public :
return new T;// [arity]; return new T;// [arity];
} }
T* construct(const T& org)
{
return new T(org);
}
void deallocate(T* t) void deallocate(T* t)
{ {
delete t; delete t;
@ -181,6 +205,50 @@ public :
return t; return t;
} }
T* construct(size_t arity, T* org)
{
T* t;
switch(arity)
{
case 0 : return 0;
case 1 :
{
t = static_cast<T*>(mem1.allocate());
new (t) T(*org);
break;
}
case 2 :
{
t = static_cast<T*>(mem2.allocate());
new (t) T(*org);
new (&t[1]) T(org[1]);
break;
}
case 3 :
{
t = static_cast<T*>(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) void deallocate(T* t, size_t arity)
{ {
switch(arity) switch(arity)
@ -221,6 +289,7 @@ private :
// static (non thread_safe) memory pools // static (non thread_safe) memory pools
template <class T> MemPool Node_alloc<T>::mem = sizeof(T); template <class T> MemPool Node_alloc<T>::mem = sizeof(T);
template <class T> MemPool Tree_alloc<T>::mem1 = sizeof(T); template <class T> MemPool Tree_alloc<T>::mem1 = sizeof(T);
template <class T> MemPool Tree_alloc<T>::mem2 = sizeof(T) * 2; template <class T> MemPool Tree_alloc<T>::mem2 = sizeof(T) * 2;
template <class T> MemPool Tree_alloc<T>::mem3 = sizeof(T) * 3; template <class T> MemPool Tree_alloc<T>::mem3 = sizeof(T) * 3;

View file

@ -4,7 +4,7 @@
/** /**
* Parse_tree and subtree classes * Parse_tree and subtree classes
* (c) Maarten Keijzer 1999 * (c) Maarten Keijzer 1999, 2000
* These classes may be used for educational and * These classes may be used for educational and
* other non-commercial purposes only. Even if I * other non-commercial purposes only. Even if I
@ -39,31 +39,39 @@
A parse_tree is evaluated through one of it's apply() members: 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 is the simplest evaluation, it will call
RetVal Node::operator()(subtree<Node, RetVal>::const_iterator) RetVal Node::operator()(RetVal, subtree<Node, RetVal>::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<double>() 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: 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 where It is whatever type you desire (most of the time
this will be a vector containing the values of your this will be a vector containing the values of your
variables); variables);
3) parse_tree::apply(It values, It2 moreValues) 3) parse_tree::apply(RetVal, It values, It2 moreValues)
will call: 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... 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: that calls:
@ -77,7 +85,7 @@
possible. Implement the simplest eval as: possible. Implement the simplest eval as:
template <class It> template <class It>
RetVal operator()(It begin) const RetVal operator()(RetVal dummy, It begin) const
****** Internal Structure ****** ****** Internal Structure ******
@ -141,6 +149,10 @@
tree.clear(); tree.clear();
copy(vec.begin(), vec.end(), back_inserter(tree)); copy(vec.begin(), vec.end(), back_inserter(tree));
or from an istream:
copy(istream_iterator<T>(my_stream), istream_iterator<T>(), back_inserter(tree));
Note that the back_inserter must be used as there is no Note that the back_inserter must be used as there is no
resize member in the parse_tree. back_inserter will use resize member in the parse_tree. back_inserter will use
the push_back member from the parse_tree the push_back member from the parse_tree
@ -172,11 +184,16 @@ template <class T> class parse_tree
{ {
public : public :
class subtree 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<T> node_allocator; Node_alloc<T> node_allocator;
Tree_alloc<subtree> tree_allocator; Tree_alloc<subtree> tree_allocator;
#else #else
@ -188,20 +205,28 @@ public :
typedef subtree* iterator; typedef subtree* iterator;
typedef const subtree* const_iterator; typedef const subtree* const_iterator;
//typedef std::vector<subtree >::const_reverse_iterator const_reverse_iterator;
/* Constructors, assignments */ /* Constructors, assignments */
subtree(void) : content(node_allocator.allocate()), args(0), parent(0), _cumulative_size(0), _depth(0), _size(1) 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) subtree(const subtree& s)
{ copy(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) subtree(const T& t) : content(node_allocator.allocate()), args(0), parent(0), _cumulative_size(0), _depth(0), _size(1)
{ copy(t); } { copy(t); }
template <class It> template <class It>
subtree(It b, It e) : content(node_allocator.allocate()), args(0), parent(0), _cumulative_size(0), _depth(0), _size(1) 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); init(b, --e);
} }
@ -215,10 +240,12 @@ public :
return copy(anotherS); 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 */ /* Access to the nodes */
@ -253,19 +280,57 @@ public :
/* Evaluation with an increasing amount of user defined arguments */ /* Evaluation with an increasing amount of user defined arguments */
template <class RetVal> template <class RetVal>
RetVal apply(RetVal v) const { return (*content)(v, begin()); } void apply(RetVal& v) const { (*content)(v, begin()); }
template <class RetVal, class It> template <class RetVal, class It>
RetVal apply(RetVal v, It values) const { return (*content)(v, begin(), values); } void apply(RetVal& v, It values) const
{
(*content)(v, begin(), values);
}
template <class RetVal, class It, class It2> template <class RetVal, class It>
RetVal apply(RetVal v, It values, It2 moreValues) const void apply_mem_func(RetVal& v, It misc, void (T::* f)(RetVal&, subtree::iterator, It))
{ return (*content)(v, begin(), values, moreValues); } {
(content->*f)(v, begin(), misc);
}
/* template <class RetVal, class It, class It2>
void apply(RetVal& v, It values, It2 moreValues) const
{ (*content)(v, begin(), values, moreValues); }
template <class RetVal, class It, class It2, class It3> template <class RetVal, class It, class It2, class It3>
RetVal apply(RetVal v, It values, It2 moreValues, It3 evenMoreValues) const void apply(RetVal& v, It values, It2 moreValues, It3 evenMoreValues) const
{ return (*content)(v, begin(), values, moreValues, evenMoreValues); } { (*content)(v, begin(), values, moreValues, evenMoreValues); }
*/
template <class Pred>
void find_nodes(vector<subtree*>& result, Pred& p)
{
if (p(*content))
{
result.push_back(this);
}
for (int i = 0; i < arity(); ++i)
{
args[i].find_nodes(result, p);
}
}
template <class Pred>
void find_nodes(vector<const subtree*>& 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 */ /* Iterators */
@ -336,6 +401,8 @@ protected :
_cumulative_size += _size; _cumulative_size += _size;
_depth++; _depth++;
content->updateAfterInsert();
if (parent) if (parent)
parent->updateAfterInsert(); parent->updateAfterInsert();
} }
@ -382,46 +449,40 @@ private :
return parent->get_root(); return parent->get_root();
} }
subtree& copy(const subtree& s) subtree& copy(const subtree& s)
{ {
int oldArity = arity(); int old_arity = arity();
disown(); int new_arity = s.arity();
int ar = s.arity(); if (new_arity != old_arity)
if (ar != oldArity)
{ {
tree_allocator.deallocate(args, oldArity); tree_allocator.deallocate(args, old_arity);
args = tree_allocator.allocate(ar); args = tree_allocator.allocate(new_arity);
//if (ar > 0)
// args = new subtree [ar];
//else
// args = 0;
} }
switch(ar) switch(new_arity)
{ {
case 3 : args[2].copy(s.args[2]); // no break! case 3 : args[2].copy(s.args[2]); args[2].parent = this; // no break!
case 2 : args[1].copy(s.args[1]); case 2 : args[1].copy(s.args[1]); args[1].parent = this;
case 1 : args[0].copy(s.args[0]); break; case 1 : args[0].copy(s.args[0]); args[0].parent = this;
case 0 : break; case 0 : break;
default : default :
{ {
for (int i = 0; i < ar; ++i) for (int i = 0; i < new_arity; ++i)
{ {
args[i].copy(s.args[i]); args[i].copy(s.args[i]);
args[i].parent = this;
} }
} }
} }
*content = *s.content; *content = *s.content;
_size = s._size;
_depth = s._depth;
_cumulative_size = s._cumulative_size;
adopt();
updateAfterInsert();
return *this; return *this;
} }
@ -559,20 +620,38 @@ private :
/* Evaluation (application), with an increasing number of user defined arguments */ /* Evaluation (application), with an increasing number of user defined arguments */
template <class RetVal> template <class RetVal>
RetVal apply(RetVal v) const void apply(RetVal& v) const
{ return _root.apply(v); } { _root.apply(v); }
template <class RetVal, class It> template <class RetVal, class It>
RetVal apply(RetVal v, It varValues) const void apply(RetVal& v, It varValues) const
{ return _root.apply(v, varValues); } { _root.apply(v, varValues); }
template <class RetVal, class It, class It2> template <class RetVal, class It>
RetVal apply(RetVal v, It varValues, It2 moreValues) const void apply_mem_func(RetVal& v, It misc, void (T::* f)(RetVal&, subtree::iterator, It))
{ return _root.apply(v, varValues, moreValues); } {
_root.apply_mem_func(v, misc, f);
}
template <class RetVal, class It, class It2, class It3> //template <class RetVal, class It, class It2>
RetVal apply(RetVal v, It varValues, It2 moreValues, It3 evenMoreValues) const // void apply(RetVal& v, It varValues, It2 moreValues) const
{ return _root.apply(v, varValues, moreValues, evenMoreValues); } // { _root.apply(v, varValues, moreValues); }
//template <class RetVal, class It, class It2, class It3>
// void apply(RetVal& v, It varValues, It2 moreValues, It3 evenMoreValues) const
// { _root.apply(v, varValues, moreValues, evenMoreValues); }
template <class Pred>
void find_nodes(vector<subtree*>& result, Pred& p)
{
_root.find_nodes(result, p);
}
template <class Pred>
void find_nodes(vector<const subtree*>& result, Pred& p) const
{
_root.find_nodes(p);
}
/* Customized Swap */ /* Customized Swap */
void swap(parse_tree<T>& other) void swap(parse_tree<T>& other)