⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tree.c

📁 Genetic Programing of music
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  lil-gp Genetic Programming System, version 1.0, 11 July 1995 *  Copyright (C) 1995  Michigan State University *  *  This program is free software; you can redistribute it and/or modify *  it under the terms of version 2 of the GNU General Public License as *  published by the Free Software Foundation. *  *  This program 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 General Public License for more details. *  *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *   *  Douglas Zongker       (zongker@isl.cps.msu.edu) *  Dr. Bill Punch        (punch@isl.cps.msu.edu) * *  Computer Science Department *  A-714 Wells Hall *  Michigan State University *  East Lansing, Michigan  48824 *  USA *   */#include <lilgp.h>/* * note:  that almost all these functions that recurse through the tree * come in two parts:  the wrapper and the recursive part.  the "standard" * method of traversing a tree like this is to set up a pointer to the * first node in the tree, then subsequent recursive calls step the * pointer forward, traversing the tree in preorder.  the wrapper function * sets up this pointer, then passes the address of that pointer [that's * an (lnode **)] to the recursive part. * * the first function in this file [tree_size()] is commented in detail, * others (which are just variations on this theme) are rather glossed over. * * note:  when I refer to a tree's "size" I almost always mean "how many * lnodes the tree takes to store", NOT how many nodes are in the tree. * watch out for this.  (the major exception is, of course, "tree_size()" * which returns the node count.) *//* * tree_nodes:  return the number of nodes in the tree. */int tree_nodes ( lnode *tree ){     lnode *l = tree;     return tree_nodes_recurse ( &l );}int tree_nodes_recurse ( lnode **l ){     /*      *  *l always points at a function node here; save the function.      */     function *f = (**l).f;     int i, j = 1;     /* step the pointer over the function. */     ++*l;     /* if the function is a terminal, then the recursion bottoms out. */     if ( f->arity == 0 )     {          /* skip the pointer over the ERC value if this node has one. */          if ( f->ephem_gen )               ++*l;          /* return this subtree size. */          return 1;     }     else     {          /* function is not a terminal, so add up its subtrees and return           * the total.           */          switch ( f->type )          {             case FUNC_DATA:             case EVAL_DATA:               for ( i = 0; i < f->arity; ++i )                    j += tree_nodes_recurse ( l );               break;                            case FUNC_EXPR:             case EVAL_EXPR:               for ( i = 0; i < f->arity; ++i )               {                    /* skip the pointer over the skipsize node. */                    ++*l;                    /* add this subtree's size to the total. */                    j += tree_nodes_recurse ( l );               }               break;          }     }          return j;}/* * tree_nodes_internal:  return number of internal (function) nodes in the *     tree. */int tree_nodes_internal ( lnode *data ){     lnode *l = data;     return tree_nodes_internal_recurse ( &l );}int tree_nodes_internal_recurse ( lnode **l ){     function *f = (**l).f;     int i, j = 1;     ++*l;          if ( f->arity == 0 )     {          if ( f->ephem_gen )               ++*l;          return 0;     }     else     {          switch ( f->type )          {             case FUNC_DATA:             case EVAL_DATA:               for ( i = 0; i < f->arity; ++i )                    j += tree_nodes_internal_recurse ( l );               break;             case FUNC_EXPR:             case EVAL_EXPR:               for ( i = 0; i < f->arity; ++i )               {                    ++*l;                    j += tree_nodes_internal_recurse ( l );               }               break;          }     }     return j;}/* * tree_nodes_external:  return number of external (terminal) nodes in the *     tree. */int tree_nodes_external ( lnode *data ){     lnode *l = data;     return tree_nodes_external_recurse ( &l );}int tree_nodes_external_recurse ( lnode **l ){     function *f = (**l).f;     int i, j = 0;     ++*l;          if ( f->arity == 0 )     {          if ( f->ephem_gen )               ++*l;          return 1;     }     else     {          switch ( f->type )          {             case FUNC_DATA:             case EVAL_DATA:               for ( i = 0; i < f->arity; ++i )                    j += tree_nodes_external_recurse ( l ) ;               break;             case FUNC_EXPR:             case EVAL_EXPR:               for ( i = 0; i < f->arity; ++i )               {                    ++*l;                    j += tree_nodes_external_recurse ( l ) ;               }               break;          }     }     return j;}/* * print_tree_array:  print the tree, as an array, on stdout.  primarily *     for debugging. */void print_tree_array ( lnode *data ){     lnode *l = data;     int i = 0;     print_tree_array_recurse ( &l, &i );}void print_tree_array_recurse ( lnode **l, int *index ){     function *f = (**l).f;     int i;     printf ( "%3d: function: \"%s\"\n", *index, f->string );          ++*l;     ++*index;     if ( f->arity == 0 )     {          if ( f->ephem_gen )          {               printf ( "%3d:    value: %s\n", *index, (f->ephem_str)((**l).d->d) );               ++*l;               ++*index;          }     }     else     {          switch ( f->type )          {             case FUNC_DATA:             case EVAL_DATA:               for ( i = 0; i < f->arity; ++i )               {                    print_tree_array_recurse ( l, index );               }               break;             case FUNC_EXPR:             case EVAL_EXPR:               for ( i = 0; i < f->arity; ++i )               {                    printf ( "%3d:    {skip %d}\n", *index, (**l).s );                    ++*l;                    ++*index;                    print_tree_array_recurse ( l, index );               }               break;          }     }}/* * print_tree:  print the tree, as a LISP S-expression, to the given FILE *. */void print_tree ( lnode *data, FILE *fil ){     lnode *c = data;     print_tree_recurse ( &c, fil );     fprintf ( fil, "\n" );}void print_tree_recurse ( lnode **l, FILE *fil ){     function *f;     int i;     f = (**l).f;     fprintf ( fil, " " );     if ( f->arity != 0 )          fprintf ( fil, "(" );          ++*l;     if ( f->ephem_gen )     {          fprintf ( fil, "%s", (f->ephem_str)((**l).d->d) );#ifdef DEBUG          fprintf ( fil, " <%d>", (**l).d->refcount );#endif          ++*l;     }     else          fprintf ( fil, "%s", f->string );          switch ( f->type )     {        case FUNC_DATA:        case EVAL_DATA:          for ( i = 0; i < f->arity; ++i )          {               print_tree_recurse ( l, fil );          }          break;        case FUNC_EXPR:        case EVAL_EXPR:          for ( i = 0; i < f->arity; ++i )          {#ifdef DEBUG                              fprintf ( fil, " {skip %d}", (**l).s );#endif                              ++*l;               print_tree_recurse ( l, fil );          }          break;     }     if ( f->arity != 0 )          fprintf ( fil, ")" );}/* * generate_random_full_tree:  generates, in the given generation space, *     a random full tree of *     the specified depth.  */void generate_random_full_tree ( int space, int depth, function_set *fset ){     int i, j;     int save;     if ( depth == 0 )     {          /* we've reached depth 0, so choose a terminal node for this           * subtree.           */                    i = random_int(fset->terminal_count)+(fset->function_count);          gensp_next(space)->f = (fset->cset)+i;          /* if this terminal is an ERC, then generate one and store it. */          if ( (fset->cset)[i].ephem_gen )               gensp_next(space)->d = new_ephemeral_const ( (fset->cset)+i );          return;     }     /* we're not a depth 0, so generate a non-terminal node. */     i = random_int(fset->function_count);     gensp_next(space)->f = (fset->cset)+i;     /* now generate the node's children. */          switch ( (fset->cset)[i].type )          {             case FUNC_DATA:             case EVAL_DATA:               for ( j = 0; j < (fset->cset)[i].arity; ++j )               {                    /* generate a full tree of depth [depth-1]. */                    generate_random_full_tree ( space, depth-1, fset );               }               break;             case FUNC_EXPR:             case EVAL_EXPR:               for ( j = 0; j < (fset->cset)[i].arity; ++j )               {                    /* yes, so save where the skip value needs to be placed                     * since we don't know what it is yet.                     */                    save = gensp_next_int ( space );                                        /* generate a full tree of depth [depth-1]. */                    generate_random_full_tree ( space, depth-1, fset );                                        /* save the size of the subtree in the skip node, if we need to. */                    gensp[space].data[save].s = gensp[space].used-save-1;                                   }               break;          }          return;     }/* * generate_random_grow_tree:  grow a random tree, of (maximum) depth [depth]. *     works just like genereate_random_full_tree, except that a node with *     depth > 0 can be a terminal. */       void generate_random_grow_tree ( int space, int depth, function_set *fset ){     int i, j;     int save;     if ( depth == 0 )     {          i = random_int(fset->terminal_count)+(fset->function_count);          gensp_next(space)->f = (fset->cset)+i;          if ( (fset->cset)[i].ephem_gen )               gensp_next(space)->d = new_ephemeral_const ( (fset->cset)+i );                    return;     }     /* note that here we can generate a terminal node. */     i = random_int(fset->function_count+fset->terminal_count);     gensp_next(space)->f = (fset->cset)+i;          if ( (fset->cset)[i].arity )     {          switch ( (fset->cset)[i].type )          {             case FUNC_DATA:             case EVAL_DATA:               for ( j = 0; j < (fset->cset)[i].arity; ++j )                    generate_random_grow_tree ( space, depth-1, fset );               break;             case FUNC_EXPR:             case EVAL_EXPR:               for ( j = 0; j < (fset->cset)[i].arity; ++j )               {                    save = gensp_next_int(space);                    generate_random_grow_tree ( space, depth-1, fset );                    gensp[space].data[save].s = gensp[space].used-save-1;               }               break;          }     }     else     {          if ( (fset->cset)[i].ephem_gen )               gensp_next(space)->d = new_ephemeral_const ( (fset->cset)+i );     }     return;}/* * tree_depth:  return the depth of the tree.  a tree with one node has *     depth 0. */int tree_depth ( lnode *data ){     lnode *l = data;     return tree_depth_recurse ( &l );}int tree_depth_recurse ( lnode **l ){     function *f = (**l).f;     int i, j, k = 0;     ++*l;     if ( f->arity == 0 )     {          /* a terminal node; advance the pointer and return 0. */                    if ( f->ephem_gen )               ++*l;          return 0;     }     /* a nonterminal; find the deepest child and return its depth plus one. */               switch ( f->type )          {             case FUNC_DATA:             case EVAL_DATA:               for ( i = 0; i < f->arity; ++i )               {                    j = tree_depth_recurse ( l );                    if ( j > k )                         k = j;               }               break;             case FUNC_EXPR:             case EVAL_EXPR:               for ( i = 0; i < f->arity; ++i )               {                    ++*l;                    j = tree_depth_recurse ( l );                    if ( j > k )                         k = j;               }               break;          }          return k+1;}int tree_depth_to_subtree ( lnode *data, lnode *sub ){     lnode *l = data;     return tree_depth_to_subtree_recurse ( &l, sub, 0 );}int tree_depth_to_subtree_recurse ( lnode **l, lnode *sub, int depth ){     function *f = (**l).f;     int i, j;     if ( *l == sub )          return depth;     ++*l;     if ( f->arity == 0 )     {          if ( f->ephem_gen )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -