From 21e42be6d3dd284b38a4872ca2033080e7e3122c Mon Sep 17 00:00:00 2001 From: jeggermo Date: Tue, 17 Jul 2001 08:58:52 +0000 Subject: [PATCH] small documentation change for eoParseTree.h. added a depth initializer for strongly typed genetic programming added subtree xover for strongly typed genetic programming added branch mutation for strongly typed genetic programming added point mutation for strongly typed genetic programming added hoist mutation for strongly typed genetic programming --- eo/src/gp/eoParseTree.h | 2 +- eo/src/gp/eoStParseTreeDepthInit.h | 191 +++++++++++++++++ eo/src/gp/eoStParseTreeOp.h | 315 +++++++++++++++++++++++++++++ 3 files changed, 507 insertions(+), 1 deletion(-) create mode 100644 eo/src/gp/eoStParseTreeDepthInit.h create mode 100644 eo/src/gp/eoStParseTreeOp.h 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