From a611939e684885a63d7b333c6ffaec0fd8148069 Mon Sep 17 00:00:00 2001 From: jeggermo Date: Mon, 2 Jul 2001 13:31:04 +0000 Subject: [PATCH] Changed the directory structure for gp now: eoParseTree <-- the eoParseTree class eoParseTreeDepthInit <-- the eoParseTree depth initializer (eoGpDepthInitializer) eoParseTreeOp <-- the operators (xover and mutation) base documentation written for: * eoParseTree * eoGpDepthInitializer * eoSubtreeXOver * eoBranchMutation * eoPointMutation * eoExpansionMutation * eoCollapseSubtreeMutation * eoHoistMutation I also created a group ParseTree which contains all classes related to eoParseTree eoGpMutate.h has been removed (merged with eoParseTree operators into eoParseTreeOp --- eo/app/gpsymreg/fitness.h | 10 +- eo/app/gpsymreg/main.cc | 5 +- eo/doc/eo.cfg | 2 +- eo/src/gp/Makefile.am | 2 +- eo/src/gp/eoParseTree.h | 236 ++++++-------------- eo/src/gp/eoParseTreeDepthInit.h | 145 ++++++++++++ eo/src/gp/{eoGpMutate.h => eoParseTreeOp.h} | 142 +++++++++--- 7 files changed, 342 insertions(+), 200 deletions(-) create mode 100644 eo/src/gp/eoParseTreeDepthInit.h rename eo/src/gp/{eoGpMutate.h => eoParseTreeOp.h} (66%) diff --git a/eo/app/gpsymreg/fitness.h b/eo/app/gpsymreg/fitness.h index e432b826..eca800f0 100644 --- a/eo/app/gpsymreg/fitness.h +++ b/eo/app/gpsymreg/fitness.h @@ -43,7 +43,7 @@ using namespace std; class MinimizingFitnessTraits : public eoParetoFitnessTraits { public : - static bool maximizing(int which) { return false;} // we want to minimize both fitnesses} + static bool maximizing(int which) { return false;} // we want to minimize both fitnesses static unsigned nObjectives() { return 2;} // the number of fitnesses } }; @@ -148,7 +148,7 @@ void init(vector &initSequence) } // next we add the unary functions - /* + initSequence.push_back( NEGATE ); initSequence.push_back( SIN ); initSequence.push_back( COS ); @@ -162,14 +162,14 @@ void init(vector &initSequence) initSequence.push_back( MULTIPLIES ); initSequence.push_back( DIVIDE ); initSequence.push_back( POW ); - */ + // and the binary operators initSequence.push_back( OpPLUS); initSequence.push_back( OpMINUS ); - /* + initSequence.push_back( OpMULTIPLIES ); initSequence.push_back( OpDIVIDE ); - */ + initSequence.push_back( OpPOW ); diff --git a/eo/app/gpsymreg/main.cc b/eo/app/gpsymreg/main.cc index 53ef6b36..6471dd8a 100644 --- a/eo/app/gpsymreg/main.cc +++ b/eo/app/gpsymreg/main.cc @@ -23,7 +23,6 @@ #include #include -#include #include using namespace gp_parse_tree; @@ -84,7 +83,9 @@ int main(int argc, char *argv[]) // define X-OVER - eoSubtreeXOver xover(parameter.MaxSize); + + eoSubtreeXOver xover(parameter.MaxSize); + // define MUTATION eoBranchMutation mutation(initializer, parameter.MaxSize); // eoExpansionMutation mutation(initializer, parameter.MaxSize); diff --git a/eo/doc/eo.cfg b/eo/doc/eo.cfg index 49b1efdc..621e754c 100644 --- a/eo/doc/eo.cfg +++ b/eo/doc/eo.cfg @@ -214,7 +214,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = ../src/obsolete ../src/gp +EXCLUDE = ../src/obsolete # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude diff --git a/eo/src/gp/Makefile.am b/eo/src/gp/Makefile.am index d4b58753..1775610a 100644 --- a/eo/src/gp/Makefile.am +++ b/eo/src/gp/Makefile.am @@ -5,4 +5,4 @@ ############################################################################### libeoincdir = $(includedir)/eo/gp -libeoinc_HEADERS = eoParseTree.h node_pool.h parse_tree.h eoGpMutate.h +libeoinc_HEADERS = eoParseTree.h node_pool.h parse_tree.h eoParseTreeDepthInit.h eoParseTreeOp.h diff --git a/eo/src/gp/eoParseTree.h b/eo/src/gp/eoParseTree.h index 7b07c85e..97181479 100644 --- a/eo/src/gp/eoParseTree.h +++ b/eo/src/gp/eoParseTree.h @@ -1,5 +1,31 @@ -#ifndef EO_PARSE_TREE_H -#define EO_PARSE_TREE_H +// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + +//----------------------------------------------------------------------------- +// eoParseTree.h : eoParseTree class (for Tree-based Genetic Programming) +// (c) Maarten Keijzer 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 + mak@dhi.dk + + */ +//----------------------------------------------------------------------------- + +#ifndef eoParseTree_h +#define eoParseTree_h #include @@ -11,6 +37,18 @@ using namespace gp_parse_tree; using namespace std; +/** +\defgroup ParseTree + + Various functions for a tree-based Genetic Programming +*/ + +/** eoParseTree : implementation of parse-tree for genetic programming +\class eoParseTree eoParseTree.h gp/eoParseTree.h +\ingroup ParseTree +*/ + + template class eoParseTree : public EO, public parse_tree { @@ -18,9 +56,20 @@ public : typedef parse_tree::subtree Subtree; + /** + * Default Constructor + */ eoParseTree(void) {} + /** + * Copy Constructor + * @param tree The tree to copy + */ eoParseTree(const parse_tree& tree) : parse_tree(tree) {} + /** + * To prune me to a certain size + * @param _size My maximum size + */ virtual void pruneTree(unsigned _size) { if (_size < 1) @@ -32,20 +81,34 @@ public : } } + /** + * To read me from a stream + * @param is The istream + */ + eoParseTree(std::istream& is) : EO(), parse_tree() { readFrom(is); } + /// My class name string className(void) const { return "eoParseTree"; } + /** + * To print me on a stream + * @param os The ostream + */ void printOn(std::ostream& os) const { os << fitness() << ' '; std::copy(ebegin(), eend(), ostream_iterator(os)); } - + + /** + * To read me from a stream + * @param is The istream + */ void readFrom(std::istream& is) { FType fit; @@ -58,6 +121,7 @@ public : } }; +// friend function to print eoParseTree template std::ostream& operator<<(std::ostream& os, const eoParseTree& eot) { @@ -65,6 +129,7 @@ std::ostream& operator<<(std::ostream& os, const eoParseTree& eot) return os; } +// friend function to read eoParseTree template std::istream& operator>>(std::istream& is, eoParseTree& eot) { @@ -72,167 +137,8 @@ std::istream& operator>>(std::istream& is, eoParseTree& eot) return is; } -template -bool lt_arity(const Node &node1, const Node &node2) -{ - return (node1.arity() < node2.arity()); -} - -template -class eoGpDepthInitializer : public eoInit< eoParseTree > -{ - public : - - typedef eoParseTree EoType; - - eoGpDepthInitializer( - unsigned _max_depth, - const vector& _initializor, - bool _grow = true) - : - eoInit(), - max_depth(_max_depth), - initializor(_initializor), - grow(_grow) - { - if(initializor.empty()) - { - throw logic_error("eoGpDepthInitializer: uhm, wouldn't you rather give a non-empty set of Nodes?"); - } - // lets sort the initializor vector according to arity (so we can be sure the terminals are in front) - // we use stable_sort so that if element i was in front of element j and they have the same arity i remains in front of j - stable_sort(initializor.begin(), initializor.end(), lt_arity); - } - - virtual string className() const { return "eoDepthInitializer"; }; - - void operator()(EoType& _tree) - { - list sequence; - - generate(sequence, max_depth); - - parse_tree tmp(sequence.begin(), sequence.end()); - _tree.swap(tmp); - } - - 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 eoQuadOp< eoParseTree > { -public: - - typedef eoParseTree EoType; - - eoSubtreeXOver( unsigned _max_length) - : eoQuadOp(), max_length(_max_length) {}; - - virtual string className() const { return "eoSubtreeXOver"; }; - - /// Dtor - virtual ~eoSubtreeXOver () {}; - - bool operator()(EoType & _eo1, EoType & _eo2 ) - { - int i = rng.random(_eo1.size()); - int j = rng.random(_eo2.size()); - - parse_tree::subtree tmp = _eo1[i]; - _eo1[i] = _eo2[j]; // insert subtree - _eo2[j] = tmp; - - _eo1.pruneTree(max_length); - _eo2.pruneTree(max_length); - - return true; - } - - unsigned max_length; -}; - -template -class eoBranchMutation: public eoMonOp< eoParseTree > -{ -public: - - typedef eoParseTree EoType; - - eoBranchMutation(eoInit& _init, unsigned _max_length) - : eoMonOp(), max_length(_max_length), initializer(_init) - {}; - - virtual string className() const { return "eoBranchMutation"; }; - - /// Dtor - virtual ~eoBranchMutation() {}; - - bool operator()(EoType& _eo1 ) - { - int i = rng.random(_eo1.size()); - - EoType eo2; - initializer(eo2); - - int j = rng.random(eo2.size()); - - _eo1[i] = eo2[j]; // insert subtree - - _eo1.pruneTree(max_length); - - return true; - } - -private : - - unsigned max_length; - eoInit& initializer; -}; - +// for backward compatibility +#include +#include #endif diff --git a/eo/src/gp/eoParseTreeDepthInit.h b/eo/src/gp/eoParseTreeDepthInit.h new file mode 100644 index 00000000..ca9be86b --- /dev/null +++ b/eo/src/gp/eoParseTreeDepthInit.h @@ -0,0 +1,145 @@ +// -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- + +//----------------------------------------------------------------------------- +// eoParseTreeDepthInit.h : initializor for eoParseTree class +// (c) Maarten Keijzer 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 + mak@dhi.dk + + */ +//----------------------------------------------------------------------------- + +#ifndef eoParseTreeDepthInit_h +#define eoParseTreeDepthInit_h + +#include +#include +#include +#include + +using namespace gp_parse_tree; +using namespace std; + +// we need this for sorting the initializor vector +template +bool lt_arity(const Node &node1, const Node &node2) +{ + return (node1.arity() < node2.arity()); +} + +/** eoGpDepthInitializer : the initializer class for eoParseTree +\class eoGpDepthInitializer eoParseTreeDepthInit.h gp/eoParseTreeDepthInit.h +\ingroup ParseTree +*/ + +template +class eoGpDepthInitializer : 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 + */ + eoGpDepthInitializer( + unsigned _max_depth, + const vector& _initializor, + bool _grow = true) + : + eoInit(), + max_depth(_max_depth), + initializor(_initializor), + grow(_grow) + { + if(initializor.empty()) + { + throw logic_error("eoGpDepthInitializer: uhm, wouldn't you rather give a non-empty set of Nodes?"); + } + // lets sort the initializor vector according to arity (so we can be sure the terminals are in front) + // we use stable_sort so that if element i was in front of element j and they have the same arity i remains in front of j + stable_sort(initializor.begin(), initializor.end(), lt_arity); + } + /// My class name + virtual string className() const { return "eoDepthInitializer"; }; + + /**initialize a tree + * @param _tree : the tree to be initialized + */ + void operator()(EoType& _tree) + { + list sequence; + + generate(sequence, max_depth); + + parse_tree tmp(sequence.begin(), sequence.end()); + _tree.swap(tmp); + } + private : + 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); + } + + + + + unsigned max_depth; + std::vector initializor; + bool grow; +}; + +#endif diff --git a/eo/src/gp/eoGpMutate.h b/eo/src/gp/eoParseTreeOp.h similarity index 66% rename from eo/src/gp/eoGpMutate.h rename to eo/src/gp/eoParseTreeOp.h index 36275480..1af31add 100644 --- a/eo/src/gp/eoGpMutate.h +++ b/eo/src/gp/eoParseTreeOp.h @@ -1,8 +1,9 @@ // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*- //----------------------------------------------------------------------------- -// eoGpMutate.h : GP mutation -// (c) Jeroen Eggermont 2001 for mutation operators +// eoParseTreeOp.h : crossover and mutation operator for the eoParseTree class +// (c) Maarten Keijzer 2000 for eoSubtreeXOver, eoBranchMutation +// (c) Jeroen Eggermont 2001 for other mutation operators /* This library is free software; you can redistribute it and/or @@ -20,27 +21,114 @@ 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 eoGpMutate_h -#define eoGpMutate_h - -//----------------------------------------------------------------------------- - -#include -#include -#include - +#ifndef eoParseTreeOp_h +#define eoParseTreeOp_h #include #include -#include -#include -using namespace gp_parse_tree; -using namespace std; +#include + +/** eoSubtreeXOver --> subtree xover +\class eoSubtreeXOver eoParseTreeOp.h gp/eoParseTreeOp.h +\ingroup ParseTree +*/ +template +class eoSubtreeXOver: public eoQuadOp< eoParseTree > { +public: + + typedef eoParseTree EoType; + /** + * Constructor + * @param _max_length the maximum size of an individual + */ + eoSubtreeXOver( unsigned _max_length) + : eoQuadOp(), max_length(_max_length) {}; + + /// the ckassname + virtual string className() const { return "eoSubtreeXOver"; }; + + /// Dtor + virtual ~eoSubtreeXOver () {}; + + /** + * 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 = rng.random(_eo1.size()); + int j = rng.random(_eo2.size()); + + parse_tree::subtree tmp = _eo1[i]; + _eo1[i] = _eo2[j]; // insert subtree + _eo2[j] = tmp; + + _eo1.pruneTree(max_length); + _eo2.pruneTree(max_length); + + return true; + } + private: + unsigned max_length; +}; + +/** eoBranchMutation --> replace a subtree with a randomly created subtree +\class eoBranchMutation eoParseTreeOp.h gp/eoParseTreeOp.h +\ingroup ParseTree + */ +template +class eoBranchMutation: public eoMonOp< eoParseTree > +{ +public: + + typedef eoParseTree EoType; + /** + * Constructor + * @param _init An instantiation of eoGpDepthInitializer + * @param _max_length the maximum size of an individual + */ + eoBranchMutation(eoInit& _init, unsigned _max_length) + : eoMonOp(), max_length(_max_length), initializer(_init) + {}; + + /// the class name + virtual string className() const { return "eoBranchMutation"; }; + + /// Dtor + virtual ~eoBranchMutation() {}; + + /** + * Mutate an individual + * @param _eo1 The individual that is to be changed + */ + bool operator()(EoType& _eo1 ) + { + int i = rng.random(_eo1.size()); + + EoType eo2; + initializer(eo2); + + int j = rng.random(eo2.size()); + + _eo1[i] = eo2[j]; // insert subtree + + _eo1.pruneTree(max_length); + + return true; + } + +private : + + unsigned max_length; + eoInit& initializer; +}; // Additional Mutation operators from // TITLE:"Genetic Programming~An Introduction" @@ -51,7 +139,8 @@ using namespace std; // For the eoParseTree class /** eoPointMutation --> replace a Node with a Node of the same arity -\class eoPointMutation eoGpMutate.h gp/eoGpMutate.h +\class eoPointMutation eoParseTreeOp.h gp/eoParseTreeOp.h +\ingroup ParseTree */ template @@ -59,7 +148,7 @@ class eoPointMutation: public eoMonOp< eoParseTree > { public: - typedef eoParseTree EoType; + typedef eoParseTree EoType; /** * Constructor @@ -107,7 +196,8 @@ private : }; /** eoExpansionMutation --> replace a terminal with a randomly created subtree -\class eoExpansionMutation eoGpMutate.h gp/eoGpMutate.h +\class eoExpansionMutation eoParseTreeOp.h gp/eoParseTreeOp.h +\ingroup ParseTree */ template @@ -174,7 +264,8 @@ private : }; /** eoCollapseSubtree --> replace a subtree with a randomly chosen terminal -\class eoCollapseSubtreeMutation eoGpMutate.h gp/eoGpMutate.h +\class eoCollapseSubtreeMutation eoParseTreeOp.h gp/eoParseTreeOp.h +\ingroup ParseTree */ template @@ -182,7 +273,7 @@ class eoCollapseSubtreeMutation: public eoMonOp< eoParseTree > { public: - typedef eoParseTree EoType; + typedef eoParseTree EoType; /** * Constructor * @param _init An instantiation of eoGpDepthInitializer @@ -236,11 +327,9 @@ private : }; - - - -/** eoHoist --> replace the individual with one of its subtree's -\class eoHoist eoGpMutate.h gp/eoGpMutate.h +/** eoHoistMutation --> replace the individual with one of its subtree's +\class eoHoistMutation eoParseTreeOp.h gp/eoParseTreeOp.h +\ingroup ParseTree */ template @@ -248,9 +337,10 @@ class eoHoistMutation: public eoMonOp< eoParseTree > { public: - typedef eoParseTree EoType; + typedef eoParseTree EoType; /** * Constructor + * @param none */ eoHoistMutation() : eoMonOp()