COSC-4P82-Final-Project/lib/lilgp/kernel/pretty.c

322 lines
8.1 KiB
C
Raw Normal View History

2024-04-01 00:01:49 -04:00
/* 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);
}
void pretty_print_tree_equ(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;
fprintf(fil, "\ny = ");
/* now print the tree using the indentation table. */
pretty_print_tree_recurse_equ(&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, ")");
}
void pretty_print_tree_recurse_equ(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;
}
if (f->arity > 2)
{
/* 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, ")");
return;
}
if (f->arity == 1)
{
fprintf(fil, "%s(", f->string);
switch (f->type)
{
case FUNC_DATA:
case EVAL_DATA:
pretty_print_tree_recurse_equ(l, is, fil);
break;
case FUNC_EXPR:
case EVAL_EXPR:
++*l;
pretty_print_tree_recurse_equ(l, is, fil);
break;
}
fprintf(fil, ")");
} else
{
fprintf(fil, "(");
switch (f->type)
{
case FUNC_DATA:
case EVAL_DATA:
pretty_print_tree_recurse_equ(l, is, fil);
break;
case FUNC_EXPR:
case EVAL_EXPR:
++*l;
pretty_print_tree_recurse_equ(l, is, fil);
break;
}
fprintf(fil, " %s ", f->string);
switch (f->type)
{
case FUNC_DATA:
case EVAL_DATA:
pretty_print_tree_recurse_equ(l, is, fil);
break;
case FUNC_EXPR:
case EVAL_EXPR:
++*l;
pretty_print_tree_recurse_equ(l, is, fil);
break;
}
fprintf(fil, ")");
}
/* 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;
}
}