no message

This commit is contained in:
mac 2000-03-22 14:12:08 +00:00
commit 648c4ab6ec
4 changed files with 1616 additions and 0 deletions

242
eo/src/gp/eoParseTree.h Normal file
View file

@ -0,0 +1,242 @@
#ifndef EO_PARSE_TREE_H
#define EO_PARSE_TREE_H
#include <list>
#include "EO.h"
#include "eoOp.h"
#include "eoInserter.h"
#include "eoIndiSelector.h"
#include "parse_tree.h"
#include "eoRnd.h"
using namespace gp_parse_tree;
using namespace std;
template <class FType, class Node>
class eoParseTree : public EO<FType>, public parse_tree<Node>
{
public :
typedef typename parse_tree<Node>::subtree Type;
eoParseTree(void) : EO<FType>(), parse_tree<Node>() {}
eoParseTree(unsigned _size, eoRnd<Type>& _rnd)
: EO<FType>(), parse_tree<Node>(_rnd())
{
pruneTree(_size);
}
eoParseTree(eoRnd<Type>& _rnd)
: EO<FType>(), parse_tree<Node>(_rnd())
{}
virtual void pruneTree(unsigned _size)
{
if (_size < 1)
return;
if (size() > _size)
{
Type* sub = &operator[](size() - 2); // prune tree
while (sub->size() > _size)
{
sub = &sub->operator[](0);
}
back() = *sub;
}
}
eoParseTree(std::istream& is) : EO<FType>(), parse_tree<Node>()
{
readFrom(is);
}
string className(void) const { return "eoParseTree"; }
void printOn(std::ostream& os) const
{
os << fitness() << ' ';
std::copy(ebegin(), eend(), ostream_iterator<Node>(os));
}
void readFrom(std::istream& is)
{
FType fit;
is >> fit;
fitness(fit);
std::copy(istream_iterator<Node>(is), istream_iterator<Node>(), back_inserter(*this));
}
};
template <class FType, class Node>
std::ostream& operator<<(std::ostream& os, const eoParseTree<FType, Node>& eot)
{
eot.printOn(os);
return os;
}
template <class FType, class Node>
std::istream& operator>>(std::istream& is, eoParseTree<FType, Node>& eot)
{
eot.readFrom(is);
return is;
}
template <class FType, class Node>
class eoGpDepthInitializer : public eoRnd< eoParseTree<FType, Node>::Type >
{
public :
typedef eoParseTree<FType, Node> EoType;
eoGpDepthInitializer(
unsigned _max_depth,
const vector<Node>& _initializor,
bool _grow = true)
:
eoRnd<EoType::Type>(),
max_depth(_max_depth),
initializor(_initializor),
grow(_grow)
{}
virtual string className() const { return "eoDepthInitializer"; };
EoType::Type operator()(void)
{
list<Node> sequence;
generate(sequence, max_depth);
parse_tree<Node> tree(sequence.begin(), sequence.end());
return tree.root();
}
void generate(list<Node>& sequence, int the_max, int last_terminal = -1)
{
if (last_terminal == -1)
{ // check where the last terminal in the sequence resides
vector<Node>::iterator it;
for (it = initializor.begin(); it != initializor.end(); ++it)
{
if (it->arity() > 0)
break;
}
last_terminal = it - initializor.begin();
}
if (the_max == 1)
{ // generate terminals only
vector<Node>::iterator it = initializor.begin() + rng.random(last_terminal);
sequence.push_front(*it);
return;
}
vector<Node>::iterator what_it;
if (grow)
{
what_it = initializor.begin() + rng.random(initializor.size());
}
else // full
{
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)
generate(sequence, the_max - 1, last_terminal);
}
private :
unsigned max_depth;
std::vector<Node> initializor;
bool grow;
};
template<class FType, class Node>
class eoSubtreeXOver: public eoGeneralOp< eoParseTree<FType, Node> > {
public:
typedef eoParseTree<FType, Node> EoType;
eoSubtreeXOver( unsigned _max_length)
: eoGeneralOp<EoType>(), max_length(_max_length) {};
virtual string className() const { return "eoSubtreeXOver"; };
/// Dtor
virtual ~eoSubtreeXOver () {};
void operator()(eoIndiSelector<EoType>& _source, eoInserter<EoType>& _sink ) const
{
EoType eo1 = _source.select();
const EoType& eo2 = _source.select();
int i = rng.random(eo1.size());
int j = rng.random(eo2.size());
eo1[i] = eo2[j]; // insert subtree
eo1.pruneTree(max_length);
eo1.invalidate();
_sink.insert(eo1);
}
unsigned max_length;
};
template<class FType, class Node>
class eoBranchMutation: public eoGeneralOp< eoParseTree<FType, Node> >
{
public:
typedef eoParseTree<FType, Node> EoType;
eoBranchMutation(eoRnd<EoType::Type>& _init, unsigned _max_length)
: eoGeneralOp<EoType>(), max_length(_max_length), initializer(_init)
{};
virtual string className() const { return "eoBranchMutation"; };
/// Dtor
virtual ~eoBranchMutation() {};
void operator()(eoIndiSelector<EoType>& _source, eoInserter<EoType>& _sink ) const
{
EoType eo1 = _source.select();
int i = rng.random(eo1.size());
EoType eo2(eo1[i].size(), initializer); // create random other to cross with
eo1[i] = eo2.back(); // insert subtree
eo1.pruneTree(max_length);
eo1.invalidate();
_sink.insert(eo1);
}
private :
unsigned max_length;
eoRnd<EoType::Type>& initializer;
};
#endif

