diff --git a/eo/src/gp/eoParseTree.h b/eo/src/gp/eoParseTree.h index 97181479..4aa82219 100644 --- a/eo/src/gp/eoParseTree.h +++ b/eo/src/gp/eoParseTree.h @@ -40,7 +40,7 @@ using namespace std; /** \defgroup ParseTree - Various functions for a tree-based Genetic Programming + Various functions for tree-based Genetic Programming */ /** eoParseTree : implementation of parse-tree for genetic programming diff --git a/eo/src/gp/eoStParseTreeDepthInit.h b/eo/src/gp/eoStParseTreeDepthInit.h new file mode 100644 index 00000000..f17ad00d --- /dev/null +++ b/eo/src/gp/eoStParseTreeDepthInit.h @@ -0,0 +1,191 @@ +// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + +//----------------------------------------------------------------------------- +// eoStDepthInit.h : initializor strongly type GP +// (c) Jeroen Eggermont 2001 +/* + 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 + jeggermo@liacs.nl + + */ +//----------------------------------------------------------------------------- + +#ifndef eoStParseTreeDepthInit_h +#define eoStParseTreeDepthInit_h + +#include +#include +#include +#include + + +using namespace gp_parse_tree; +using namespace std; + +#define TERMINAL 0 + +#define NONTERMINAL 4 +#define ALL 5 + + /** +\defgroup StParseTree + + Various functions for strongly typed tree-based Genetic Programming. + The StParseTree functions use the same eoParseTree class for the + individual but now each node class must have two additional functions. + \li int type(void) which returns the return type of the node + \li int type(int child) which returns the required type for child 0, 1 or 2 + + Tree pruning strongly typed trees is not possible at the moment. +*/ + +/** eoStDepthInit : the initializer class for strongly typed tree-based genetic programming +\class eoStDepthInit eoStDepthInit.h gp/eoStDepthInit.h +\ingroup StParseTree +*/ + +template +class eoStDepthInit : public eoInit< eoParseTree > +{ + public : + + typedef eoParseTree EoType; + + /** + * Constructor + * @parm _max_depth The maximum depth of a tree + * @param _initializor A vector containing the possible nodes + * @param _grow False results in a full tree, True result is a randomly grown tree + */ + eoStDepthInit( + unsigned _max_depth, + const vector& _node, + const int& _return_type, + bool _grow = true) + : + eoInit(), + max_depth(_max_depth), + return_type(_return_type), + grow(_grow) + { + if(_node.empty()) + { + throw logic_error("eoGpDepthInitializer: uhm, wouldn't you rather give a non-empty set of Nodes?"); + } + + + unsigned int i=0; + int arity=0; + int type=0; + vector node_vector; + for(i=0; i < _node.size(); i++) + { + arity = _node[i].arity(); + type = _node[i].type(); + if(arity==0) + { + node_vector = node[type][TERMINAL]; + node_vector.push_back(_node[i]); + node[type][TERMINAL]= node_vector; + } + else + //if (arity != 0) // non-terminal + { + node_vector = node[type][NONTERMINAL]; + node_vector.push_back(_node[i]); + node[type][NONTERMINAL] = node_vector; + } + node_vector = node[type][ALL]; + node_vector.push_back(_node[i]); + node[type][ALL] = node_vector; + + } + + + } + /// My class name + virtual string className() const { return "eoStDepthInit"; }; + + /**initialize a tree + * @param _tree : the tree to be initialized + */ + void operator()(EoType& _tree) + { + list sequence; + bool good_tree = false; + do + { + sequence.clear(); + good_tree = generate(sequence, max_depth, return_type); + }while (!good_tree); + + parse_tree tmp(sequence.begin(), sequence.end()); + _tree.swap(tmp); + } + private : + bool generate(list& sequence, int the_max, int request_type) + { + + int selected=0; + bool ok = true; + + if (the_max == 1) + { // generate terminals only + if( node[request_type][TERMINAL].empty() ) // no possible terminal node of this type + return false; // we have an invalid tree + else + { + selected = rng.random((node[request_type][TERMINAL]).size()); + sequence.push_front(node[request_type][TERMINAL][selected]); + return true; + } + + } + + int arity=0; + if (grow) + { + selected = rng.random((node[request_type][ALL]).size()); + arity = node[request_type][ALL][selected].arity(); + sequence.push_front(node[request_type][ALL][selected]); + for (int i = 0; i < arity; ++i) + ok &= generate(sequence, the_max - 1, node[request_type][ALL][selected].type(i)); + } + else // full + { + selected = rng.random((node[request_type][NONTERMINAL]).size()); + arity = node[request_type][NONTERMINAL][selected].arity(); + sequence.push_front(node[request_type][NONTERMINAL][selected]); + for (int i = 0; i < arity; ++i) + ok &=generate(sequence, the_max - 1, node[request_type][NONTERMINAL][selected].type(i)); + } + + return ok; + + } + + + + + unsigned max_depth; + map < int, map < int, vector > > node; + + int return_type; + bool grow; +}; + +#endif diff --git a/eo/src/gp/eoStParseTreeOp.h b/eo/src/gp/eoStParseTreeOp.h new file mode 100644 index 00000000..c2e97521 --- /dev/null +++ b/eo/src/gp/eoStParseTreeOp.h @@ -0,0 +1,315 @@ +// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + +//----------------------------------------------------------------------------- +// eoStParseTreeOp.h : crossover and mutation operators for the strongly typed GP +// (c) Jeroen Eggermont 2001 for other mutation operators + +/* + 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 + mak@dhi.dk + jeggermo@liacs.nl + */ +//----------------------------------------------------------------------------- + +#ifndef eoStParseTreeOp_h +#define eoStParseTreeOp_h + +#include +#include +#include +#include + +#include + +// a help function +template +void get_possible_nodes(const EOT &_eo, vector &possible_nodes, const int type) +{ + int n=0; + possible_nodes.clear(); + // collect the possible crossover points in _eo (nodes with the same type) + for(n=0; n < _eo.size(); n++) + if (type == _eo[n]->type()) + possible_nodes.push_back(n); +} + + +/** eoStSubtreeXOver --> subtree xover for strongly typed tree-based genetic programming +\class eoStSubtreeXOver eoStParseTreeOp.h gp/eoStParseTreeOp.h +\ingroup StParseTree +*/ +template +class eoStSubtreeXOver: public eoQuadOp< eoParseTree > { +public: + + typedef eoParseTree EoType; + /** + * Constructor + * @param _max_length the maximum size of an individual + */ + eoStSubtreeXOver( unsigned _max_length) + : eoQuadOp(), max_length(_max_length) {}; + + /// the ckassname + virtual string className() const { return "eoStSubtreeXOver"; }; + + /// Dtor + virtual ~eoStSubtreeXOver () {}; + + /** + * Perform crossover on two individuals + * param _eo1 The first parent individual + * param _eo2 The second parent individual + */ + bool operator()(EoType & _eo1, EoType & _eo2 ) + { + int i = 0; + vector nodes; + int n = 0; + int type = 0; + int j = 0; + set test; + do + { + do // select a random node in _eo1 as crossover point, and check if we didn't try it already + { + i = rng.random(_eo1.size()); + }while(test.count(i) > 0); + + test.insert(i); + + type = _eo1[i]->type(); + + get_possible_nodes(_eo2, nodes, type); + + }while(nodes.empty() && (test.size() < _eo1.size())); + + if (nodes.empty()) // we failed to select a crossover point but tried all points (test.size() == _eo1.size()). + return true; // should this be false ?? + + // we did find at least one possible crossover point in _eo2 + + n = rng.random(nodes.size()); + j = nodes[n]; + + parse_tree::subtree tmp = _eo1[i]; + _eo1[i] = _eo2[j]; // insert subtree + _eo2[j] = tmp; + + // we can't prune anymore + /* + _eo1.pruneTree(max_length); + _eo2.pruneTree(max_length); + */ + + return true; + } + private: + unsigned max_length; +}; + +/** eoStBranchMutation --> replace a strongly typed subtree with a randomly created strongly typed subtree +\class eoStBranchMutation eoStParseTreeOp.h gp/eoStParseTreeOp.h +\ingroup StParseTree + */ +template +class eoStBranchMutation: public eoMonOp< eoParseTree > +{ +public: + + typedef eoParseTree EoType; + /** + * Constructor + * @param _init An instantiation of eoGpDepthInitializer + * @param _max_length the maximum size of an individual + */ + eoStBranchMutation(eoInit& _init, unsigned _max_length) + : eoMonOp(), max_length(_max_length), initializer(_init) + {}; + + /// the class name + virtual string className() const { return "eoStBranchMutation"; }; + + /// Dtor + virtual ~eoStBranchMutation() {}; + + /** + * Mutate an individual + * @param _eo1 The individual that is to be changed + */ + bool operator()(EoType& _eo1 ) + { + int i = rng.random(_eo1.size()); + vector nodes; + int type = _eo1[i]->type(); + int j=0; + int n=0; + + EoType eo2; + + do + { + initializer(eo2); + get_possible_nodes(eo2, nodes, type); + }while (nodes.empty()); + + n = rng.random(nodes.size()); + j = nodes[n]; + + _eo1[i] = eo2[j]; // insert subtree + + // no more pruning + /* + _eo1.pruneTree(max_length); + */ + + return true; + } + +private : + + unsigned max_length; + eoInit& initializer; +}; + + +/** eoStPointMutation --> replace a Node with a Node of the same arity and type +\class eoStPointMutation eoStParseTreeOp.h gp/eoStParseTreeOp.h +\ingroup StParseTree + */ +template +class eoStPointMutation: public eoMonOp< eoParseTree > +{ +public: + + typedef eoParseTree EoType; + + /** + * Constructor + * @param _initializor The vector of Nodes given to the eoGpDepthInitializer + */ + eoStPointMutation( vector& _node) + : eoMonOp() + { + unsigned int i=0; + int arity=0; + int type=0; + vector node_vector; + for(i=0; i < _node.size(); i++) + { + arity = _node[i].arity(); + type = _node[i].type(); + + node_vector = node[type][arity]; + node_vector.push_back(_node[i]); + node[type][arity]= node_vector; + + }; + }; + + /// the class name + virtual string className() const { return "eoStPointMutation"; }; + + /// Dtor + virtual ~eoStPointMutation() {}; + + /** + * Mutate an individual + * @param _eo1 The individual that is to be changed + */ + bool operator()(EoType& _eo1 ) + { + // select a random node i that is to be mutated + int i = rng.random(_eo1.size()); + int arity = _eo1[i].arity(); + int type = _eo1[i]->type(); + int j = rng.random(node[type][arity].size()); + + + _eo1[i] = node[type][arity][j]; + return true; + } + +private : + + map < int, map < int, vector > > node; +}; + + + /** eoStHoistMutation --> replace the individual with one of its strongly typed subtree's +\class eoStHoistMutation eoStParseTreeOp.h gp/eoStParseTreeOp.h +\ingroup StParseTree + */ +template +class eoStHoistMutation: public eoMonOp< eoParseTree > +{ +public: + + typedef eoParseTree EoType; + /** + * Constructor + * @param _init An instantiation of eoStDepthInit + * @param _max_length the maximum size of an individual + */ + eoStHoistMutation(eoInit& _init, unsigned _max_length) + : eoMonOp(), max_length(_max_length), initializer(_init) + {}; + + /// the class name + virtual string className() const { return "eoStHoistMutation"; }; + + /// Dtor + virtual ~eoStHoistMutation() {}; + + /** + * Mutate an individual + * @param _eo1 The individual that is to be changed + */ + bool operator()(EoType& _eo1 ) + { + + vector nodes; + // get the type of the current tree + int type = _eo1[ _eo1.size() - 1 ]->type(); + + + + do + { + initializer(eo2); + get_possible_nodes(eo2, nodes, type); + }while (nodes.empty()); + + // select a subtree-node to replace the current tree + int n = rng.random(nodes.size()); + int i = nodes[n]; + + EoType eo2(_eo1[i]); + + _eo1 = eo2; + + return true; + } + +private : + + unsigned max_length; + eoInit& initializer; +}; + + +#endif