diff --git a/eo/src/gp/eoParseTree.h b/eo/src/gp/eoParseTree.h new file mode 100644 index 00000000..7bac6125 --- /dev/null +++ b/eo/src/gp/eoParseTree.h @@ -0,0 +1,242 @@ +#ifndef EO_PARSE_TREE_H +#define EO_PARSE_TREE_H + +#include + +#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 eoParseTree : public EO, public parse_tree +{ +public : + + typedef typename parse_tree::subtree Type; + + eoParseTree(void) : EO(), parse_tree() {} + eoParseTree(unsigned _size, eoRnd& _rnd) + : EO(), parse_tree(_rnd()) + { + pruneTree(_size); + } + eoParseTree(eoRnd& _rnd) + : EO(), parse_tree(_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(), parse_tree() + { + readFrom(is); + } + + string className(void) const { return "eoParseTree"; } + + void printOn(std::ostream& os) const + { + os << fitness() << ' '; + + std::copy(ebegin(), eend(), ostream_iterator(os)); + } + + void readFrom(std::istream& is) + { + FType fit; + + is >> fit; + + fitness(fit); + + std::copy(istream_iterator(is), istream_iterator(), back_inserter(*this)); + } +}; + +template +std::ostream& operator<<(std::ostream& os, const eoParseTree& eot) +{ + eot.printOn(os); + return os; +} + +template +std::istream& operator>>(std::istream& is, eoParseTree& eot) +{ + eot.readFrom(is); + return is; +} + + +template +class eoGpDepthInitializer : public eoRnd< eoParseTree::Type > +{ + public : + + typedef eoParseTree EoType; + + eoGpDepthInitializer( + unsigned _max_depth, + const vector& _initializor, + bool _grow = true) + : + eoRnd(), + max_depth(_max_depth), + initializor(_initializor), + grow(_grow) + {} + + virtual string className() const { return "eoDepthInitializer"; }; + + EoType::Type operator()(void) + { + list sequence; + + generate(sequence, max_depth); + + parse_tree tree(sequence.begin(), sequence.end()); + + return tree.root(); + } + + void generate(list& sequence, int the_max, int last_terminal = -1) + { + if (last_terminal == -1) + { // check where the last terminal in the sequence resides + vector::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::iterator it = initializor.begin() + rng.random(last_terminal); + sequence.push_front(*it); + return; + } + + vector::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 initializor; + bool grow; +}; + +template +class eoSubtreeXOver: public eoGeneralOp< eoParseTree > { +public: + + typedef eoParseTree EoType; + + eoSubtreeXOver( unsigned _max_length) + : eoGeneralOp(), max_length(_max_length) {}; + + virtual string className() const { return "eoSubtreeXOver"; }; + + /// Dtor + virtual ~eoSubtreeXOver () {}; + + void operator()(eoIndiSelector& _source, eoInserter& _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 eoBranchMutation: public eoGeneralOp< eoParseTree > +{ +public: + + typedef eoParseTree EoType; + + eoBranchMutation(eoRnd& _init, unsigned _max_length) + : eoGeneralOp(), max_length(_max_length), initializer(_init) + {}; + + virtual string className() const { return "eoBranchMutation"; }; + + /// Dtor + virtual ~eoBranchMutation() {}; + + void operator()(eoIndiSelector& _source, eoInserter& _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& initializer; +}; + + +#endif diff --git a/eo/src/gp/node_pool.h b/eo/src/gp/node_pool.h new file mode 100644 index 00000000..f541d5f0 --- /dev/null +++ b/eo/src/gp/node_pool.h @@ -0,0 +1,297 @@ + +#ifndef node_pool_h +#define node_pool_h + +class MemPool +{ +public : + + MemPool(unsigned int sz) : esize(sznext; + delete p; + } + } + + void* allocate() + { + if (head == 0) grow(); + Link* p = head; + head = p->next; + return static_cast(p); + } + + void deallocate(void* b) + { + Link* p = static_cast(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(p)->next = + reinterpret_cast(p + esize); + } + + reinterpret_cast(last)->next = 0; + head = reinterpret_cast(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 Node_alloc +{ +public : + + T* allocate(void) + { + T* t = static_cast(mem.allocate()); + t = new (t) T; + return t; + } + + T* construct(const T& org) + { + T* t = static_cast(mem.allocate()); + t = new (t) T(org); + return t; + } + + void deallocate(T* t) + { + t->~T(); // call destructor + mem.deallocate(static_cast(t)); + } + +private : + static MemPool mem; +}; + + +template +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 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 Tree_alloc +{ +public : + Tree_alloc() {} + + T* allocate(size_t arity) + { + T* t; + + switch(arity) + { + + case 0 : return 0; + case 1 : + { + t = static_cast(mem1.allocate()); + new (t) T; + break; + } + case 2 : + { + t = static_cast(mem2.allocate()); + new (t) T; + new (&t[1]) T; + break; + } + case 3 : + { + t = static_cast(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(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) + { + case 0: return; + case 3 : + { + t[2].~T(); t[1].~T(); t[0].~T(); + mem3.deallocate(static_cast(t)); + return; + } + case 2 : + { + t[1].~T(); t[0].~T(); + mem2.deallocate(static_cast(t)); + return; + } + case 1 : + { + t[0].~T(); + mem1.deallocate(static_cast(t)); + return; + } + default : + { + delete [] t; + return; + } + } + } + + +private : + static MemPool mem1; + static MemPool mem2; + static MemPool mem3; +}; + +// 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; + +#endif diff --git a/eo/src/gp/parse_tree.h b/eo/src/gp/parse_tree.h new file mode 100644 index 00000000..ea971bbf --- /dev/null +++ b/eo/src/gp/parse_tree.h @@ -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::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() 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 + 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 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(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 + +*/ + +#include +#include // 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 +inline void do_the_swap(T& a, T& b) +{ + T tmp = a; + a = b; + b = tmp; +} + +template 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 node_allocator; + Tree_alloc tree_allocator; +#else + Standard_Node_alloc node_allocator; + Standard_alloc 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 + 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 + void apply(RetVal& v) const { (*content)(v, begin()); } + + template + void apply(RetVal& v, It values) const + { + (*content)(v, begin(), values); + } + + 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 + 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; } + 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(imp_select_cumulative(which)); } + + subtree& get_node(size_t which) + { return const_cast(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 + 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 + 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 + void apply(RetVal& v) const + { _root.apply(v); } + + template + void apply(RetVal& v, It varValues) const + { _root.apply(v, varValues); } + + 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 + // 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) + { + 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& 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(_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(_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 pushed; +}; // end class parse_tree + + +} // end namespace gp_parse_tree + +namespace std +{ // for use with stlport on MSVC + +template inline +std::forward_iterator_tag iterator_category(gp_parse_tree::parse_tree::embedded_iterator) +{ + return std::forward_iterator_tag(); +} + +template inline +ptrdiff_t* distance_type(gp_parse_tree::parse_tree::embedded_iterator) +{ + return 0; +} + +template inline +std::forward_iterator_tag iterator_category(gp_parse_tree::parse_tree::iterator) +{ + return std::forward_iterator_tag(); +} + +template inline +ptrdiff_t* distance_type(gp_parse_tree::parse_tree::iterator) +{ + return 0; +} + +// Put customized swaps also in std... + +template inline +void swap(gp_parse_tree::parse_tree& a, gp_parse_tree::parse_tree& b) +{ + a.swap(b); +} + +template inline +void iter_swap(vector >::iterator a, vector > b) +{ + a->swap(*b); +} + + +} // namespace std + + +#endif diff --git a/eo/src/utils/rnd_generators.h b/eo/src/utils/rnd_generators.h new file mode 100644 index 00000000..5074af01 --- /dev/null +++ b/eo/src/utils/rnd_generators.h @@ -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 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 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 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