297
eo/src/gp/node_pool.h Normal file
View file

@ -0,0 +1,297 @@
#ifndef node_pool_h
#define node_pool_h
class MemPool
{
public :
MemPool(unsigned int sz) : esize(sz<sizeof(Link)? sizeof(Link) : sz) {}
~MemPool()
{
Chunk* n = chunks;
while(n)
{
Chunk* p = n;
n = n->next;
delete p;
}
}
void* allocate()
{
if (head == 0) grow();
Link* p = head;
head = p->next;
return static_cast<void*>(p);
}
void deallocate(void* b)
{
Link* p = static_cast<Link*>(b);
p->next = head;
head = p;
}
private :
void grow()
{
Chunk* n = new Chunk;
n->next = chunks;
chunks = n;
const int nelem = Chunk::size/esize;
char* start = n->mem;
char* last = &start[(nelem-1)*esize];
for (char* p = start; p < last; p += esize)
{
reinterpret_cast<Link*>(p)->next =
reinterpret_cast<Link*>(p + esize);
}
reinterpret_cast<Link*>(last)->next = 0;
head = reinterpret_cast<Link*>(start);
}
struct Link
{
Link* next;
};
struct Chunk
{
enum {size = 8 * 1024 - 16};
Chunk* next;
char mem[size];
};
Chunk* chunks;
const unsigned int esize;
Link* head;
};
template<class T>
class Node_alloc
{
public :
T* allocate(void)
{
T* t = static_cast<T*>(mem.allocate());
t = new (t) T;
return t;
}
T* construct(const T& org)
{
T* t = static_cast<T*>(mem.allocate());
t = new (t) T(org);
return t;
}
void deallocate(T* t)
{
t->~T(); // call destructor
mem.deallocate(static_cast<void*>(t));
}
private :
static MemPool mem;
};
template <class T>
class Standard_alloc
{
public :
Standard_alloc() {}
T* allocate(size_t arity = 1)
{
if (arity == 0)
return 0;
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)
{
if (arity == 0)
return ;
delete [] t;
}
};
template <class T>
class Standard_Node_alloc
{
public :
Standard_Node_alloc() {}
T* allocate(void)
{
return new T;// [arity];
}
T* construct(const T& org)
{
return new T(org);
}
void deallocate(T* t)
{
delete t;
}
};
template <class T>
class Tree_alloc
{
public :
Tree_alloc() {}
T* allocate(size_t arity)
{
T* t;
switch(arity)
{
case 0 : return 0;
case 1 :
{
t = static_cast<T*>(mem1.allocate());
new (t) T;
break;
}
case 2 :
{
t = static_cast<T*>(mem2.allocate());
new (t) T;
new (&t[1]) T;
break;
}
case 3 :
{
t = static_cast<T*>(mem3.allocate());
new (t) T;
new (&t[1]) T;
new (&t[2]) T;
break;
}
default :
{
return new T[arity];
}
}
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)
{
case 0: return;
case 3 :
{
t[2].~T(); t[1].~T(); t[0].~T();
mem3.deallocate(static_cast<void*>(t));
return;
}
case 2 :
{
t[1].~T(); t[0].~T();
mem2.deallocate(static_cast<void*>(t));
return;
}
case 1 :
{
t[0].~T();
mem1.deallocate(static_cast<void*>(t));
return;
}
default :
{
delete [] t;
return;
}
}
}
private :
static MemPool mem1;
static MemPool mem2;
static MemPool mem3;
};
// 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;
#endif

