simplify # trees: Catalan trees -> Wedderburn–Etherington trees

This commit is contained in:
2021-01-25 10:12:45 +01:00
parent 684c33f156
commit 507988a93b
8 changed files with 203 additions and 76 deletions

View File

@@ -1,9 +1,12 @@
SHELL := /bin/bash SHELL := /bin/bash
#CFLAGS := -w -O3 -pg -DDEBUG -DDEBUG_BEST #CFLAGS := -w -O3 -pg -DDEBUG -DDEBUG_BEST
CFLAGS := -w -O3 -DDEBUG -DDEBUG_BEST CFLAGS := -O3 -DDEBUG -DDEBUG_BEST -DDEBUG_TREE -DDEBUG_STACK
# specific DEBUG flags: # specific DEBUG flags:
# timer: -DDEBUG_TIMER # timer: -DDEBUG_TIMER
# best control: -DDEBUG_BEST # best control: -DDEBUG_BEST
# tree: -DDEBUG_TREE
# stack: -DDEBUG_STACK
# stack: -DDEBUG_EVAL -DDEBUG_EVAL2
#CFLAGS := -w -g -pg -DDEBUG #CFLAGS := -w -g -pg -DDEBUG
TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n" TIME := \time -f "\ttime: %E real, %U user, %S sys\n\tcontext-switch:\t%c+%w, page-faults: %F+%R\n"
@@ -18,22 +21,17 @@ OBJS=$(TARGETS:=.o)
all: $(TARGETS) all: $(TARGETS)
lceb: $(OBJS) lceb: $(OBJS)
$(CC) $(CFLAGS) -DSTANDALONE -o $@ $^ $(CC) $(CFLAGS) -o $@ $^
tree oper timer: lceb.h
tree: tree.c tree: tree.c
$(CC) $(CFLAGS) -DSTANDALONE -o $@ $? $(CC) $(CFLAGS) -DSTANDALONE -o $@ $<
oper: oper.c oper: oper.c
$(CC) $(CFLAGS) -DSTANDALONE -o $@ $? $(CC) $(CFLAGS) -DSTANDALONE -o $@ $<
timer: timer.c timer: timer.c
$(CC) $(CFLAGS) -DSTANDALONE -o $@ $? $(CC) $(CFLAGS) -DSTANDALONE -o $@ $<
lceb.o tree.o oper.o eval.o stack.o best.o: lceb.h lceb.o tree.o oper.o eval.o stack.o best.o timer.o: lceb.h
tree oper: lceb.h
ex2: ex2-c
@$(TIME) ex2-c < $(INPUT)
%.o: %.c $(INCLUDES)
clean: clean:
rm -f $(TARGETS) $(OBJS) core rm -f $(TARGETS) $(OBJS) core

45
eval.c
View File

@@ -1,4 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include "lceb.h" #include "lceb.h"
@@ -14,7 +15,7 @@ int eval_node(node, depth, pvals, pops, ncalcs)
{ {
static int *vals, *val_zero; static int *vals, *val_zero;
static char *ops, *ops_zero; static char *ops, *ops_zero;
static *node_zero; static NODE *node_zero;
static int totcalc; static int totcalc;
int val1, val2, op, res=-1, i, lcalcs, rcalcs; int val1, val2, op, res=-1, i, lcalcs, rcalcs;
@@ -24,16 +25,16 @@ int eval_node(node, depth, pvals, pops, ncalcs)
node_zero=node; node_zero=node;
totcalc=0; totcalc=0;
} }
# ifdef DEBUG1 # ifdef DEBUG_EVAL
for (i=0; i<=depth; ++i) for (i=0; i<=depth; ++i)
printf(" "); printf(" ");
printf("eval : depth=%d : ncalcs=%d", depth, *ncalcs); printf("eval : depth=%d : ncalcs=%d ", depth, *ncalcs);
if (node->type == TREE_NODE) { if (node->type == TREE_NODE) {
printf("node(%c)\n", *ops); printf("node(%c)\n", *ops);
print_node(node, TREE_TOP, 0, 0); print_node(node, TREE_TOP, 0, 0);
} else { } else {
printf("val(%d)\n", *vals); printf("leaf(%d)\n", *vals);
} }
# endif # endif
if (node->type == TREE_LEAF) { if (node->type == TREE_LEAF) {
@@ -63,20 +64,38 @@ int eval_node(node, depth, pvals, pops, ncalcs)
res=val1+val2; res=val1+val2;
break; break;
case Mul: case Mul:
if (val1 > 1 && val2 > 1) /* we avoid "x*1" */ if (val1 > 1 && val2 > 1) /* we avoid "x*1" */
res=val1*val2; res=val1*val2;
break; break;
case Sub: case Sub:
if (val1 > val2) if (val1 != val2) {
res=val1-val2; if (val1 > val2) {
if (res == val2) /* we already got this value in tree */ res=val1-val2;
res=-1; } else {
# ifdef DEBUG_EVAL2
printf("eval: Sub: swapping val1=%d val2=%d\n", val1, val2);
# endif
res=val2-val1;
}
if (res == val2) /* already found in subtree */
res=-1;
}
break; break;
case Div: case Div:
if (val1 >= val2 && val2 != 1 && (val1 % val2 == 0)) if (val1 >= val2) {
res=val1/val2; if (val2 != 1 && (val1 % val2 == 0))
if (res == val2) /* we already got this value in tree */ res=val1/val2;
res=-1; if (res == val2) /* already found in subtree */
res=-1;
} else {
# ifdef DEBUG_EVAL2
printf("eval: Div: swapping val1=%d val2=%d\n", val1, val2);
# endif
if (val1 != 1 && (val2 % val1 == 0))
res=val2/val1;
if (res == val1) /* already found in subtree */
res=-1;
}
break; break;
case Nop: case Nop:
case End: case End:

16
lceb.c
View File

@@ -20,11 +20,18 @@ int main(ac, av)
char **av; char **av;
{ {
unsigned target; unsigned target;
STACK inputstack, *stack; STACK inputstack = {
"initial",
MAXINPUT, /* size */
0, /* last */
NULL, /* next */
{0}
};
STACK *stack;
int i, j, k, stacksize, val; int i, j, k, stacksize, val;
int ncombs, nstacks, ntrees, nops; int ncombs, nstacks, ntrees, nops;
TREE *tree; TREE *tree;
int intarray[1024]; char intarray[1024];
int eval; int eval;
char *comb; char *comb;
struct timespec end; struct timespec end;
@@ -47,7 +54,7 @@ int main(ac, av)
set_target(target); set_target(target);
//printf("len_ops=%d\nnops=%d\nops_comb=%d\n", len_ops, nops, ncombs); //printf("len_ops=%d\nnops=%d\nops_comb=%d\n", len_ops, nops, ncombs);
//stack=new_stack(stacksize, "Main Stack", 1); //stack=new_stack(stacksize, "Main Stack", 1);
strcpy(inputstack.name, "initial"); //strcpy(inputstack.name, "initial");
for (i=2; i<ac; ++i) { for (i=2; i<ac; ++i) {
val=atoi(av[i]); val=atoi(av[i]);
push_stack(&inputstack, val); push_stack(&inputstack, val);
@@ -66,7 +73,8 @@ int main(ac, av)
} while (permute_stack(stack->stack, stack->last)); } while (permute_stack(stack->stack, stack->last));
*/ */
gen_tree(intarray, nops, 0, 0); //gen_tree(intarray, nops, 0, 0);
gen_reduced_trees(nops+1);
nstacks=n_stacks(); nstacks=n_stacks();
ntrees=n_trees(); ntrees=n_trees();
printf("stacks=%d\noperators combinations=%d\ntrees=%d\n", printf("stacks=%d\noperators combinations=%d\ntrees=%d\n",

37
lceb.h
View File

@@ -1,8 +1,11 @@
#include <time.h> #include <time.h>
#define MAXINPUT 6 /* max numbers as input */ #define MAXINPUT (6) /* max numbers as input */
#define ALLOCSIZE 1024 /* # of elements to alloc when needed */ #define ALLOCSIZE (1024) /* # of elements to alloc */
#define EMPTY -1
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define ABS(a) (((a)<0)?-(a):(a))
typedef enum { typedef enum {
Nop='N', Nop='N',
@@ -21,7 +24,7 @@ typedef struct stack {
int stack[MAXINPUT+1]; int stack[MAXINPUT+1];
} STACK; } STACK;
#define TREE_UNDEF (-1) /* should not happen */ #define TREE_UNDEF (-1) /* should not happen */
#define TREE_LEAF 0 #define TREE_LEAF 0
#define TREE_NODE 1 #define TREE_NODE 1
#define TREE_LEFT 'L' #define TREE_LEFT 'L'
@@ -31,22 +34,25 @@ typedef struct stack {
#define EMPTY -1 #define EMPTY -1
typedef struct node { typedef struct node {
int type; /* TREE_LEAF or TREE_NODE */ int type; /* TREE_LEAF or TREE_NODE */
int op; int op; /* operator (nodes only) */
int val; int val; /* value (leafs only) */
int eval; int eval; /* eval (unused) */
int prof; /* max left/right profs */
int left_prof;
struct node *left; struct node *left;
int right_prof;
struct node *right; struct node *right;
struct node *next; /* for transversal walk and free nodes */ struct node *next; /* for transv walk and free nodes */
} NODE; } NODE;
typedef struct tree { typedef struct tree {
char name[80]; char name[80];
NODE *head; NODE *head;
struct tree *next; struct tree *next;
int nodes; /* number of nodes */ int nodes; /* number of nodes */
int leaves; /* number of leaves */ int leaves; /* number of leaves */
int depth; /* max depth */ int depth; /* max depth */
} TREE; } TREE;
typedef struct best { typedef struct best {
@@ -67,8 +73,11 @@ extern void print_tree(TREE *tree, int details);
extern void print_trees(int details); extern void print_trees(int details);
extern TREE *new_tree(char *name); extern TREE *new_tree(char *name);
extern NODE *dup_node(NODE *src); extern NODE *dup_node(NODE *src);
extern NODE *build_tree(int *desc, int size); //extern NODE *build_tree(int *desc, int size);
extern void gen_tree(int *seq, int n, int nb1, int nb0); extern NODE *build_tree(char *desc, int size);
//extern void gen_tree(int *seq, int n, int nb1, int nb0);
extern void gen_reduced_trees(int n);
extern void gen_tree(char *seq, int n, int nb1, int nb0);
extern TREE *nth_tree(int n); extern TREE *nth_tree(int n);
extern int n_trees(); extern int n_trees();

2
oper.c
View File

@@ -1,3 +1,5 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include "lceb.h" #include "lceb.h"

View File

@@ -107,6 +107,10 @@ int *push_stack(stack, val)
int size=stack->size; int size=stack->size;
int *pelt=stack->stack+stack->last; int *pelt=stack->stack+stack->last;
#ifdef DEBUG_STACK
printf("push_stack(%d): last=%d size=%d\n", val, stack->last, stack->size);
#endif
if (pos >= size) { if (pos >= size) {
fprintf(stderr, "stack overflow: size=%d last=%d\n", size, pos); fprintf(stderr, "stack overflow: size=%d last=%d\n", size, pos);
return NULL; return NULL;

View File

@@ -1,4 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <time.h> #include <time.h>
#define NANOSEC 1000000000.0 #define NANOSEC 1000000000.0
@@ -20,7 +21,7 @@ void set_timer(timer)
{ {
clock_gettime(CLOCK_MONOTONIC, timer); clock_gettime(CLOCK_MONOTONIC, timer);
# ifdef DEBUG_TIMER # ifdef DEBUG_TIMER
printf("timer: sec=%d nsec=%d orig: sec=%d nsec=%d\n", printf("timer: sec=%d nsec=%d orig: sec=%ld nsec=%ld\n",
timer->tv_sec, timer->tv_nsec, start.tv_sec, start.tv_nsec); timer->tv_sec, timer->tv_nsec, start.tv_sec, start.tv_nsec);
# endif # endif
} }
@@ -37,7 +38,7 @@ double get_timer(timer)
} }
#ifdef STANDALONE #ifdef STANDALONE
main(ac, av) int main(ac, av)
int ac; int ac;
char **av; char **av;
{ {
@@ -52,7 +53,7 @@ main(ac, av)
start_timer(); start_timer();
tsdelay.tv_sec=delay/MILLISEC; tsdelay.tv_sec=delay/MILLISEC;
tsdelay.tv_nsec=delay%MILLISEC; tsdelay.tv_nsec=delay%MILLISEC;
printf("delay %d=%d:%d\n", delay, tsdelay.tv_sec, tsdelay.tv_nsec); printf("delay %d=%ld:%ld\n", delay, tsdelay.tv_sec, tsdelay.tv_nsec);
nanosleep(&tsdelay, NULL); nanosleep(&tsdelay, NULL);
set_timer(&end); set_timer(&end);
printf("Time elapsed: %.5f seconds\n", get_timer(end)); printf("Time elapsed: %.5f seconds\n", get_timer(end));

146
tree.c
View File

@@ -194,41 +194,49 @@ NODE *dup_node(src)
return dst; return dst;
} }
/*void free_node(node) /* untested - unused */
int calc_prof_node(node)
NODE *node; NODE *node;
{ {
int left, right;
if (node->type==TREE_LEAF) { if (node->type==TREE_LEAF) {
node->next=freenodes; return 0;
freenodes=node;
} else { } else {
free_node(node->left); left=calc_prof_node(node->left);
free_node(node->right); right=calc_prof_node(node->right);
node->next=freenodes; node->prof=MAX(left, right)+1;
freenodes=node;
} }
}*/ return node->prof;
}
NODE *build_tree(desc, size) NODE *build_tree(desc, size)
int *desc; char *desc;
int size; int size;
{ {
NODE *root, *node; NODE *root, *node;
NODE *nodestack[1024]; /* TODO: make it dynamic */ NODE *nodestack[1024]; /* TODO: make it dynamic */
int i, curnode=0; int i, curnode=0;
# ifdef DEBUG_TREE
printf("tree %d desc=", ntrees);
for (i=0; i<size; ++i)
printf("%c", desc[i]);
putchar('\n');
# endif
root=get_node(); root=get_node();
root->type=TREE_NODE; root->type=TREE_NODE;
nodestack[curnode++]=root; nodestack[curnode++]=root;
for(i=1; i<size; ++i) { for(i=1; i<size; ++i) {
node = get_node(); node = get_node();
if (desc[i-1]) { if (desc[i-1]=='1') {
nodestack[curnode-1]->left = node; nodestack[curnode-1]->left = node;
} else { } else {
nodestack[curnode-1]->right = node; nodestack[curnode-1]->right = node;
curnode--; curnode--;
} }
if (desc[i]) { if (desc[i]=='1') {
node->type=TREE_NODE; node->type=TREE_NODE;
nodestack[curnode++]=node; nodestack[curnode++]=node;
} else { } else {
@@ -239,25 +247,102 @@ NODE *build_tree(desc, size)
return root; return root;
} }
void gen_tree(seq, n, nb1, nb0) /* generate reduced trees from static description */
int *seq; void gen_reduced_trees(n)
int n; /* number of nodes */ int n;
int nb1; /* number of "1" */ {
int nb0; /* number of "0" */ int size=n*2-1, i;
TREE *tree;
char name[80];
char *seq2[]= {
"100"
};
char *seq3[]= {
"10100"
};
char *seq4[]= {
"1010100",
"1100100"
};
char *seq5[]= {
"101010100",
"110010100",
"101100100"
};
char *seq6[]= {
"10101010100",
"11001010100",
"10110010100",
"10101100100",
"11001100100",
"11010010100"
};
if (n<2 || n>MAXINPUT) {
fprintf(stderr, "gen_reduced_trees: wrong leaves %d\n", n);
return;
}
# ifdef DEBUG_TREE
printf("gen_reduced_trees(leaves=%d)\n", n);
# endif
switch (n) {
case 2:
ntrees++;
sprintf(name, "Tree %d", ntrees);
tree=new_tree(name);
tree->head=build_tree(seq2[0], size);
break;
case 3:
ntrees++;
sprintf(name, "Tree %d", ntrees);
tree=new_tree(name);
tree->head=build_tree(seq3[0], size);
break;
case 4:
for (i=0; i<2; ++i) {
ntrees++;
sprintf(name, "Tree %d", ntrees);
tree=new_tree(name);
tree->head=build_tree(seq4[i], size);
}
break;
case 5:
for (i=0; i<3; ++i) {
ntrees++;
sprintf(name, "Tree %d", ntrees);
tree=new_tree(name);
tree->head=build_tree(seq5[i], size);
}
break;
case 6:
for (i=0; i<6; ++i) {
ntrees++;
sprintf(name, "Tree %d", ntrees);
tree=new_tree(name);
tree->head=build_tree(seq6[i], size);
}
break;
}
return;
}
void gen_tree(seq, n, nb1, nb0)
char *seq;
int n; /* number of nodes */
int nb1; /* number of "1" */
int nb0; /* number of "0" */
{ {
int i;
char name[80]; char name[80];
TREE *tree; TREE *tree;
if((nb1 + nb0) == 2*n) { /* end */ # ifdef DEBUG_TREE
seq[2*n] = 0; printf("gen_tree(n=%d, nb1=%d, nb0=%d)\n", n, nb1, nb0);
# endif
if((nb1 + nb0) == 2*n) { /* end */
seq[2*n] = '0';
seq[2*n+1] = 0;
ntrees++; ntrees++;
# ifdef DEBUG1
printf("tree %d desc=", ntrees);
for (i=0; i<=2*n; ++i)
printf("%d", seq[i]);
putchar('\n');
# endif
sprintf(name, "Tree %d", ntrees); sprintf(name, "Tree %d", ntrees);
tree=new_tree(name); tree=new_tree(name);
tree->head=build_tree(seq, 2*n+1); tree->head=build_tree(seq, 2*n+1);
@@ -265,12 +350,12 @@ void gen_tree(seq, n, nb1, nb0)
} }
if(nb1 >= nb0 && nb1 < n) { if(nb1 >= nb0 && nb1 < n) {
seq[nb1+nb0] = 1; seq[nb1+nb0] = '1';
gen_tree(seq, n, nb1+1, nb0); gen_tree(seq, n, nb1+1, nb0);
} }
if(nb0 < nb1 && nb1 <=n) { if(nb0 < nb1 && nb1 <=n) {
seq[nb1+nb0] = 0; seq[nb1+nb0] = '0';
gen_tree(seq, n, nb1, nb0+1); gen_tree(seq, n, nb1, nb0+1);
} }
} }
@@ -292,13 +377,13 @@ int n_trees()
} }
#ifdef STANDALONE #ifdef STANDALONE
main(ac, av) void main(ac, av)
int ac; int ac;
char **av; char **av;
{ {
int n, details=0; int n, details=0;
char array[1024];
int array[1024];
if (ac<2 || ac>3) { if (ac<2 || ac>3) {
fprintf(stderr, "usage: %s nodes [type]\n", *av); fprintf(stderr, "usage: %s nodes [type]\n", *av);
fprintf(stderr, "type can be 0 (RPN, default, 1 (polish), 2 (details), 3 (lisp notation), 4 (parenthesed notation)\n"); fprintf(stderr, "type can be 0 (RPN, default, 1 (polish), 2 (details), 3 (lisp notation), 4 (parenthesed notation)\n");
@@ -308,7 +393,8 @@ main(ac, av)
details=atoi(av[2]); details=atoi(av[2]);
} }
n=atoi(av[1]); n=atoi(av[1]);
gen_tree(array, n, 0, 0); gen_reduced_trees(n+1);
//gen_tree(array, n, 0, 0);
print_trees(details); print_trees(details);
exit(0); exit(0);
} }