Upgraded parse_tree a bit...
This commit is contained in:
parent
f1fd1f8e33
commit
ca4e470092
3 changed files with 213 additions and 61 deletions
|
|
@ -26,8 +26,11 @@ public :
|
|||
{
|
||||
pruneTree(_size);
|
||||
}
|
||||
eoParseTree(eoRnd<Type>& _rnd)
|
||||
: EO<FType>(), parse_tree<Node>(_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<FType, Node>& eot)
|
|||
}
|
||||
|
||||
|
||||
|
||||
template <class FType, class Node>
|
||||
class eoGpDepthInitializer : public eoRnd< eoParseTree<FType, Node>::Type >
|
||||
{
|
||||
|
|
@ -125,7 +127,7 @@ class eoGpDepthInitializer : public eoRnd< eoParseTree<FType, Node>::Type >
|
|||
vector<Node>::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<FType, Node>::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)
|
||||
|
|
|
|||
|
|
@ -75,13 +75,18 @@ template<class T>
|
|||
class Node_alloc
|
||||
{
|
||||
public :
|
||||
Node_alloc() {};
|
||||
|
||||
|
||||
T* allocate(void)
|
||||
{
|
||||
T* t = static_cast<T*>(mem.allocate());
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -95,6 +100,7 @@ private :
|
|||
static MemPool mem;
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
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<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)
|
||||
{
|
||||
switch(arity)
|
||||
|
|
@ -221,6 +289,7 @@ private :
|
|||
|
||||
// static (non thread_safe) memory pools
|
||||
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>::mem2 = sizeof(T) * 2;
|
||||
template <class T> MemPool Tree_alloc<T>::mem3 = sizeof(T) * 3;
|
||||
|
|
|
|||
|
|
@ -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<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:
|
||||
|
||||
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 <class It>
|
||||
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<T>(my_stream), istream_iterator<T>(), 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 T> 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<T> node_allocator;
|
||||
Tree_alloc<subtree> tree_allocator;
|
||||
#else
|
||||
|
|
@ -188,20 +205,28 @@ public :
|
|||
|
||||
typedef subtree* iterator;
|
||||
typedef const subtree* const_iterator;
|
||||
//typedef std::vector<subtree >::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 <class It>
|
||||
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 <class RetVal>
|
||||
RetVal apply(RetVal v) const { return (*content)(v, begin()); }
|
||||
void apply(RetVal& v) const { (*content)(v, begin()); }
|
||||
|
||||
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>
|
||||
RetVal apply(RetVal v, It values, It2 moreValues) const
|
||||
{ return (*content)(v, begin(), values, moreValues); }
|
||||
template <class RetVal, class It>
|
||||
void apply_mem_func(RetVal& v, It misc, void (T::* f)(RetVal&, subtree::iterator, It))
|
||||
{
|
||||
(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>
|
||||
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 <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 */
|
||||
|
||||
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 <class RetVal>
|
||||
RetVal apply(RetVal v) const
|
||||
{ return _root.apply(v); }
|
||||
void apply(RetVal& v) const
|
||||
{ _root.apply(v); }
|
||||
|
||||
template <class RetVal, class It>
|
||||
RetVal apply(RetVal v, It varValues) const
|
||||
{ return _root.apply(v, varValues); }
|
||||
void apply(RetVal& v, It varValues) const
|
||||
{ _root.apply(v, varValues); }
|
||||
|
||||
template <class RetVal, class It, class It2>
|
||||
RetVal apply(RetVal v, It varValues, It2 moreValues) const
|
||||
{ return _root.apply(v, varValues, moreValues); }
|
||||
template <class RetVal, class It>
|
||||
void apply_mem_func(RetVal& v, It misc, void (T::* f)(RetVal&, subtree::iterator, It))
|
||||
{
|
||||
_root.apply_mem_func(v, misc, f);
|
||||
}
|
||||
|
||||
//template <class RetVal, class It, class It2>
|
||||
// void apply(RetVal& v, It varValues, It2 moreValues) const
|
||||
// { _root.apply(v, varValues, moreValues); }
|
||||
|
||||
template <class RetVal, class It, class It2, class It3>
|
||||
RetVal apply(RetVal v, It varValues, It2 moreValues, It3 evenMoreValues) const
|
||||
{ return _root.apply(v, varValues, moreValues, evenMoreValues); }
|
||||
//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 */
|
||||
void swap(parse_tree<T>& other)
|
||||
|
|
|
|||
Reference in a new issue