# eoParseTreeDepthInit.h

    00001 // -*- mode: c++; c-indent-level: 4; c++-member-init-indent: 8; comment-column: 35; -*-
    00002
    00003 //-----------------------------------------------------------------------------
    00004 // eoParseTreeDepthInit.h : initializor for eoParseTree class
    00005 // (c) Maarten Keijzer 2000  Jeroen Eggermont 2002
    00006 /*
    00007     This library is free software; you can redistribute it and/or
    00008     modify it under the terms of the GNU Lesser General Public
    00009     License as published by the Free Software Foundation; either
    00010     version 2 of the License, or (at your option) any later version.
    00011
    00012     This library is distributed in the hope that it will be useful,
    00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00015     Lesser General Public License for more details.
    00016
    00017     You should have received a copy of the GNU Lesser General Public
    00018     License along with this library; if not, write to the Free Software
    00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00020
    00021     Contact: todos@geneura.ugr.es, http://geneura.ugr.es
    00022              mak@dhi.dk
    00023              jeggermo@liacs.nl
    00024
    00025  */
    00026 //-----------------------------------------------------------------------------
    00027
    00028 #ifndef eoParseTreeDepthInit_h
    00029 #define eoParseTreeDepthInit_h
    00030
    00031 #include <EO.h>
    00032 #include <gp/eoParseTree.h>
    00033 #include <eoInit.h>
    00034 #include <eoOp.h>
    00035 #include <eoPop.h>
    00036
    00037 using namespace gp_parse_tree;
    00038
    00044 // eoGpDepthInitializer is defined for backward compatibility
    00045 #define eoGpDepthInitializer eoParseTreeDepthInit
    00046
    00047 template <class FType, class Node>
    00048 class eoParseTreeDepthInit : public eoInit< eoParseTree<FType, Node> >
    00049 {
    00050     protected:
    00051         // a binary predicate for sorting
    00052         // hopefully this will work with M$VC++ 6.0
    00053         struct lt_arity:public std::binary_function<Node,Node,bool>
    00054         {
    00055                 bool operator()(const Node &_node1, const Node &_node2) { return (_node1.arity() < _node2.arity());};
    00056         };
    00057
    00058     public :
    00059
    00060     typedef eoParseTree<FType, Node> EoType;
    00061
    00069         eoParseTreeDepthInit(
    00070         unsigned _max_depth,
    00071         const std::vector<Node>& _initializor,
    00072         bool _grow = true,
    00073         bool _ramped_half_and_half = false)
    00074             :
    00075             eoInit<EoType>(),
    00076                         max_depth(_max_depth),
    00077                         initializor(_initializor),
    00078                         grow(_grow),
    00079                         ramped_half_and_half(_ramped_half_and_half),
    00080                         current_depth(_max_depth)
    00081     {
    00082       if(initializor.empty())
    00083       {
    00084         throw std::logic_error("eoParseTreeDepthInit: uhm, wouldn't you rather give a non-empty set of Nodes?");
    00085       }
    00086       // lets sort the initializor std::vector according to  arity (so we can be sure the terminals are in front)
    00087       // 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
    00088       stable_sort(initializor.begin(), initializor.end(), lt_arity());
    00089     }
    00091         virtual std::string className() const { return "eoParseTreeDepthInit"; };
    00092
    00096     void operator()(EoType& _tree)
    00097         {
    00098         std::list<Node> sequence;
    00099         generate(sequence, current_depth);
    00100
    00101         parse_tree<Node> tmp(sequence.begin(), sequence.end());
    00102         _tree.swap(tmp);
    00103
    00104         if(ramped_half_and_half)
    00105         {
    00106                 if(grow)
    00107                 {
    00108                         if (current_depth > 2)
    00109                                 current_depth--;
    00110                         else
    00111                                 current_depth = max_depth;
    00112                 }
    00113                 // change the grow method from 'grow' to 'full' or from 'full' to 'grow'
    00114                 grow = !grow;
    00115         };
    00116
    00117         }
    00118    private :
    00119     void generate(std::list<Node>& sequence, int the_max, int last_terminal = -1)
    00120     {
    00121             if (last_terminal == -1)
    00122             { // check where the last terminal in the sequence resides
    00123             typename std::vector<Node>::iterator it;
    00124                     for (it = initializor.begin(); it != initializor.end(); ++it)
    00125                     {
    00126                             if (it->arity() > 0)
    00127                                     break;
    00128                     }
    00129
    00130                     last_terminal = it - initializor.begin();
    00131             }
    00132
    00133             if (the_max == 1)
    00134             { // generate terminals only
    00135                     typename std::vector<Node>::iterator it = initializor.begin() + rng.random(last_terminal);
    00136                     it->randomize();
    00137                     sequence.push_front(*it);
    00138                     return;
    00139             }
    00140
    00141             typename std::vector<Node>::iterator what_it;
    00142
    00143             if (grow)
    00144             {
    00145                     what_it = initializor.begin() + rng.random(initializor.size());
    00146             }
    00147             else // full
    00148             {
    00149                     what_it = initializor.begin() + last_terminal + rng.random(initializor.size() - last_terminal);
    00150             }
    00151
    00152         what_it->randomize();
    00153
    00154             sequence.push_front(*what_it);
    00155
    00156             for (int i = 0; i < what_it->arity(); ++i)
    00157                     generate(sequence, the_max - 1, last_terminal);
    00158     }
    00159
    00160
    00161
    00162         unsigned max_depth;
    00163         std::vector<Node> initializor;
    00164         bool grow;
    00165         bool ramped_half_and_half;
    00166         unsigned current_depth;
    00167 };
    00168
    00178 template <class FType, class Node>
    00179 void  eoInitRampedHalfAndHalf(eoPop< eoParseTree<FType,Node> > &pop, unsigned int population_size, unsigned int init_max_depth, std::vector<Node> &initializor)
    00180 {
    00181         typedef eoParseTree<FType,Node> EoType;
    00182         typedef eoPop< EoType > Pop;
    00183
    00184         unsigned int M = init_max_depth - 1;
    00185         unsigned int part_pop_size = population_size / (2*M);
    00186         unsigned int m=0;
    00187
    00188         std::cerr << "EO WARNING: Ramped Half and Half Initialization is now supported by eoParseTreeDepthInit." << std::endl;
    00189         std::cerr << "            This function is now obsolete and might be removed in the future so you should"<< std::endl;
    00190         std::cerr << "            update your code to use: " << std::endl << std::endl;
    00191         std::cerr << "            eoParseTreeDepthInit( _max_depth, _initializer, bool _grow, bool _ramped_half_and_half)" << std::endl << std::endl;
    00192
    00193         pop.clear();
    00194
    00195         // initialize with Depth's (D) -> 2
    00196         for(m=init_max_depth; m >= 2; m--)
    00197         {
    00198                 eoParseTreeDepthInit<FType, Node> grow_initializer(m, initializor, true);
    00199                 Pop grow(part_pop_size, grow_initializer);
    00200                 pop.insert(pop.begin(), grow.begin(), grow.end());
    00201
    00202                 eoParseTreeDepthInit<FType, Node> full_initializer(m, initializor, false);
    00203                 Pop full(part_pop_size, full_initializer);
    00204                 pop.insert(pop.begin(), full.begin(), full.end());
    00205         }
    00206
    00207         bool g = true;
    00208         while (pop.size() < population_size)
    00209         {
    00210                 eoParseTreeDepthInit<FType, Node> initializer(init_max_depth, initializor, g);
    00211                 Pop p(1, initializer);
    00212                 pop.insert(pop.begin(), p.begin(), p.end());
    00213                 g= !g;
    00214         }
    00215 }
    00216
    00217
    00218 #endif