992
eo/src/gp/parse_tree.h Normal file
View file

@ -0,0 +1,992 @@
#ifndef PARSE_TREE_HH
#define PARSE_TREE_HH
/**
* Parse_tree and subtree classes
* (c) Maarten Keijzer 1999, 2000
* These classes may be used for educational and
* other non-commercial purposes only. Even if I
* wanted to, I am not at liberty to place this file
* under the GNU Lesser Public Library License, as this
* would limit my and my institution's freedom to use
* this file in closed-source software.
* This material is provided "as is", with absolutely no warranty expressed
* or implied. Any use is at your own risk.
*
* Permission to use or copy this software for non-commercial purpose is hereby granted
* without fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is granted,
* provided the above notices are retained, and a notice that the code was
* modified is included with the above copyright notice.
*
Usage information.
class Node (your node in the tree) must have the following implemented:
****** Arity ******
int arity(void) const
Note: the default constructor of a Node should provide a
Node with arity 0!
****** Evaluation ******
A parse_tree is evaluated through one of it's apply() members:
1) parse_tree::apply(RetVal)
is the simplest evaluation, it will call
RetVal Node::operator()(RetVal, subtree<Node, RetVal>::const_iterator)
(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()(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(RetVal, It values, It2 moreValues)
will call:
RetVal Node::operator()(RetVal, subtree<... , It values, It2 moreValues)
although I do not see the immediate use of this, however...
4) parse_tree::apply(RetVal, It values, It2 args, It3 adfs)
that calls:
RetVal Node::operator()(subtree<... , It values, It2 args, It3 adfs)
can be useful for implementing adfs.
In general it is a good idea to leave the specifics of the
arguments open so that different ways of evaluation remain
possible. Implement the simplest eval as:
template <class It>
RetVal operator()(RetVal dummy, It begin) const
****** Internal Structure ******
A parse_tree has two template arguments: the Node and the ReturnValue
produced by evaluating the node. The structure of the tree is defined
through a subtree class that has the same two template arguments.
The nodes are stored in a tree like :
node4
/ \
node3 node2
/ \
node1 node0
where nodes 2 and 4 have arity 2 and nodes 0,1 and 3 arity 0 (terminals)
The nodes are subtrees, containing the structure of the tree, together
with its size and depth. They contain a Node, the user defined template
argument. To access these nodes from a subtree, use operator-> or operator*.
The numbers behind the nodes define a reverse-polish or postfix
traversel through the tree. The parse_tree defines iterators
on the tree such that
tree.begin() points at the subtree at node0 and
tree.back() returns the subtree at node4, the complete tree
Likewise operator[] is defined on the tree, such that:
tree[0] will return the subtree at node0, while
tree[2] will return the subtree at node2
Assigments of subtrees is protected so that the code:
tree[2] = tree[0];
will not crash and result in a tree structured as:
node4
/ \
node3 node0
Note that the rank numbers no longer specify their place in the tree:
tree[0] still points at node0, but
tree[1] now points to node3 and
tree[2] points at the root node4
Embedded iterators are implemented to iterate over nodes rather
than subtrees. So an easy way to copy your tree to a vector is:
vector<Node> vec(tree.size());
copy(tree.ebegin(), tree.eend(), vec.begin());
You can also copy it to an ostream_iterator with this
technique, given that your Node implements an appropriate
operator<<. Reinitializing a tree with the vector is also
simple:
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
*/
#include <vector>
#include <utility> // for swap
#ifdef _MSC_VER
#pragma warning(disable : 4786) // disable this nagging warning about the limitations of the mirkosoft debugger
#endif
namespace gp_parse_tree
{
#include "node_pool.h"
template <class T>
inline void do_the_swap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}
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)
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
Standard_Node_alloc<T> node_allocator;
Standard_alloc<subtree> tree_allocator;
#endif
public :
typedef subtree* iterator;
typedef const subtree* const_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(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 order for efficiency reasons
init(b, --e);
}
virtual ~subtree(void) { tree_allocator.deallocate(args, arity()); node_allocator.deallocate(content); }
subtree& operator=(const subtree& s)
{
if (s.get_root() == get_root())
{ // from the same tree, maybe a child. Don't take any chances
subtree anotherS = s;
return copy(anotherS);
}
copy(s);
updateAfterInsert();
return *this;
}
subtree& operator=(const T& t) { copy(t); updateAfterInsert(); return *this; }
/* Access to the nodes */
T& operator*(void) { return *content; }
const T& operator*(void) const { return *content; }
T* operator->(void) { return content; }
const T* operator->(void) const { return content; }
/* Equality, inequality check, Node needs to implement operator== */
bool operator==(const subtree& other) const
{
if (! (*content == *other.content))
return false;
for (int i = 0; i < arity(); i++)
{
if (!(args[i] == other.args[i]))
return false;
}
return true;
}
bool operator !=(const subtree& other) const
{
return !operator==(other);
}
/* Arity */
int arity(void) const { return content->arity(); }
/* Evaluation with an increasing amount of user defined arguments */
template <class RetVal>
void apply(RetVal& v) const { (*content)(v, begin()); }
template <class RetVal, class It>
void apply(RetVal& v, It values) const
{
(*content)(v, begin(), values);
}
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>
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; }
const_iterator begin(void) const { return args; }
iterator end(void) { return args + arity(); }
const_iterator end(void) const { return args + arity(); }
subtree& operator[](int i) { return *(begin() + i); }
const subtree& operator[](int i) const { return *(begin() + i); }
/* Some statistics */
size_t size(void) const { return _size; }
size_t cumulative_size(void) const { return _cumulative_size; }
size_t depth(void) const { return _depth; }
const subtree& select_cumulative(size_t which) const
{ return imp_select_cumulative(which); }
subtree& select_cumulative(size_t which)
{ return const_cast<subtree&>(imp_select_cumulative(which)); }
subtree& get_node(size_t which)
{ return const_cast<subtree&>(imp_get_node(which));}
const subtree& get_node(size_t which) const
{ return imp_get_node(which); }
subtree* get_parent(void) { return parent; }
const subtree* get_parent(void) const { return parent; }
void clear(void)
{ tree_allocator.deallocate(args, arity()); args = 0; *content = T(); parent = 0; _cumulative_size = 0; _depth = 0; _size = 0; }
void swap(subtree& y)
{
do_the_swap(content, y.content);
do_the_swap(args, y.args);
do_the_swap(parent, y.parent);
do_the_swap(_cumulative_size, y._cumulative_size);
do_the_swap(_depth, y._depth);
do_the_swap(_size, y._size);
updateAfterInsert();
}
friend void swap(subtree& x, subtree& y)
{
x.swap(y);
}
protected :
virtual void updateAfterInsert(void)
{
_depth = 0;
_size = 1;
_cumulative_size = 0;
for (iterator it = begin(); it != end(); ++it)
{
_size += it->size();
_cumulative_size += it->_cumulative_size;
_depth = it->_depth > _depth? it->_depth: _depth;
}
_cumulative_size += _size;
_depth++;
if (parent)
parent->updateAfterInsert();
}
private :
const subtree& imp_select_cumulative(size_t which) const
{
if (which >= (_cumulative_size - size()))
return *this;
// else
for (int i = arity() - 1; i >= 0; --i)
{
if (which < args[i]._cumulative_size)
return args[i].imp_select_cumulative(which);
which -= args[i]._cumulative_size;
}
return *this; // error!
}
const subtree& imp_get_node(size_t which) const
{
if (which == size() - 1)
return *this;
for (int i = arity() - 1; i >= 0; --i)
{
unsigned c_size = args[i].size();
if (which < c_size)
return args[i].imp_get_node(which);
which -= c_size;
}
return *this; // error!
}
const subtree* get_root(void) const
{
if (parent == 0)
return this;
// else
return parent->get_root();
}
subtree& copy(const subtree& s)
{
int old_arity = arity();
int new_arity = s.arity();
if (new_arity != old_arity)
{
tree_allocator.deallocate(args, old_arity);
args = tree_allocator.allocate(new_arity);
}
switch(new_arity)
{
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 < new_arity; ++i)
{
args[i].copy(s.args[i]);
args[i].parent = this;
}
}
}
*content = *s.content;
_size = s._size;
_depth = s._depth;
_cumulative_size = s._cumulative_size;
return *this;
}
subtree& copy(const T& t)
{
int oldArity = arity();
if (content != &t)
*content = t;
else
oldArity = -1;
int ar = arity();
if (ar != oldArity)
{
if (oldArity != -1)
tree_allocator.deallocate(args, oldArity);
args = tree_allocator.allocate(ar);
//if (ar > 0)
// args = new subtree [ar];
//else
// args = 0;
}
adopt();
updateAfterInsert();
return *this;
}
void disown(void)
{
switch(arity())
{
case 3 : args[2].parent = 0; // no break!
case 2 : args[1].parent = 0;
case 1 : args[0].parent = 0; break;
case 0 : break;
default :
{
for (iterator it = begin(); it != end(); ++it)
{
it->parent = 0;
}
}
}
}
void adopt(void)
{
switch(arity())
{
case 3 : args[2].parent = this; // no break!
case 2 : args[1].parent = this;
case 1 : args[0].parent = this; break;
case 0 : break;
default :
{
for (iterator it = begin(); it != end(); ++it)
{
it->parent = this;
}
}
}
}
template <class It>
void init(It b, It& last)
{
*this = *last;
#ifndef NDEBUG
if (last == b && arity() > 0)
{
throw "subtree::init()";
}
#endif
for (int i = 0; i < arity(); ++i)
{
args[i].parent = 0;
args[i].init(b, --last);
args[i].parent = this;
}
updateAfterInsert();
}
T* content;
subtree* args;
subtree* parent;
size_t _cumulative_size;
size_t _depth;
size_t _size;
};
// Continuing with parse_tree
typedef T value_type;
/* Constructors and Assignments */
parse_tree(void) : _root(), pushed() {}
parse_tree(const parse_tree& org) : _root(org._root), pushed(org.pushed) { }
parse_tree(const subtree& sub) : _root(sub), pushed() { }
template <class It>
parse_tree(It b, It e) : _root(b, e), pushed() {}
virtual ~parse_tree(void) {}
parse_tree& operator=(const parse_tree& org) { return copy(org); }
parse_tree& operator=(const subtree& sub)
{ return copy(sub); }
/* Equality and inequality */
bool operator==(const parse_tree& other) const
{ return _root == other._root; }
bool operator !=(const parse_tree& other) const
{ return !operator==(other); }
/* Simple tree statistics */
size_t size(void) const { return _root.size(); }
size_t depth(void) const { return _root.depth(); }
void clear(void) { _root.clear(); pushed.resize(0); }
/* Evaluation (application), with an increasing number of user defined arguments */
template <class RetVal>
void apply(RetVal& v) const
{ _root.apply(v); }
template <class RetVal, class It>
void apply(RetVal& v, It varValues) const
{ _root.apply(v, varValues); }
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>
// 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)
{
do_the_swap(pushed, other.pushed);
_root.swap(other._root);
}
/* Definitions of the iterators */
class base_iterator
{
public :
base_iterator() {}
base_iterator(subtree* n) { node = n; }
base_iterator& operator=(const base_iterator& org)
{ node = org.node; return *this; }
bool operator==(const base_iterator& org) const
{ return node == org.node; }
bool operator!=(const base_iterator& org) const
{ return !operator==(org); }
base_iterator operator+(size_t n) const
{
base_iterator tmp = *this;
for(;n != 0; --n)
{
++tmp;
}
return tmp;
}
base_iterator& operator++(void)
{
subtree* parent = node->get_parent();
if (parent == 0)
{
node = 0;
return *this;
}
// else
subtree::iterator it;
for (it = parent->begin(); it != parent->end(); ++it)
{
if (node == &(*it))
break;
}
if (it == parent->begin())
node = parent;
else
{
node = &(--it)->get_node(0);
}
return *this;
}
base_iterator operator++(int)
{
base_iterator tmp = *this;
operator++();
return tmp;
}
protected :
subtree* node;
};
class iterator : public base_iterator
{
public :
typedef std::forward_iterator_tag iterator_category;
typedef subtree value_type;
typedef size_t distance_type;
typedef size_t difference_type;
typedef subtree* pointer;
typedef subtree& reference;
iterator() : base_iterator() {}
iterator(subtree* n): base_iterator(n) {}
iterator& operator=(const iterator& org)
{ base_iterator::operator=(org); return *this; }
subtree& operator*(void) { return *node; }
subtree* operator->(void) { return node; }
};
class embedded_iterator : public base_iterator
{
public :
typedef std::forward_iterator_tag iterator_category;
typedef T value_type;
typedef size_t distance_type;
typedef size_t difference_type;
typedef T* pointer;
typedef T& reference;
embedded_iterator() : base_iterator() {}
embedded_iterator(subtree* n): base_iterator(n) {}
embedded_iterator& operator=(const embedded_iterator& org)
{ base_iterator::operator=(org); return *this; }
T& operator*(void) { return **node; }
T* operator->(void) { return &**node; }
};
class base_const_iterator
{
public :
base_const_iterator() {}
base_const_iterator(const subtree* n) { node = n; }
base_const_iterator& operator=(const base_const_iterator& org)
{ node = org.node; return *this; }
bool operator==(const base_const_iterator& org) const
{ return node == org.node; }
bool operator!=(const base_const_iterator& org) const
{ return !operator==(org); }
base_const_iterator& operator++(void)
{
const subtree* parent = node->get_parent();
if (parent == 0)
{
node = 0;
return *this;
}
// else
subtree::const_iterator it;
for (it = parent->begin(); it != parent->end(); ++it)
{
if (node == &(*it))
break;
}
if (it == parent->begin())
node = parent;
else
node = &(--it)->get_node(0);
return *this;
}
base_const_iterator operator++(int)
{
base_const_iterator tmp = *this;
operator++();
return tmp;
}
protected :
const subtree* node;
};
class const_iterator : public base_const_iterator
{
public :
typedef std::forward_iterator_tag iterator_category;
typedef const subtree value_type;
typedef size_t distance_type;
typedef size_t difference_type;
typedef const subtree* pointer;
typedef const subtree& reference;
const_iterator() : base_const_iterator() {}
const_iterator(const subtree* n): base_const_iterator(n) {}
const_iterator& operator=(const const_iterator& org)
{ base_const_iterator::operator=(org); return *this; }
const subtree& operator*(void) { return *node; }
const subtree* operator->(void) { return node; }
};
class embedded_const_iterator : public base_const_iterator
{
public :
typedef std::forward_iterator_tag iterator_category;
typedef const T value_type;
typedef size_t distance_type;
typedef size_t difference_type;
typedef const T* pointer;
typedef const T& reference;
embedded_const_iterator() : base_const_iterator() {}
embedded_const_iterator(const subtree* n): base_const_iterator(n) {}
embedded_const_iterator& operator=(const embedded_const_iterator& org)
{ base_const_iterator::operator=(org); return *this; }
embedded_const_iterator operator+(size_t n) const
{
embedded_const_iterator tmp = *this;
for(;n != 0; --n)
{
++tmp;
}
return tmp;
}
const T& operator*(void) const { return **node; }
const T* operator->(void) const { return node->operator->(); }
};
/* Iterator access */
iterator begin(void) { return iterator(&operator[](0)); }
const_iterator begin(void) const { return const_iterator(&operator[](0)); }
iterator end(void) { return iterator(0); }
const_iterator end(void) const { return const_iterator(0);}
embedded_iterator ebegin(void) { return embedded_iterator(&operator[](0)); }
embedded_const_iterator ebegin(void) const { return embedded_const_iterator(&operator[](0)); }
embedded_iterator eend(void) { return embedded_iterator(0); }
embedded_const_iterator eend(void) const { return embedded_const_iterator(0);}
bool empty(void) const { return size() == 0; }
bool valid(void) const { return pushed.empty(); }
/* push_back */
void push_back(const parse_tree<T>& tree)
{
if (!empty())
pushed.push_back(_root);
_root = tree.back();
}
void push_back(const T& t)
{
if (!empty())
pushed.push_back(_root);
_root = t;
for (subtree::iterator it = _root.begin(); it != _root.end(); it++)
{
*it = pushed.back();
pushed.pop_back();
}
}
/* Access to subtrees */
subtree& back(void) { return _root; }
const subtree& back(void) const { return _root; }
subtree& root(void) { return _root; }
const subtree& root(void) const { return _root; }
subtree& front(void) { return _root[0]; }
const subtree& front(void) const { return _root[0]; }
subtree& operator[](size_t i)
{ return const_cast<subtree&>(_root.get_node(i)); }
const subtree& operator[](size_t i) const
{ return _root.get_node(i); }
subtree& get_cumulative(size_t i)
{ return const_cast<subtree&>(_root.get_cumulative(i)); }
const subtree& get_cumulative(size_t i) const
{ return get_cumulative(i); }
private :
parse_tree& copy(const parse_tree& org)
{
_root = org._root;
pushed = org.pushed;
return *this;
}
parse_tree& copy(const subtree& sub)
{ _root = sub; pushed.resize(0); return *this; }
subtree _root;
std::vector<subtree > pushed;
}; // end class parse_tree
} // end namespace gp_parse_tree
namespace std
{ // for use with stlport on MSVC
template <class T> inline
std::forward_iterator_tag iterator_category(gp_parse_tree::parse_tree<T>::embedded_iterator)
{
return std::forward_iterator_tag();
}
template <class T> inline
ptrdiff_t* distance_type(gp_parse_tree::parse_tree<T>::embedded_iterator)
{
return 0;
}
template <class T> inline
std::forward_iterator_tag iterator_category(gp_parse_tree::parse_tree<T>::iterator)
{
return std::forward_iterator_tag();
}
template <class T> inline
ptrdiff_t* distance_type(gp_parse_tree::parse_tree<T>::iterator)
{
return 0;
}
// Put customized swaps also in std...
template<class T> inline
void swap(gp_parse_tree::parse_tree<T>& a, gp_parse_tree::parse_tree<T>& b)
{
a.swap(b);
}
template<class T> inline
void iter_swap(vector<gp_parse_tree::parse_tree<T> >::iterator a, vector<gp_parse_tree::parse_tree<T> > b)
{
a->swap(*b);
}
} // namespace std
#endif

View file

@ -0,0 +1,85 @@
/* -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
-----------------------------------------------------------------------------
rnd_generators.h
Some utility functors for generating random generators:
uniform_generator : generates uniform floats or doubles
random_generator : generates unsigneds, ints etc.
normal_generator : normally distributed floats or doubles
(c) Maarten Keijzer (mak@dhi.dk) and GeNeura Team, 1999, 2000
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact: todos@geneura.ugr.es, http://geneura.ugr.es
*/
//-----------------------------------------------------------------------------
#ifndef eoRND_GENERATORS_H
#define eoRND_GENERATORS_H
#include "eoRNG.h"
/**
The class uniform_generator can be used in the STL generate function
to easily generate random floats and doubles between [0, _max). _max
defaults to 1.0
*/
template <class T = double> class uniform_generator
{
public :
uniform_generator(T _max = T(1.0), eoRng& _rng = rng) : maxim(_max), uniform(_rng) {}
virtual T operator()(void) { return (T) uniform.uniform(maxim); }
private :
T maxim;
eoRng& uniform;
};
/**
The class random_generator can be used in the STL generate function
to easily generate random ints between [0, _max).
*/
template <class T = uint32> class random_generator
{
public :
random_generator(int _max, eoRng& _rng = rng) : maxim(_max), random(_rng) {}
virtual T operator()(void) { return (T) random.random(max); }
private :
T maxim;
eoRng& random;
};
/**
The class normal_generator can be used in the STL generate function
to easily generate gaussian distributed floats and doubles. The user
can supply a standard deviation which defaults to 1.
*/
template <class T = double> class normal_generator
{
public :
normal_generator(T _stdev = T(1.0), eoRng& _rng = rng) : stdev(_stdev), normal(_rng) {}
virtual T operator()(void) { return (T) normal.normal(stdev); }
private :
T stdev;
eoRng& normal;
};
#endif