186 lines
4.5 KiB
C
186 lines
4.5 KiB
C
|
/* 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>
|
||
|
|
||
|
/* pretty_print_tree()
|
||
|
*
|
||
|
* print a tree as an S-expression, indenting functions to show
|
||
|
* structure.
|
||
|
*/
|
||
|
|
||
|
void pretty_print_tree ( lnode *data, FILE *fil )
|
||
|
{
|
||
|
lnode *l = data;
|
||
|
int *indent;
|
||
|
int *istep;
|
||
|
|
||
|
/* indent is a table, parallel to the tree's array, of indentation
|
||
|
values. */
|
||
|
indent = (int *)MALLOC ( (tree_nodes(data)+1) * sizeof(int) );
|
||
|
istep = indent;
|
||
|
/* fill the indentation table. */
|
||
|
gen_indents ( &l, &istep, 0, 1 );
|
||
|
|
||
|
istep = indent;
|
||
|
l = data;
|
||
|
|
||
|
/* now print the tree using the indentation table. */
|
||
|
pretty_print_tree_recurse ( &l, &istep, fil );
|
||
|
|
||
|
fprintf ( fil, "\n" );
|
||
|
|
||
|
FREE ( indent );
|
||
|
|
||
|
}
|
||
|
|
||
|
/* pretty_print_tree_recurse()
|
||
|
*
|
||
|
* recursive tree printer, using a table of indentations.
|
||
|
*/
|
||
|
|
||
|
void pretty_print_tree_recurse ( lnode **l, int **is, FILE *fil )
|
||
|
{
|
||
|
int i;
|
||
|
function *f;
|
||
|
|
||
|
f = (**l).f;
|
||
|
|
||
|
/** a positive indentation value means move to the next line and
|
||
|
print that many spaces before the function name. */
|
||
|
if ( **is >= 0 )
|
||
|
{
|
||
|
fprintf ( fil, "\n" );
|
||
|
for ( i = 0; i < **is; ++i )
|
||
|
fprintf ( fil, " " );
|
||
|
}
|
||
|
++*l;
|
||
|
++*is;
|
||
|
|
||
|
/** for terminals, don't print ()'s. **/
|
||
|
if ( f->arity == 0 )
|
||
|
{
|
||
|
if ( f->ephem_gen )
|
||
|
{
|
||
|
/* show value of ERCs. */
|
||
|
fprintf ( fil, " %s", (f->ephem_str)((**l).d->d) );
|
||
|
++*l;
|
||
|
}
|
||
|
else
|
||
|
/* show name of other terminals. */
|
||
|
fprintf ( fil, " %s", f->string );
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* print function name with a parenthesis. */
|
||
|
fprintf ( fil, " (%s", f->string );
|
||
|
|
||
|
switch ( f->type )
|
||
|
{
|
||
|
case FUNC_DATA:
|
||
|
case EVAL_DATA:
|
||
|
/* recursively print children. */
|
||
|
for ( i = 0; i < f->arity; ++i )
|
||
|
pretty_print_tree_recurse ( l, is, fil );
|
||
|
break;
|
||
|
case FUNC_EXPR:
|
||
|
case EVAL_EXPR:
|
||
|
/* recursively print children, ignoring skip nodes. */
|
||
|
for ( i = 0; i < f->arity; ++i )
|
||
|
{
|
||
|
++*l;
|
||
|
pretty_print_tree_recurse ( l, is, fil );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* print matching parenthesis. */
|
||
|
fprintf ( fil, ")" );
|
||
|
}
|
||
|
|
||
|
/* gen_indents()
|
||
|
*
|
||
|
* generates a table of indentations -- positive numbers indicate skipping
|
||
|
* to next line and indenting that much, negative indicate continuing current
|
||
|
* line. the result should look like:
|
||
|
*
|
||
|
* (function terminal
|
||
|
* (function terminal
|
||
|
* terminal)
|
||
|
* terminal)
|
||
|
*/
|
||
|
|
||
|
void gen_indents ( lnode **l, int **is, int start, int sameline )
|
||
|
{
|
||
|
function *f = (**l).f;
|
||
|
int i;
|
||
|
|
||
|
/** sameline is true for the first child of a function. first
|
||
|
children and terminals always go on the same line as their
|
||
|
parent. **/
|
||
|
if ( sameline || f->arity == 0 )
|
||
|
**is = -start;
|
||
|
else
|
||
|
**is = start;
|
||
|
|
||
|
++*is;
|
||
|
++*l;
|
||
|
|
||
|
if ( f->arity == 0 )
|
||
|
{
|
||
|
if ( f->ephem_gen )
|
||
|
/* skip the value of an ERC. */
|
||
|
++*l;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* move forward the length of the function name plus a space
|
||
|
plus a '('. */
|
||
|
start += strlen ( f->string ) + 2;
|
||
|
|
||
|
switch ( f->type )
|
||
|
{
|
||
|
case FUNC_DATA:
|
||
|
case EVAL_DATA:
|
||
|
/* generate children's indents. */
|
||
|
for ( i = 0; i < f->arity; ++i )
|
||
|
gen_indents ( l, is, start, i==0 );
|
||
|
break;
|
||
|
case FUNC_EXPR:
|
||
|
case EVAL_EXPR:
|
||
|
/* generate children's indents, ignoring skip nodes. */
|
||
|
for ( i = 0; i < f->arity; ++i )
|
||
|
{
|
||
|
++*l;
|
||
|
gen_indents ( l, is, start, i==0 );
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|