diff --git a/test/raytracer/Makefile b/test/raytracer/Makefile index 2812909737d97ceb74cc5215e836cc5590d74ee3..dea57af90fad98c12d070865f2b94d8c0ab7a672 100644 --- a/test/raytracer/Makefile +++ b/test/raytracer/Makefile @@ -1,5 +1,5 @@ CC=../../ccomp -CFLAGS=-U__GNUC__ -stdlib ../../runtime -dclight -dasm +CFLAGS=-stdlib ../../runtime -dparse -dclight -dasm -fstruct-passing -fstruct-assign LIBS= TIME=xtime -mintime 2.0 @@ -11,7 +11,7 @@ render: $(OBJS) $(CC) $(CFLAGS) -o render $(OBJS) $(LIBS) clean: - rm -f *.o *.light.c *.s *.ppm render + rm -f *.o *.parsed.c *.light.c *.s *.ppm render include .depend diff --git a/test/raytracer/arrays.h b/test/raytracer/arrays.h index 47634f62d9e59b92e8b26c020569ec118de0663c..fe65af0c44d685e6d3878528da9a3b45532d2331 100644 --- a/test/raytracer/arrays.h +++ b/test/raytracer/arrays.h @@ -18,14 +18,8 @@ struct array * copy_array(int eltsize, struct array * arr, int extrasize); #define get_array(ty,arr,idx) (data_array(ty,arr)[idx]) -#define get_array_large(dst,ty,arr,idx) \ - ASSIGN(dst, data_array(ty,arr)[idx]) - #define set_array(ty,arr,idx,newval) (data_array(ty,arr)[idx] = (newval)) -#define set_array_large(ty,arr,idx,newval) \ - ASSIGN(data_array(ty,arr)[idx], newval) - #define extend_array(ty,arr) \ if ((arr)->size >= (arr)->capacity) grow_array(sizeof(ty), (arr)); \ (arr)->size++ diff --git a/test/raytracer/config.h b/test/raytracer/config.h index ed5b8478cbacfc0ca6b3bcdf45d6c7c250639891..49361dc5d837f237f17f48ef3990eac1dd75a4a3 100644 --- a/test/raytracer/config.h +++ b/test/raytracer/config.h @@ -1,9 +1,9 @@ #include <math.h> +#include <assert.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <assert.h> #ifdef SINGLE_PRECISION typedef float flt; @@ -11,17 +11,6 @@ typedef float flt; typedef double flt; #endif -#if 0 -extern void abord(void); - -#define assert(cond) \ - if (!(cond)) { fprintf(stderr, "%s:%u: failed assertion\n", __FILE__, __LINE__); abort(); } - -#endif - -#define ASSIGN(lv,rv) memcpy(&(lv), &(rv), sizeof(rv)) - void arena_init(void); void arena_clear(void); void * arena_alloc(int size); - diff --git a/test/raytracer/eval.c b/test/raytracer/eval.c index 4d3f3dcc4523106ad7966a01997f5ca97709edd7..7c3cb93218116a62f99f2f8833111148f136d072 100644 --- a/test/raytracer/eval.c +++ b/test/raytracer/eval.c @@ -38,7 +38,7 @@ static int lookup(struct array * env, char * name, /*out*/ struct value * res) for (i = env->size - 1; i >= 0; i--) { struct binding * b = &get_array(struct binding, env, i); if (name == b->name) { - ASSIGN(*res, b->val); + *res = b->val; return 1; } } @@ -55,7 +55,7 @@ static void assign(struct array * env, char * name, struct value * newval) b = &get_array(struct binding, env, i); if (! b->mutable) break; if (name == b->name) { - ASSIGN(b->val, *newval); + b->val = *newval; return; } } @@ -63,7 +63,7 @@ static void assign(struct array * env, char * name, struct value * newval) b = &get_array(struct binding, env, env->size - 1); b->name = name; b->mutable = 1; - ASSIGN(b->val, *newval); + b->val = *newval; } /* Take an immutable copy of an environment */ @@ -173,22 +173,11 @@ static void print_value(struct value * s) static struct value main_stack[MAIN_STACK_SIZE]; static struct value surface_stack[SURFACE_STACK_SIZE]; -/* Error handling functions */ -#define ERRORFUN(name, msg) \ - static void name(void) { fprintf(stderr, msg); exit(2); } - -ERRORFUN(stack_overflow, "Stack overflow\n") -ERRORFUN(stack_underflow, "Stack underflow\n") -ERRORFUN(type_error, "Type error\n") -ERRORFUN(division_by_zero, "Division by zero\n") -ERRORFUN(bound_error, "Out-of-bound array access\n") -ERRORFUN(negative_sqrt, "Square root of negative number\n") - /* Macros for stack checking and type checking */ -#define push() if (--sp < bos) stack_overflow() -#define can_pop(n) if (sp + (n) > tos) stack_underflow() -#define check(n,ty) if (sp[n].tag != ty) type_error() +#define push() if (--sp < bos) goto stack_overflow +#define can_pop(n) if (sp + (n) > tos) goto stack_underflow +#define check(n,ty) if (sp[n].tag != ty) goto type_error /* Execute the given token list in the given environment */ @@ -238,7 +227,7 @@ static struct value * execute_list(struct array * code, struct array * a = new_array(struct value, sz); int j; a->size = sz; - for (j = 0; j < sz; j++) set_array_large(struct value, a, j, sp[-1-j]); + for (j = 0; j < sz; j++) set_array(struct value, a, j, sp[-1-j]); push(); sp[0].tag = Arr; sp[0].u.arr = a; break; @@ -287,7 +276,7 @@ static struct value * execute_list(struct array * code, can_pop(1); check(0, Clos); sp[0].tag = Obj; - sp[0].u.obj = cone(&sp[0].u.clos); + sp[0].u.obj = cone(sp[0].u.clos); break; case Op_cos: can_pop(1); @@ -298,13 +287,13 @@ static struct value * execute_list(struct array * code, can_pop(1); check(0, Clos); sp[0].tag = Obj; - sp[0].u.obj = cube(&sp[0].u.clos); + sp[0].u.obj = cube(sp[0].u.clos); break; case Op_cylinder: can_pop(1); check(0, Clos); sp[0].tag = Obj; - sp[0].u.obj = cylinder(&sp[0].u.clos); + sp[0].u.obj = cylinder(sp[0].u.clos); break; case Op_difference: can_pop(2); @@ -317,7 +306,7 @@ static struct value * execute_list(struct array * code, can_pop(2); check(1, I); check(0, I); - if (sp[0].u.i == 0) division_by_zero(); + if (sp[0].u.i == 0) goto division_by_zero; sp[1].u.i = sp[1].u.i / sp[0].u.i; sp += 1; break; @@ -365,8 +354,8 @@ static struct value * execute_list(struct array * code, check(0, I); a = sp[1].u.arr; idx = sp[0].u.i; - if (idx < 0 || idx >= a->size) bound_error(); - get_array_large(sp[1], struct value, a, idx); + if (idx < 0 || idx >= a->size) goto bound_error; + sp[1] = get_array(struct value, a, idx); sp++; break; } @@ -439,7 +428,7 @@ static struct value * execute_list(struct array * code, can_pop(2); check(1, I); check(0, I); - if (sp[0].u.i == 0) division_by_zero(); + if (sp[0].u.i == 0) goto division_by_zero; sp[1].u.i = sp[1].u.i % sp[0].u.i; sp += 1; break; @@ -471,7 +460,7 @@ static struct value * execute_list(struct array * code, can_pop(1); check(0, Clos); sp[0].tag = Obj; - sp[0].u.obj = plane(&sp[0].u.clos); + sp[0].u.obj = plane(sp[0].u.clos); break; case Op_point: { struct point * p; @@ -562,7 +551,7 @@ static struct value * execute_list(struct array * code, can_pop(1); check(0, Clos); sp[0].tag = Obj; - sp[0].u.obj = sphere(&sp[0].u.clos); + sp[0].u.obj = sphere(sp[0].u.clos); break; case Op_spotlight: can_pop(5); @@ -579,7 +568,7 @@ static struct value * execute_list(struct array * code, case Op_sqrt: can_pop(1); check(0, R); - if (sp[0].u.r < 0) negative_sqrt(); + if (sp[0].u.r < 0) goto negative_sqrt; sp[0].u.r = sqrt(sp[0].u.r); break; case Op_subi: @@ -627,11 +616,32 @@ static struct value * execute_list(struct array * code, } } return sp; + /* Error handling */ + stack_overflow: + fprintf(stderr, "Stack overflow\n"); + goto print_context; + stack_underflow: + fprintf(stderr, "Stack underflow\n"); + goto print_context; + type_error: + fprintf(stderr, "Type error\n"); + goto print_context; + division_by_zero: + fprintf(stderr, "Division by zero\n"); + goto print_context; + bound_error: + fprintf(stderr, "Out-of-bound array access\n"); + goto print_context; + negative_sqrt: + fprintf(stderr, "Square root of negative number\n"); + print_context: + fprintf(stderr, "(operation: %s, PC: %d)\n", operator_names[t->tag], i); + exit(2); } /* Evaluate a surface function */ -void surface_function(struct closure * clos, int face, flt u, flt v, +void surface_function(struct closure clos, int face, flt u, flt v, /*out*/ struct surface_characteristics * sc) { struct value * sp; @@ -643,7 +653,7 @@ void surface_function(struct closure * clos, int face, flt u, flt v, sp[0].tag = R; sp[0].u.i = v; sp = - execute_list(clos->code, clos->env, surface_stack, + execute_list(clos.code, clos.env, surface_stack, surface_stack + SURFACE_STACK_SIZE, sp); if (sp != surface_stack + SURFACE_STACK_SIZE - 4 || sp[0].tag != R || diff --git a/test/raytracer/eval.h b/test/raytracer/eval.h index 610b5d96734bd49a7b2647e0f3c0985aa20b9a92..88facfea203b5f9b23555b3e99631c9eb3d78a8b 100644 --- a/test/raytracer/eval.h +++ b/test/raytracer/eval.h @@ -14,5 +14,5 @@ struct surface_characteristics { void execute_program(struct array * toklist); -void surface_function(struct closure * clos, int face, flt u, flt v, +void surface_function(struct closure clos, int face, flt u, flt v, /*out*/ struct surface_characteristics * sc); diff --git a/test/raytracer/gmllexer.c b/test/raytracer/gmllexer.c index 04f8df814ae4a8eef89c52fb85e2e01011d724f9..a8594dd37189b666ea691c5c4bc697a4e01d150e 100644 --- a/test/raytracer/gmllexer.c +++ b/test/raytracer/gmllexer.c @@ -1,14 +1,10 @@ /* Lexer for GML */ #include "config.h" +#include <ctype.h> #include "gmllexer.h" #include "gml.h" -#define isdigit(c) (c >= '0' && c <= '9') -#define isalpha(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) -#define isalnum(c) (isdigit(c) || isalpha(c)) -#define isprint(c) (c >= ' ' && c <= 126) - struct lexeme current_lexeme; struct bucket { @@ -91,7 +87,7 @@ static void get_binder(void) current_lexeme.kind = BINDER; } -static int get_number(int firstchar) +static void get_number(int firstchar) { int c, pos, is_real; @@ -102,7 +98,7 @@ static int get_number(int firstchar) if (c == '-') { STORE_BUFFER(pos, c); c = getchar(); - if (! isdigit(c)) return -1; + if (! isdigit(c)) goto bad_number; } /* Decimal number */ do { @@ -114,7 +110,7 @@ static int get_number(int firstchar) is_real = 1; STORE_BUFFER(pos, c); c = getchar(); - if (! isdigit(c)) return -1; + if (! isdigit(c)) goto bad_number; do { STORE_BUFFER(pos, c); c = getchar(); @@ -129,7 +125,7 @@ static int get_number(int firstchar) STORE_BUFFER(pos, c); c = getchar(); } - if (! isdigit(c)) return -1; + if (! isdigit(c)) goto bad_number; do { STORE_BUFFER(pos, c); c = getchar(); @@ -145,23 +141,29 @@ static int get_number(int firstchar) current_lexeme.kind = INTEGER; current_lexeme.u.i = atoi(buffer); } - return 0; + return; + bad_number: + fprintf(stderr, "Illegal number\n"); + exit(2); } -static int get_string(void) +static void get_string() { int c, pos; pos = 0; while (1) { c = getchar(); if (c == '"') break; - if (! isprint(c)) return -1; + if (! isprint(c)) goto bad_string; STORE_BUFFER(pos, c); } buffer[pos] = 0; current_lexeme.kind = STRING; current_lexeme.u.s = strdup(buffer); - return 0; + return; + bad_string: + fprintf(stderr, "Illegal string literal\n"); + exit(2); } void get_lexeme(void) @@ -169,49 +171,39 @@ void get_lexeme(void) int c; if (current_lexeme.kind != NONE) return; - while (1) { - c = getchar(); - switch (c) { - case EOF: - current_lexeme.kind = END_OF_FILE; break; - case ' ': case '\n': case '\t': case '\r': case 11: - continue; - case '%': - do { c = getchar(); } while (c != '\n' && c != EOF); - continue; - case '/': - get_binder(); break; - case '-': case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (get_number(c) == -1) { - fprintf(stderr, "Bad number\n"); - exit(2); - } - break; - case '"': - if (get_string() == -1) { - fprintf(stderr, "Bad string literal\n"); - exit(2); - } - break; - case '{': - current_lexeme.kind = LBRACE; break; - case '}': - current_lexeme.kind = RBRACE; break; - case '[': - current_lexeme.kind = LBRACKET; break; - case ']': - current_lexeme.kind = RBRACKET; break; - default: - if (isalpha(c)) { - get_ident(c); - } else { - fprintf(stderr, "Illegal character `%c'\n", c); - exit(2); - } - break; + again: + c = getchar(); + switch (c) { + case EOF: + current_lexeme.kind = END_OF_FILE; break; + case ' ': case '\n': case '\t': case '\r': case 11: + goto again; + case '%': + do { c = getchar(); } while (c != '\n' && c != EOF); + goto again; + case '/': + get_binder(); break; + case '-': case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + get_number(c); break; + case '"': + get_string(); break; + case '{': + current_lexeme.kind = LBRACE; break; + case '}': + current_lexeme.kind = RBRACE; break; + case '[': + current_lexeme.kind = LBRACKET; break; + case ']': + current_lexeme.kind = RBRACKET; break; + default: + if (isalpha(c)) { + get_ident(c); + } else { + fprintf(stderr, "Illegal character `%c'\n", c); + exit(2); } - return; + break; } } diff --git a/test/raytracer/gmlparser.c b/test/raytracer/gmlparser.c index b0a6cbc19a6bd9d79b7e1dd9188bb13e839351ba..dc05105227fe04aed5facdb97f257bc3d38db219 100644 --- a/test/raytracer/gmlparser.c +++ b/test/raytracer/gmlparser.c @@ -82,7 +82,7 @@ static struct array * parse_tokenlist(void) int i = 0; while (parse_token(&t)) { extend_array(struct tok, a); - set_array_large(struct tok, a, i, t); + set_array(struct tok, a, i, t); i++; } return a; diff --git a/test/raytracer/intersect.c b/test/raytracer/intersect.c index c8a212603036d41c0ec6561bd9da3e3ae7d451cd..3b2d7b0dd7f8caddb52b6aba100086aaeacf9421 100644 --- a/test/raytracer/intersect.c +++ b/test/raytracer/intersect.c @@ -9,7 +9,7 @@ /* Operations on interval lists */ -#define POS_INFTY 1e300 +#define POS_INFTY HUGE_VAL struct intervlist { flt beg; diff --git a/test/raytracer/light.c b/test/raytracer/light.c index 1c90104ce744ba1eeddbf9859e0e03d6d861d7ac..60d979a7049d2b31f4fd3f90aa77ad1f6033b93a 100644 --- a/test/raytracer/light.c +++ b/test/raytracer/light.c @@ -10,8 +10,8 @@ struct light * dirlight(struct point * dir, struct point * c) { struct light * l = arena_alloc(sizeof(struct light)); l->kind = Directional; - ASSIGN(l->u.directional.dir, *dir); - ASSIGN(l->u.directional.col, *c); + l->u.directional.dir = *dir; + l->u.directional.col = *c; return l; } @@ -19,8 +19,8 @@ struct light * pointlight(struct point * orig, struct point * c) { struct light * l = arena_alloc(sizeof(struct light)); l->kind = Pointlight; - ASSIGN(l->u.point.orig, *orig); - ASSIGN(l->u.point.col, *c); + l->u.point.orig = *orig; + l->u.point.col = *c; return l; } @@ -30,9 +30,9 @@ struct light * spotlight(struct point * pos, struct point * at, struct light * l = arena_alloc(sizeof(struct light)); struct vector uv; l->kind = Spot; - ASSIGN(l->u.spot.orig, *pos); - ASSIGN(l->u.spot.at, *at); - ASSIGN(l->u.spot.col, *c); + l->u.spot.orig = *pos; + l->u.spot.at = *at; + l->u.spot.col = *c; l->u.spot.cutoff = cutoff; l->u.spot.exponent = exp; between(at, pos, &uv); @@ -81,9 +81,7 @@ static void color_from_light(struct object * scene, /* Intensity of light source at object */ switch (light->kind) { case Directional: - i.x = light->u.directional.col.x; - i.y = light->u.directional.col.y; - i.z = light->u.directional.col.z; + i = light->u.directional.col; break; case Pointlight: att = 100.0 / (99.0 + dist2(pt, &light->u.point.orig)); diff --git a/test/raytracer/matrix.c b/test/raytracer/matrix.c index 8814346891ed6dd4911d4058ed66372c5dbedf0c..5c85c7b4869f823085b96f4b763b529e96a639fa 100644 --- a/test/raytracer/matrix.c +++ b/test/raytracer/matrix.c @@ -3,12 +3,6 @@ #include "vector.h" #include "matrix.h" -struct matrix matrix_identity = { - 1.0, 0.0, 0.0, 0.0, - 0.0, 1.0, 0.0, 0.0, - 0.0, 0.0, 1.0, 0.0, -}; - void apply_to_point(struct matrix * m, struct point * p, /*out*/ struct point * r) { @@ -25,7 +19,13 @@ void apply_to_vect(struct matrix * m, struct vector * v, r->dz = m->zx * v->dx + m->zy * v->dy + m->zz * v->dz; } +static struct matrix matrix_identity = { + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, +}; +struct matrix * mid = &matrix_identity; struct matrix * mtranslate(flt sx, flt sy, flt sz) { diff --git a/test/raytracer/matrix.h b/test/raytracer/matrix.h index 4b9f4346eb0555a227a3f227f96b8962c8905561..5ab63b33c0f07b992006cffbe380735263aa1d1c 100644 --- a/test/raytracer/matrix.h +++ b/test/raytracer/matrix.h @@ -8,8 +8,7 @@ void apply_to_point(struct matrix * m, struct point * p, /*out*/ struct point * r); void apply_to_vect(struct matrix * m, struct vector * v, /*out*/ struct vector * r); -extern struct matrix matrix_identity; -#define mid (&matrix_identity) +extern struct matrix * mid; struct matrix * mtranslate(flt sx, flt sy, flt sz); struct matrix * mscale(flt sx, flt sy, flt sz); struct matrix * mrotatex(flt a); diff --git a/test/raytracer/object.c b/test/raytracer/object.c index 3dd6e77e467373993d75867a7be0215cc75d4e39..c7e5f53fe96594f5dd03e25ac9a63f6906fa47ea 100644 --- a/test/raytracer/object.c +++ b/test/raytracer/object.c @@ -6,30 +6,30 @@ #include "object.h" #include "matrix.h" -static struct object * new_object(int kind, struct closure * c) +static struct object * new_object(int kind, struct closure c) { struct object * o = arena_alloc(sizeof(struct object)); o->kind = kind; - ASSIGN(o->surf, *c); + o->surf = c; o->world2obj = o->obj2world = mid; o->max_scale_applied = 1.0; o->radius = BS_NOT_COMPUTED; return o; } -struct object * cone(struct closure * c) +struct object * cone(struct closure c) { return new_object(Cone, c); } -struct object * cube(struct closure * c) +struct object * cube(struct closure c) { return new_object(Cube, c); } -struct object * cylinder(struct closure * c) +struct object * cylinder(struct closure c) { return new_object(Cylinder, c); } -struct object * plane(struct closure * c) +struct object * plane(struct closure c) { return new_object(Plane, c); } -struct object * sphere(struct closure * c) +struct object * sphere(struct closure c) { return new_object(Sphere, c); } static struct object * transform(struct object * o, @@ -47,7 +47,7 @@ static struct object * transform(struct object * o, no->o2 = transform(o->o2, t, tinv, scale); break; default: - ASSIGN(no->surf, o->surf); + no->surf = o->surf; no->world2obj = mcompose(o->world2obj, tinv); no->obj2world = mcompose(t, o->obj2world); no->max_scale_applied = o->max_scale_applied * scale; @@ -212,3 +212,4 @@ void normal_vector(struct object * obj, struct point * p, int face, product(&tang_world1, &tang_world2, n); vnormalize(n, n); } + diff --git a/test/raytracer/object.h b/test/raytracer/object.h index d890bda866b923c946a10f537f5ff77cf97bfccf..b5edd58ef9ff7087a31c6ccaa6b76f9afe4f2e89 100644 --- a/test/raytracer/object.h +++ b/test/raytracer/object.h @@ -12,11 +12,11 @@ struct object { flt radius; }; -struct object * cone(struct closure * c); -struct object * cube(struct closure * c); -struct object * cylinder(struct closure * c); -struct object * plane(struct closure * c); -struct object * sphere(struct closure * c); +struct object * cone(struct closure c); +struct object * cube(struct closure c); +struct object * cylinder(struct closure c); +struct object * plane(struct closure c); +struct object * sphere(struct closure c); struct object * orotatex(struct object * o1, flt a); struct object * orotatey(struct object * o1, flt a); diff --git a/test/raytracer/point.h b/test/raytracer/point.h index b8d6ff0fcdae57bf2f311573cd28caecb11f3048..64bf5821e4e014836d7582b264a5a3a491f43567 100644 --- a/test/raytracer/point.h +++ b/test/raytracer/point.h @@ -2,7 +2,6 @@ struct point { flt x, y, z; }; -#if 0 static inline flt dist2(struct point * p1, struct point * p2) { flt dx = p2->x - p1->x; @@ -10,9 +9,4 @@ static inline flt dist2(struct point * p1, struct point * p2) flt dz = p2->z - p1->z; return dx * dx + dy * dy + dz * dz; } -#else -#define dist2(p1,p2) \ - (((p2)->x - (p1)->x) * ((p2)->x - (p1)->x) + \ - ((p2)->y - (p1)->y) * ((p2)->y - (p1)->y) + \ - ((p2)->z - (p1)->z) * ((p2)->z - (p1)->z)) -#endif + diff --git a/test/raytracer/render.c b/test/raytracer/render.c index 3678cb6faa30bb33bf596deff5a5c4a5bc8e5e9a..9d732806bc8b4c1f7bb327941fd52090102d7599 100644 --- a/test/raytracer/render.c +++ b/test/raytracer/render.c @@ -45,7 +45,7 @@ static void render_ray(struct point * amb, point_along(p, v, t, &inter_w); apply_to_point(bobj->world2obj, &inter_w, &inter_o); surface_coords(bobj, &inter_o, &face, &surf_u, &surf_v); - surface_function(&bobj->surf, face, surf_u, surf_v, &sc); + surface_function(bobj->surf, face, surf_u, surf_v, &sc); /* Construct the vectors on figure 4 */ normal_vector(bobj, &inter_w, face, &n); dotprod = dotproduct(v, &n); diff --git a/test/raytracer/simplify.c b/test/raytracer/simplify.c index 7a4a5457194a8c6bd8d93fb2bee8da3d7a56575b..d8cbe64e2289f522a3ff544a8c3511d4539d8d54 100644 --- a/test/raytracer/simplify.c +++ b/test/raytracer/simplify.c @@ -7,7 +7,7 @@ #include "object.h" #include "simplify.h" -#define INFINITE_RADIUS 1e300 +#define INFINITE_RADIUS HUGE_VAL static flt cone_radius = 1.0; static flt cube_radius = 0.86602540378443859659; /* sqrt(3)/2 */ @@ -44,11 +44,11 @@ static inline void union_bs(struct object * t1, struct object * t2, if (dd2 <= rr2) { /* take the biggest sphere */ if (t1->radius <= t2->radius) { - ASSIGN(obj->center, t2->center); + obj->center = t2->center; obj->radius = t2->radius; set_infinite(t2); } else { - ASSIGN(obj->center, t1->center); + obj->center = t1->center; obj->radius = t1->radius; set_infinite(t1); } @@ -67,12 +67,12 @@ static inline void intersection_bs(struct object * t1, struct object * t2, flt dd2, rr, rr2, rpr, rpr2, diff, d, te1, te2, te3, te4, te, alpha; if (t1->radius >= INFINITE_RADIUS) { - ASSIGN(obj->center, t2->center); + obj->center = t2->center; obj->radius = t2->radius; return; } if (t2->radius >= INFINITE_RADIUS) { - ASSIGN(obj->center, t1->center); + obj->center = t1->center; obj->radius = t1->radius; return; } @@ -83,11 +83,11 @@ static inline void intersection_bs(struct object * t1, struct object * t2, if (dd2 <= rr2) { /* take the smallest sphere */ if (t2->radius <= t1->radius) { - ASSIGN(obj->center, t2->center); + obj->center = t2->center; obj->radius = t2->radius; set_infinite(t2); } else { - ASSIGN(obj->center, t1->center); + obj->center = t1->center; obj->radius = t1->radius; set_infinite(t1); } @@ -96,19 +96,19 @@ static inline void intersection_bs(struct object * t1, struct object * t2, rpr = t1->radius + t2->radius; rpr2 = rpr * rpr; if (dd2 > rpr2) { - ASSIGN(obj->center, origin); + obj->center = origin; obj->radius = 0.0; return; } diff = t1->radius * t1->radius - t2->radius * t2->radius; if (dd2 <= diff) { - ASSIGN(obj->center, t2->center); + obj->center = t2->center; obj->radius = t2->radius; set_infinite(t2); return; } if (dd2 <= -diff) { - ASSIGN(obj->center, t1->center); + obj->center = t1->center; obj->radius = t1->radius; set_infinite(t1); return; @@ -128,7 +128,7 @@ static inline void intersection_bs(struct object * t1, struct object * t2, static inline void difference_bs(struct object * t1, struct object * t2, struct object * obj) { - ASSIGN(obj->center, t1->center); + obj->center = t1->center; obj->radius = t1->radius; set_infinite(t1); } @@ -150,7 +150,7 @@ void compute_bounding_spheres(struct object * obj) obj->radius = obj->max_scale_applied * cylinder_radius; break; case Plane: - ASSIGN(obj->center, plane_center); + obj->center = plane_center; obj->radius = INFINITE_RADIUS; break; case Sphere: diff --git a/test/spass/.depend b/test/spass/.depend new file mode 100644 index 0000000000000000000000000000000000000000..5348867d703b1dda4718595399a233b4ab581cfe --- /dev/null +++ b/test/spass/.depend @@ -0,0 +1,130 @@ +analyze.o: analyze.c analyze.h search.h clause.h sharing.h term.h \ + symbol.h list.h memory.h misc.h stringsx.h stack.h st.h foldfg.h \ + flags.h unify.h context.h subst.h order.h sort.h hash.h subsumption.h \ + component.h vector.h graph.h +clause.o: clause.c clause.h sharing.h term.h symbol.h list.h memory.h \ + misc.h stringsx.h stack.h st.h foldfg.h flags.h unify.h context.h \ + subst.h order.h +clock.o: clock.c clock.h misc.h +closure.o: closure.c closure.h clause.h sharing.h term.h symbol.h list.h \ + memory.h misc.h stringsx.h stack.h st.h foldfg.h flags.h unify.h \ + context.h subst.h order.h table.h partition.h ras.h +cnf.o: cnf.c cnf.h hasharray.h list.h memory.h misc.h renaming.h foldfg.h \ + flags.h unify.h term.h symbol.h stringsx.h stack.h context.h subst.h \ + vector.h resolution.h st.h subsumption.h component.h clause.h sharing.h \ + order.h condensing.h search.h sort.h hash.h rules-inf.h rules-split.h \ + rules-sort.h rules-ur.h defs.h rules-red.h doc-proof.h proofcheck.h \ + options.h dfg.h tableau.h clock.h closure.h table.h partition.h ras.h +component.o: component.c term.h symbol.h list.h memory.h misc.h \ + stringsx.h stack.h component.h +condensing.o: condensing.c subsumption.h misc.h unify.h term.h symbol.h \ + list.h memory.h stringsx.h stack.h context.h subst.h component.h \ + vector.h clause.h sharing.h st.h foldfg.h flags.h order.h condensing.h +context.o: context.c context.h term.h symbol.h list.h memory.h misc.h \ + stringsx.h stack.h +defs.o: defs.c cnf.h hasharray.h list.h memory.h misc.h renaming.h \ + foldfg.h flags.h unify.h term.h symbol.h stringsx.h stack.h context.h \ + subst.h vector.h resolution.h st.h subsumption.h component.h clause.h \ + sharing.h order.h condensing.h search.h sort.h hash.h defs.h +dfgparser.o: dfgparser.c dfg.h list.h memory.h misc.h flags.h clause.h \ + sharing.h term.h symbol.h stringsx.h stack.h st.h foldfg.h unify.h \ + context.h subst.h order.h +dfgscanner.o: dfgscanner.c misc.h memory.h symbol.h list.h stringsx.h \ + term.h stack.h dfg.h flags.h clause.h sharing.h st.h foldfg.h unify.h \ + context.h subst.h order.h dfgparser.h +doc-proof.o: doc-proof.c doc-proof.h clause.h sharing.h term.h symbol.h \ + list.h memory.h misc.h stringsx.h stack.h st.h foldfg.h flags.h unify.h \ + context.h subst.h order.h search.h sort.h hash.h subsumption.h \ + component.h vector.h proofcheck.h options.h dfg.h tableau.h +flags.o: flags.c flags.h memory.h misc.h stringsx.h +foldfg.o: foldfg.c foldfg.h flags.h memory.h misc.h unify.h term.h \ + symbol.h list.h stringsx.h stack.h context.h subst.h +graph.o: graph.c graph.h list.h memory.h misc.h +hash.o: hash.c hash.h list.h memory.h misc.h +hasharray.o: hasharray.c hasharray.h list.h memory.h misc.h +iaparser.o: iaparser.c flags.h memory.h misc.h ia.h list.h symbol.h \ + stringsx.h term.h stack.h foldfg.h unify.h context.h subst.h clause.h \ + sharing.h st.h order.h +iascanner.o: iascanner.c misc.h memory.h symbol.h list.h stringsx.h \ + term.h stack.h ia.h flags.h iaparser.h +kbo.o: kbo.c kbo.h term.h symbol.h list.h memory.h misc.h stringsx.h \ + stack.h context.h foldfg.h flags.h unify.h subst.h order.h +list.o: list.c list.h memory.h misc.h +memory.o: memory.c memory.h misc.h +misc.o: misc.c misc.h +options.o: options.c options.h flags.h memory.h misc.h list.h stringsx.h +order.o: order.c flags.h memory.h misc.h order.h term.h symbol.h list.h \ + stringsx.h stack.h context.h kbo.h foldfg.h unify.h subst.h rpos.h +partition.o: partition.c partition.h memory.h misc.h +proofcheck.o: proofcheck.c proofcheck.h options.h flags.h memory.h misc.h \ + list.h vector.h dfg.h clause.h sharing.h term.h symbol.h stringsx.h \ + stack.h st.h foldfg.h unify.h context.h subst.h order.h tableau.h \ + search.h sort.h hash.h subsumption.h component.h +renaming.o: renaming.c renaming.h misc.h foldfg.h flags.h memory.h \ + unify.h term.h symbol.h list.h stringsx.h stack.h context.h subst.h \ + vector.h +resolution.o: resolution.c resolution.h misc.h unify.h term.h symbol.h \ + list.h memory.h stringsx.h stack.h context.h subst.h foldfg.h flags.h \ + st.h subsumption.h component.h vector.h clause.h sharing.h order.h \ + condensing.h +rpos.o: rpos.c rpos.h misc.h term.h symbol.h list.h memory.h stringsx.h \ + stack.h order.h context.h flags.h +rules-inf.o: rules-inf.c rules-inf.h search.h clause.h sharing.h term.h \ + symbol.h list.h memory.h misc.h stringsx.h stack.h st.h foldfg.h \ + flags.h unify.h context.h subst.h order.h sort.h hash.h subsumption.h \ + component.h vector.h rules-split.h rules-sort.h rules-ur.h defs.h +rules-red.o: rules-red.c rules-red.h sort.h clause.h sharing.h term.h \ + symbol.h list.h memory.h misc.h stringsx.h stack.h st.h foldfg.h \ + flags.h unify.h context.h subst.h order.h hash.h subsumption.h \ + component.h vector.h condensing.h search.h rules-split.h rules-inf.h \ + rules-sort.h rules-ur.h defs.h doc-proof.h proofcheck.h options.h dfg.h \ + tableau.h clock.h closure.h table.h partition.h ras.h +rules-sort.o: rules-sort.c rules-sort.h sort.h clause.h sharing.h term.h \ + symbol.h list.h memory.h misc.h stringsx.h stack.h st.h foldfg.h \ + flags.h unify.h context.h subst.h order.h hash.h subsumption.h \ + component.h vector.h +rules-split.o: rules-split.c rules-split.h clause.h sharing.h term.h \ + symbol.h list.h memory.h misc.h stringsx.h stack.h st.h foldfg.h \ + flags.h unify.h context.h subst.h order.h search.h sort.h hash.h \ + subsumption.h component.h vector.h +rules-ur.o: rules-ur.c rules-ur.h clause.h sharing.h term.h symbol.h \ + list.h memory.h misc.h stringsx.h stack.h st.h foldfg.h flags.h unify.h \ + context.h subst.h order.h +search.o: search.c search.h clause.h sharing.h term.h symbol.h list.h \ + memory.h misc.h stringsx.h stack.h st.h foldfg.h flags.h unify.h \ + context.h subst.h order.h sort.h hash.h subsumption.h component.h \ + vector.h defs.h +sharing.o: sharing.c sharing.h term.h symbol.h list.h memory.h misc.h \ + stringsx.h stack.h st.h foldfg.h flags.h unify.h context.h subst.h +sort.o: sort.c sort.h clause.h sharing.h term.h symbol.h list.h memory.h \ + misc.h stringsx.h stack.h st.h foldfg.h flags.h unify.h context.h \ + subst.h order.h hash.h subsumption.h component.h vector.h +st.o: st.c st.h foldfg.h flags.h memory.h misc.h unify.h term.h symbol.h \ + list.h stringsx.h stack.h context.h subst.h +stack.o: stack.c stack.h misc.h +strings.o: strings.c stringsx.h memory.h misc.h list.h +subst.o: subst.c subst.h term.h symbol.h list.h memory.h misc.h \ + stringsx.h stack.h unify.h context.h +subsumption.o: subsumption.c subsumption.h misc.h unify.h term.h symbol.h \ + list.h memory.h stringsx.h stack.h context.h subst.h component.h \ + vector.h clause.h sharing.h st.h foldfg.h flags.h order.h +symbol.o: symbol.c symbol.h list.h memory.h misc.h stringsx.h +table.o: table.c table.h term.h symbol.h list.h memory.h misc.h \ + stringsx.h stack.h partition.h +tableau.o: tableau.c tableau.h list.h memory.h misc.h clause.h sharing.h \ + term.h symbol.h stringsx.h stack.h st.h foldfg.h flags.h unify.h \ + context.h subst.h order.h +term.o: term.c term.h symbol.h list.h memory.h misc.h stringsx.h stack.h +terminator.o: terminator.c terminator.h misc.h symbol.h list.h memory.h \ + stringsx.h clause.h sharing.h term.h stack.h st.h foldfg.h flags.h \ + unify.h context.h subst.h order.h +top.o: top.c dfg.h list.h memory.h misc.h flags.h clause.h sharing.h \ + term.h symbol.h stringsx.h stack.h st.h foldfg.h unify.h context.h \ + subst.h order.h defs.h search.h sort.h hash.h subsumption.h component.h \ + vector.h ia.h rules-inf.h rules-split.h rules-sort.h rules-ur.h \ + terminator.h rules-red.h condensing.h doc-proof.h proofcheck.h \ + options.h tableau.h clock.h closure.h table.h partition.h ras.h \ + analyze.h graph.h cnf.h hasharray.h renaming.h resolution.h +unify.o: unify.c unify.h term.h symbol.h list.h memory.h misc.h \ + stringsx.h stack.h context.h subst.h +vector.o: vector.c vector.h misc.h diff --git a/test/spass/AUTHORS b/test/spass/AUTHORS new file mode 100644 index 0000000000000000000000000000000000000000..c373ede86cf15698408caf6efce3729d9d4c90ba --- /dev/null +++ b/test/spass/AUTHORS @@ -0,0 +1,23 @@ +Current: +======== + +Christoph Weidenbach <weidenb@mpi-sb.mpg.de> +Uwe Brahm <brahm@mpi-sb.mpg.de> +Thomas Hillenbrand <hillen@mpi-sb.mpg.de> +Dalibor Topic <topic@mpi-sb.mpg.de> + + +Former: +======= + +Bijan Afshordel <afshorde@mpi-sb.mpg.de> +Christof Brinker <chbr@mpi-sb.mpg.de> +Christian Cohrs <cohrs@mpi-sb.mpg.de> +Thorsten Engel <engel@mpi-sb.mpg.de> +Bernd Gaede <gaede@mpi-sb.mpg.de> +Peter Graf <graf@mpi-sb.mpg.de> +Georg Jung <gjung@mpi-sb.mpg.de> +Christoph Meyer <meyer@mpi-sb.mpg.de> +Georg Rock <rock@mpi-sb.mpg.de> +Christian Theobalt <theobalt@mpi-sb.mpg.de> + diff --git a/test/spass/COPYING b/test/spass/COPYING new file mode 100644 index 0000000000000000000000000000000000000000..eeb586b392a5a7dc63d64ba697374ea37e6e122a --- /dev/null +++ b/test/spass/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/test/spass/LICENSE.TXT b/test/spass/LICENSE.TXT new file mode 100644 index 0000000000000000000000000000000000000000..72712689ff8bdc9507ca4549b6d97e6ee70b835b --- /dev/null +++ b/test/spass/LICENSE.TXT @@ -0,0 +1 @@ +see the file "COPYING" diff --git a/test/spass/Makefile b/test/spass/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..b96477070f052ee02492757886fe37ee11c570e5 --- /dev/null +++ b/test/spass/Makefile @@ -0,0 +1,34 @@ +CC=../../ccomp +CFLAGS=-stdlib ../../runtime -dparse -dclight -dasm -fstruct-passing -fstruct-assign + +SRCS=analyze.c clause.c clock.c closure.c cnf.c component.c \ + condensing.c context.c defs.c dfgparser.c dfgscanner.c doc-proof.c \ + flags.c foldfg.c graph.c hash.c hasharray.c iaparser.c iascanner.c \ + kbo.c list.c memory.c misc.c options.c order.c partition.c \ + proofcheck.c renaming.c resolution.c rpos.c rules-inf.c rules-red.c \ + rules-sort.c rules-split.c rules-ur.c search.c sharing.c sort.c st.c \ + stack.c strings.c subst.c subsumption.c symbol.c table.c tableau.c \ + term.c terminator.c top.c unify.c vector.c + +all: spass + +spass: $(SRCS:.c=.o) + $(CC) $(CFLAGS) -o spass $(SRCS:.c=.o) + +clean: + rm -f spass + rm -f *.o *.s *.parsed.c *.light.c + +test: + ./spass small_problem.dfg | grep 'Proof found' + +TIME=xtime -o /dev/null # Xavier's hack +#TIME=time >/dev/null # Otherwise + +bench: + $(TIME) ./spass problem.dfg + +depend: + gcc -MM $(SRCS) > .depend + +include .depend diff --git a/test/spass/Makefile.bak b/test/spass/Makefile.bak new file mode 100644 index 0000000000000000000000000000000000000000..320f6221bff8f98d6d05e4eb0177439042b5e7c0 --- /dev/null +++ b/test/spass/Makefile.bak @@ -0,0 +1,13 @@ +LEVEL = ../../.. +PROG = SPASS + +CPPFLAGS = -DCLOCK_NO_TIMING -fno-strict-aliasing -w +LDFLAGS = -lm + +ifdef SMALL_PROBLEM_SIZE +RUN_OPTIONS="$(PROJ_SRC_DIR)/small_problem.dfg" +else +RUN_OPTIONS="$(PROJ_SRC_DIR)/problem.dfg" +endif + +include ../../Makefile.multisrc diff --git a/test/spass/README b/test/spass/README new file mode 100644 index 0000000000000000000000000000000000000000..efdfb84f1ebd35beec890e64367048cfe74f5528 --- /dev/null +++ b/test/spass/README @@ -0,0 +1,96 @@ + Welcome to SPASS! + ================= + +This is the generic README file for all SPASS distributions, so your downloaded +package may only contain a subset of what is described here. + + + Important Files + =============== + +AUTHORS all authors that contributed to SPASS + +INSTALLATION for a guide to install the prover, man pages, + tools etc.; by default binaries are installed + in /usr/local/bin and man-pages in /usr/local/man; + use the prefix option of make install for a different + path + +COPYING for the licence agreement that you certify by + installation, its the GNU GENERAL PUBLIC LICENSE, Version 2 + +VERSIONHISTORY changes starting from version 1.0.0 + +README is this file + + + + + Programs + ======== + +The distribution contains the following programs. Most +of them give you a brief description if they are called +without arguments. Most of the programs come with man-pages. + +SPASS is our prover for first-order logic with equality. + +FLOTTER translates first-order formulae into clauses; its + incorporated in SPASS and hence now only a link to + SPASS. + +pcs is our proof checker. NOTE that in its default settings + pcs needs an installation of otter for proof checking. + You can also employ SPASS itself for this purpose by the + -o option. + +pgen generates out of a SPASS proof file all subtasks needed + to guarantee the correctness of the proof. + +dfg2otter translates DFG-syntax input files into otter input files, + without any settings commands. + +dfg2otter.pl has the same functionality than dfg2otter but adds specific + settings that are useful if otter is employd as a proof checker + for SPASS. + +dfg2tptp translates DFG-syntax input files into TPTP input files. + + +dfg2ascii provides an ASCII pretty print of DFG-syntax input files + + + Documentation + ============= + +Besides the man pages, in the directory doc you'll find a description +of our input syntax (spass-input-syntax.pdf), a small tutorial (tutorial.pdf) +that is just a print out of our tutorial web page and the complete +theory of SPASS (handbook-spass.pdf). Furthermore, there is a FAQ +database (faq.txt). + + + Examples + ======== + +In the examples directory you'll find some small examples. Further +example collections can be downloaded from the SPASS homepage. By +convention, files ending in ".dfg" are formula files and files ending +in ".cnf" are files containing clauses. + + + WWW + === + +Consider the SPASS homepage at + + http://spass.mpi-sb.mpg.de/ + +for recent developments, downloads etc. + + + + + +have SPASS + Christoph Weidenbach \ No newline at end of file diff --git a/test/spass/VERSIONHISTORY b/test/spass/VERSIONHISTORY new file mode 100644 index 0000000000000000000000000000000000000000..448870ccde1710c01f49be6c89950e9426cbf786 --- /dev/null +++ b/test/spass/VERSIONHISTORY @@ -0,0 +1,135 @@ +Version: 1.0.1 + + - Fixed a bug in the atom definition support where it could happen + that variable dependencies between the atom definition and formulae + outside the definition are discarded. + + - Fixed a bug in the renaming module, where in some cases a renaming + with non-zero benefit was not performed. + +Version: 1.0.2 + + - Fixed inconsistencies between the DFG proof format description in + dfgsyntax.ps and the actual implementation. Proof checking is more + more liberal, because the empty clause needs not to have the highest + clause number. + +Version: 1.0.3 + + - Sharpend renaming; it now potentially produces fewer clauses. + +Version: 1.0.4 + + - Changed some clause generation functions such that sequentially + applying FLOTTER, SPASS and just applying SPASS result in the + very same clause sets. + + - Added the new tool dfg2dfg that supports transformations into + monadic clause classes and their further approximations. + +Version: 1.0.5 + + - Improved SPASS man pages: In particular, we added further detailed + explanations of inference rule flags and soft typing flags. + + - Significantly improved modularity of the code by making the flagstore + object part of the proof search object; so there is no global flagstore + around anymore. These changes touched nearly all modules. + + - Changed certain clause generation procedures such that now applying SPASS + directly to a formula or subsequent application of FLOTTER and SPASS produce + exactly the same ordering of a clause set (literlas). Since the behaviour of + SPASS is not independant from initial clause/literal orderings the changes + make SPASS results a little more robust/more predictable. + As all code was touched, we also included a code style review (comments, + prototypes, ...). + + - Flag values given to SPASS are now checked and rejected if out of range. + +Version: 1.0.6 + + - Strengthened prototyping of functions in particular in the case of function + arguments. This resulted in specialized extra functions. + + - Improved printing efficiency by replacing (f)printf calls with (f)puts calls + whenever possible. + + - Removed the modul global precedence variable of the symbol modul and replaced + it by argument passing. The precedence is now stored in the proofsearch structure. + This affected huge parts of the SPASS code. + + - Adjusted comments and code layout. + + - Strengthened warnings for the gcc compiler. + + - Increased usage of the string module. + + +Version: 2.0.0 + + - Corrections to spellings, documentation. + + - Added handbooks for SPASS and dfg2dfg. + + - Added contextual rewriting. + + - Added semantic tautology check. + + - Fixed bugs in CNF translation: Renaming, Equation elimination rules. + + - Improved splitting clause selection on the basis of reduction potential. + + - Improved robustness of initial clause list ordering. + + - Added the terminator module. + + - Extended formula definition detection/expansion to so called guarded definitions. + + - Improved determination of initial precedence such that as many as possible + equations in the input clause list can be oriented. + + - Added mainloop without complete interreduction. + + - Developed PROOFSEARCH data type enabling a modularization of the SPASS + source code on search engine level, such that several proof attempts can + now be run completely independantly at the same time within SPASS. + + - Moved GUI to Qt 3.0. The GUI now also includes dfg2dfg and new even more + user friendly layout. The GUI runs on any platform where SPASS and Qt are + available. + +Version: 2.1 + + - Fixed a bug in the definition module. Formulae were not normalized before + application of the procedure, leading to wrong matchings of variables. + + - Fixed a bug in the flag module. The subproof flagstore settings were not + complete: ordering flag and the weight flags were missing. + + - Fixed a bug in dfgparser.y, where a missing semicolon with + bison version 1.75 now caused an error. + + - Fixed a bug in cnf.c where the formula "equiv(false,false)" was + not properly treated in function cnf_RemoveTrivialAtoms. + + - Fixed a bug in symbol_LowerSignature where capital 'A's and 'Z's were not + prefixed by a lowercase 'ss' due to their exclusion in the condition. This + caused problems in the result of dfg2tptp applied to dfg input files with + uppercase symbols starting with an 'A' or 'Z'. + + - Now dfg2otter negates conjecture formulae of the SPASS input file + before printing the Otter usable list. + + - Added man pages for dfg2ascii, dfg2otter and dfg2tptp. + + + + + + + + + + + + diff --git a/test/spass/analyze.c b/test/spass/analyze.c new file mode 100644 index 0000000000000000000000000000000000000000..dd47d0d938c41dd51f0124208048f3c659f813b4 --- /dev/null +++ b/test/spass/analyze.c @@ -0,0 +1,774 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * ANALYSIS OF CLAUSE SETS * */ +/* * * */ +/* * $Module: ANALYZE * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include <stdio.h> + +#include "analyze.h" + +static LIST ana_CalculatePredicatePrecedence(LIST, LIST); +static LIST ana_CalculateFunctionPrecedence(LIST, LIST, FLAGSTORE); + +/**************************************************************/ +/* Global Variables */ +/**************************************************************/ + +LIST ana_FINITEMONADICPREDICATES; /* List of monadic predicates with finite extension */ + +BOOL ana_EQUATIONS; /* Problem contains any equations at all */ +static BOOL ana_PEQUATIONS; /* Problem contains positive equations */ +static BOOL ana_NEQUATIONS; /* Problem contains negative equations */ +static BOOL ana_FUNCTIONS; /* Problem contains non-constant function symbols */ +static BOOL ana_PROP; /* Problem contains propositional variables */ +static BOOL ana_GROUND; /* Problem contains non-propositional, non-equational ground atoms */ +static BOOL ana_NONUNIT; /* Problem contains non-unit clauses */ +static BOOL ana_MONADIC; /* Problem contains non-ground monadic predicates */ +static BOOL ana_NONMONADIC; /* Problem contains non-ground n-place predicates, n>1, not equality */ +BOOL ana_SORTRES; /* Problem contains literal not(S(x)) for some S */ +BOOL ana_USORTRES; /* Problem contains literal not(S(t)) for some S */ +static BOOL ana_FINDOMAIN; /* Problem contains clause implying a finite domain */ +static BOOL ana_NONTRIVDOMAIN; /* Problem contains clause implying a domain of size greater one */ +static BOOL ana_CONGROUND; /* Conjecture is ground */ + +static BOOL ana_PUREEQUATIONAL; /* Problem is purely equational */ +static BOOL ana_PUREPROPOSITIONAL; /* Problem is purely propositional */ + +BOOL ana_SORTDECEQUATIONS; /* True if all positive equations are sort decreasing with respect to + the static sort theory contained in the problem */ +static BOOL ana_SORTMANYEQUATIONS; /* True if all positive equations have the + same sort on left and right hand side with + respect to the static sort theory + contained in the problem */ + +static NAT ana_AXIOMCLAUSES; /* Number of axiom clauses */ +static NAT ana_CONCLAUSES; /* Number of conjecture clauses */ +static NAT ana_NONHORNCLAUSES; /* Number of Non-Horn clauses */ + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +void ana_AnalyzeProblem(PROOFSEARCH Search, LIST Clauses) +/************************************************************** + INPUT: A proofsearch object and a list of clauses. + RETURNS: Void. + EFFECT: Analyzes the clauses and sets the analyze variables. + Recomputes the weight for the clauses. + <Search> is modified according to clauses: non trivial domain number + is set +***************************************************************/ +{ + CLAUSE Clause; + + ana_EQUATIONS = FALSE; + ana_PEQUATIONS = FALSE; /* Defaults for properties */ + ana_NEQUATIONS = FALSE; + ana_FUNCTIONS = FALSE; + ana_FINDOMAIN = FALSE; + ana_NONTRIVDOMAIN = FALSE; + ana_MONADIC = FALSE; + ana_NONMONADIC = FALSE; + ana_PROP = FALSE; + ana_GROUND = FALSE; + ana_SORTRES = FALSE; + ana_USORTRES = FALSE; + ana_NONUNIT = FALSE; + ana_CONGROUND = TRUE; + + ana_AXIOMCLAUSES = 0; + ana_CONCLAUSES = 0; + ana_NONHORNCLAUSES = 0; + + list_Delete(ana_FINITEMONADICPREDICATES); + ana_FINITEMONADICPREDICATES = list_Nil(); + + if (list_Empty(Clauses)) + return; + + ana_FINITEMONADICPREDICATES = clause_FiniteMonadicPredicates(Clauses); + + while (!list_Empty(Clauses)) { + Clause = (CLAUSE)list_Car(Clauses); + clause_UpdateWeight(Clause, prfs_Store(Search)); + + if (clause_GetFlag(Clause,CONCLAUSE)) + ana_CONCLAUSES++; + else + ana_AXIOMCLAUSES++; + + if (clause_NumOfSuccLits(Clause) > 1) + ana_NONHORNCLAUSES++; + + if (ana_CONGROUND && clause_GetFlag(Clause,CONCLAUSE) && + clause_MaxVar(Clause) != symbol_GetInitialStandardVarCounter()) + ana_CONGROUND = FALSE; + if (!ana_PEQUATIONS && clause_ContainsPositiveEquations(Clause)) { + ana_PEQUATIONS = TRUE; + } + if (!ana_NEQUATIONS && clause_ContainsNegativeEquations(Clause)) { + ana_NEQUATIONS = TRUE; + } + if (!ana_MONADIC || !ana_NONMONADIC || !ana_PROP || !ana_GROUND) + clause_ContainsFolAtom(Clause,&ana_PROP,&ana_GROUND,&ana_MONADIC,&ana_NONMONADIC); + + if (!ana_FUNCTIONS && clause_ContainsFunctions(Clause)) { + ana_FUNCTIONS = TRUE; + } + if (!ana_FINDOMAIN && clause_ImpliesFiniteDomain(Clause)) { + ana_FINDOMAIN = TRUE; + } + if (!ana_NONTRIVDOMAIN && clause_ImpliesNonTrivialDomain(Clause)) { + prfs_SetNonTrivClauseNumber(Search, clause_Number(Clause)); + ana_NONTRIVDOMAIN = TRUE; + } + if (!ana_NONUNIT && clause_Length(Clause) > 1) { + ana_NONUNIT = TRUE; + } + if (!ana_SORTRES || !ana_USORTRES) + clause_ContainsSortRestriction(Clause,&ana_SORTRES,&ana_USORTRES); + + Clauses = list_Cdr(Clauses); + } + + ana_PUREEQUATIONAL = ((ana_PEQUATIONS || ana_NEQUATIONS) && !ana_MONADIC && + !ana_NONMONADIC && !ana_PROP && !ana_GROUND); + ana_EQUATIONS = (ana_PEQUATIONS || ana_NEQUATIONS); + ana_PUREPROPOSITIONAL = (!ana_PEQUATIONS && !ana_NEQUATIONS &&!ana_MONADIC && + !ana_NONMONADIC && ana_PROP); +} + + +void ana_AnalyzeSortStructure(LIST Clauses, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A list of clauses, a flag store and a precedence. + RETURNS: Nothing. + EFFECT: The sort structure with respect to equations is analyzed. + It is detected whether all equations are many sorted or + sort decreasing. +***************************************************************/ +{ + if (ana_PEQUATIONS && ana_SORTRES) { + STR Result; + Result = sort_AnalyzeSortStructure(Clauses,Flags,Precedence); + ana_SORTMANYEQUATIONS = (Result == SORTEQMANY); + ana_SORTDECEQUATIONS = (Result == SORTEQMANY || Result == SORTEQDECR); + } +} + + +void ana_Print(FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A flag store and a precedence. + RETURNS: Nothing. + EFFECT: The results of an analysis stored in the module variables + is printed to stdout. +***************************************************************/ +{ + const char* Horn; + + if (ana_NONHORNCLAUSES == 0) + Horn = "Horn"; + else + Horn = "Non-Horn"; + + if (ana_MONADIC && !ana_NONMONADIC) { + printf("\n This is a monadic %s problem",Horn); + if (ana_PEQUATIONS || ana_NEQUATIONS) + fputs(" with equality.", stdout); + else + fputs(" without equality.", stdout); + } + else + if (ana_PEQUATIONS || ana_NEQUATIONS) { + if (ana_NONMONADIC || ana_MONADIC || ana_PROP) + printf("\n This is a first-order %s problem containing equality.",Horn); + else + if (ana_NONUNIT) + printf("\n This is a pure equality %s problem.",Horn); + else + fputs("\n This is a unit equality problem.", stdout); + } + else + if (ana_NONMONADIC || ana_MONADIC) + printf("\n This is a first-order %s problem without equality.",Horn); + + if (ana_PUREPROPOSITIONAL) + printf("\n This is a propositional %s problem.",Horn); + else + if (ana_FINDOMAIN || !ana_FUNCTIONS) { + fputs("\n This is a problem that has, if any, a finite domain model.", + stdout); + if (ana_FINDOMAIN) + fputs("\n There is a finite domain clause.", stdout); + if (!ana_FUNCTIONS) + fputs("\n There are no function symbols.", stdout); + } + + if (ana_NONTRIVDOMAIN) + fputs("\n This is a problem that has, if any, a non-trivial domain model.", + stdout); + + + if (ana_SORTRES) { + fputs("\n This is a problem that contains sort information.", stdout); + if (ana_PEQUATIONS) { + if (ana_SORTMANYEQUATIONS) + fputs("\n All equations are many sorted.", stdout); + else { + if (ana_SORTDECEQUATIONS) + fputs("\n All equations are sort-decreasing.", stdout); + } + } + } + + if (ana_CONCLAUSES > 0 && ana_CONGROUND && !ana_PUREPROPOSITIONAL) + fputs("\n The conjecture is ground.", stdout); + + if (!list_Empty(ana_FINITEMONADICPREDICATES)) { + LIST Scan; + fputs("\n The following monadic predicates have finite extensions: ", stdout); + for (Scan=ana_FINITEMONADICPREDICATES;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + symbol_Print((SYMBOL)list_Car(Scan)); + if (!list_Empty(list_Cdr(Scan))) + fputs(", ", stdout); + } + putchar('.'); + } + + printf("\n Axiom clauses: %d Conjecture clauses: %d",ana_AXIOMCLAUSES,ana_CONCLAUSES); + + flag_PrintInferenceRules(Flags); + flag_PrintReductionRules(Flags); + fputs("\n Extras : ", stdout); + if (flag_GetFlagValue(Flags, flag_SATINPUT)) + fputs("Input Saturation, ", stdout); + else + fputs("No Input Saturation, ", stdout); + if (flag_GetFlagValue(Flags, flag_SELECT) == flag_SELECTOFF) + fputs("No Selection, ", stdout); + else + if (flag_GetFlagValue(Flags, flag_SELECT) == flag_SELECTIFSEVERALMAXIMAL) + fputs("Dynamic Selection, ", stdout); + else + fputs("Always Selection, ", stdout); + if (flag_GetFlagValue(Flags, flag_SPLITS) == flag_SPLITSUNLIMITED) + fputs("Full Splitting, ", stdout); + else + if (flag_GetFlagValue(Flags, flag_SPLITS) == flag_SPLITSOFF) + fputs("No Splitting, ", stdout); + else + printf("Maximum of %d Splits, ",flag_GetFlagValue(Flags, flag_SPLITS)); + if (flag_GetFlagValue(Flags, flag_FULLRED)) + fputs("Full Reduction, ", stdout); + else + fputs("Lazy Reduction, ", stdout); + printf(" Ratio: %d, FuncWeight: %d, VarWeight: %d", + flag_GetFlagValue(Flags, flag_WDRATIO), + flag_GetFlagValue(Flags, flag_FUNCWEIGHT), + flag_GetFlagValue(Flags, flag_VARWEIGHT)); + fputs("\n Precedence: ", stdout); + fol_PrintPrecedence(Precedence); + fputs("\n Ordering : ", stdout); + fputs(flag_GetFlagValue(Flags, flag_ORD) == flag_ORDKBO ? "KBO" : "RPOS", + stdout); +} + + +void ana_AutoConfiguration(LIST Clauses, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A list of clauses, a flag store and a precedence. + RETURNS: Nothing. + EFFECT: Based on the values of the ana analysis module, an appropriate + complete configuration of inference, reduction rules and other + settings is established. +***************************************************************/ +{ + LIST Scan, Functions, Predicates, Constants; + + Functions = symbol_GetAllFunctions(); + Predicates = fol_GetNonFOLPredicates(); + + /* Set precedence */ + Predicates = ana_CalculatePredicatePrecedence(Predicates, Clauses); + Functions = ana_CalculateFunctionPrecedence(Functions, Clauses, Flags); + Constants = list_Nil(); + + for (Scan=Functions; !list_Empty(Scan); Scan=list_Cdr(Scan)) + if (symbol_IsConstant((SYMBOL)list_Car(Scan))) + Constants = list_Cons(list_Car(Scan),Constants); + Functions = list_NPointerDifference(Functions,Constants); + Constants = list_NReverse(Constants); + + for ( ; !list_Empty(Functions); Functions = list_Pop(Functions)) + symbol_SetIncreasedOrdering(Precedence, (SYMBOL)list_Car(Functions)); + /* Predicates < Functions */ + for ( ; !list_Empty(Predicates); Predicates = list_Pop(Predicates)) + symbol_SetIncreasedOrdering(Precedence, (SYMBOL)list_Car(Predicates)); + /* Constants < Predicates */ + /* Predicates < Functions */ + for ( ; !list_Empty(Constants); Constants = list_Pop(Constants)) + symbol_SetIncreasedOrdering(Precedence, (SYMBOL)list_Car(Constants)); + + flag_ClearInferenceRules(Flags); + flag_ClearReductionRules(Flags); + + flag_SetFlagValue(Flags, flag_ROBV, flag_ROBVON); + flag_SetFlagValue(Flags, flag_RTAUT, flag_RTAUTSYNTACTIC); + flag_SetFlagValue(Flags, flag_RFSUB, flag_RFSUBON); + flag_SetFlagValue(Flags, flag_RBSUB, flag_RBSUBON); + flag_SetFlagValue(Flags, flag_RFMRR, flag_RFMRRON); + flag_SetFlagValue(Flags, flag_RBMRR, flag_RBMRRON); + flag_SetFlagValue(Flags, flag_RUNC, flag_RUNCON); + flag_SetFlagValue(Flags, flag_FULLRED, flag_FULLREDON); + /*flag_SetFlagValue(Flags, flag_FUNCWEIGHT,1); + flag_SetFlagValue(Flags, flag_VARWEIGHT,1);*/ + flag_SetFlagValue(Flags, flag_WDRATIO,5); + + if (ana_NEQUATIONS) { + flag_SetFlagValue(Flags, flag_IEQR, flag_EQUALITYRESOLUTIONON); + if (ana_NONUNIT) { + if (ana_NONTRIVDOMAIN) + flag_SetFlagValue(Flags, flag_RAED, flag_RAEDPOTUNSOUND); + else + flag_SetFlagValue(Flags, flag_RAED, flag_RAEDSOUND); + } + } + + if (ana_PEQUATIONS) { + flag_SetFlagValue(Flags, flag_ISPR, flag_SUPERPOSITIONRIGHTON); + flag_SetFlagValue(Flags, flag_ISPL, flag_SUPERPOSITIONLEFTON); + if (ana_NONHORNCLAUSES > 0) + flag_SetFlagValue(Flags, flag_IEQF, flag_EQUALITYFACTORINGON); + if (ana_NONUNIT) + flag_SetFlagValue(Flags, flag_RCON, flag_RCONON); + flag_SetFlagValue(Flags, flag_RFREW, flag_RFREWON); + flag_SetFlagValue(Flags, flag_RBREW, flag_RBREWON); + flag_SetFlagValue(Flags, flag_RFCRW, flag_RFCRWOFF); /* Here we could activate contextual rewriting */ + flag_SetFlagValue(Flags, flag_RBCRW, flag_RBCRWOFF); + } + + if (ana_SORTRES) { + flag_SetFlagValue(Flags, flag_SORTS, flag_SORTSMONADICWITHVARIABLE); + flag_SetFlagValue(Flags, flag_IEMS, flag_EMPTYSORTON); + flag_SetFlagValue(Flags, flag_ISOR, flag_SORTRESOLUTIONON); + flag_SetFlagValue(Flags, flag_RSSI, flag_RSSION); + if (!ana_PEQUATIONS || ana_SORTMANYEQUATIONS) + flag_SetFlagValue(Flags, flag_RSST, flag_RSSTON); + } + else + flag_SetFlagValue(Flags, flag_SORTS, flag_SORTSOFF); + + if (ana_MONADIC || ana_NONMONADIC) { /* Problem contains real predicates */ + flag_SetFlagValue(Flags, flag_IORE, flag_ORDEREDRESOLUTIONNOEQUATIONS); + if (ana_NONHORNCLAUSES > 0) + flag_SetFlagValue(Flags, flag_IOFC, flag_FACTORINGONLYRIGHT); + if (ana_NONUNIT) + flag_SetFlagValue(Flags, flag_RCON, flag_RCONON); + } + + + if (!ana_FUNCTIONS) + flag_SetFlagValue(Flags, flag_SELECT, flag_SELECTALWAYS); + else + if (ana_NONUNIT) + flag_SetFlagValue(Flags, flag_SELECT, flag_SELECTIFSEVERALMAXIMAL); + else + flag_SetFlagValue(Flags, flag_SELECT, flag_SELECTOFF); + + if (ana_CONCLAUSES < ana_AXIOMCLAUSES || (ana_CONGROUND && !ana_PUREPROPOSITIONAL)) + flag_SetFlagValue(Flags, flag_SATINPUT, flag_SATINPUTON); + else + flag_SetFlagValue(Flags, flag_SATINPUT, flag_SATINPUTOFF); + + if (ana_NONHORNCLAUSES > 0) + flag_SetFlagValue(Flags, flag_SPLITS, flag_SPLITSUNLIMITED); + else + flag_SetFlagValue(Flags, flag_SPLITS, flag_SPLITSOFF); +} + + +void ana_ExploitSortAnalysis(FLAGSTORE Flags) +/************************************************************** + INPUT: A flag store. + EFFECT: If all equations are many sorted and or no positive + equations occur at all and the problem contains sort + information, static soft typing is activated. +***************************************************************/ +{ + if (ana_SORTRES && (!ana_PEQUATIONS || ana_SORTMANYEQUATIONS)) + flag_SetFlagValue(Flags, flag_RSST, flag_RSSTON); +} + + +static LIST ana_CalculatePredicatePrecedence(LIST Predicates, LIST Clauses) +/************************************************************** + INPUT: A list of predicates and a list of clauses. + RETURNS: A list of predicate symbols, which should be used + for setting the symbol precedence. The list is sorted + in descending order, that means predicates with highest + precedence come first. + EFFECT: Analyze the clause list to build a directed graph G where + the predicates are vertices. There's an edge (P,Q) in + G iff a clause exists where P is a negative literal + and Q is a positive literal and P != Q. Apply DFS to + find the strongly connected components of this graph. + The <Predicates> list is deleted. + CAUTION: The predicate list must contain ALL predicates + occurring in the clause list! +***************************************************************/ +{ + GRAPH graph; + LIST result, scan; + int i, j; + NAT count; + SYMBOL s; + + /* clause_ListPrint(Clauses); DBG */ + + if (list_Empty(Predicates)) { + return Predicates; + } + + graph = graph_Create(); + + /* First create the nodes: one node for every predicate symbol. */ + for ( ; !list_Empty(Predicates); Predicates = list_Pop(Predicates)) + graph_AddNode(graph, symbol_Index((SYMBOL)list_Car(Predicates))); + + /* Now scan the clause clause list to create the edges */ + /* An edge (P,Q) means P is smaller than Q */ + for (scan = Clauses; !list_Empty(scan); scan = list_Cdr(scan)) { + CLAUSE c = list_Car(scan); + + for (i = clause_FirstLitIndex(); i < clause_FirstSuccedentLitIndex(c); i++) { + SYMBOL negPred = term_TopSymbol(clause_GetLiteralAtom(c, i)); + if (!symbol_Equal(negPred, fol_Equality())) { /* negative predicate */ + for (j = clause_FirstSuccedentLitIndex(c); j < clause_Length(c); j++) { + SYMBOL posPred = term_TopSymbol(clause_GetLiteralAtom(c, j)); + if (!symbol_Equal(posPred, fol_Equality()) && /* positive predicate */ + negPred != posPred) { /* No self loops! */ + graph_AddEdge(graph_GetNode(graph, symbol_Index(negPred)), + graph_GetNode(graph, symbol_Index(posPred))); + } + } + } + } + } + + /* graph_Print(graph); fflush(stdout); DBG */ + + /* Calculate the strongly connected components of the graph */ + count = graph_StronglyConnectedComponents(graph); + + /* Now create the precedence list by scanning the nodes. */ + /* If there's a link between two strongly connected components */ + /* c1 and c2 then component_num(c1) > component_num(c2), so the */ + /* following code creates a valid precedence list in descending */ + /* order. */ + result = list_Nil(); + for (i = count - 1; i >= 0; i--) { + for (scan = graph_Nodes(graph); !list_Empty(scan); scan = list_Cdr(scan)) { + GRAPHNODE n = list_Car(scan); + if (graph_NodeCompNum(n) == i) { + /* The symbol represented by the node <<n> belongs to component <i> */ + s = symbol_GetSigSymbol(graph_NodeNumber(n)); + result = list_Cons((POINTER)s, result); + } + } + } + + /* putchar('\n'); + for (scan = result; !list_Empty(scan); scan = list_Cdr(scan)) { + s = (SYMBOL) list_Car(scan); + symbol_Print(s); + putchar(' '); + } + putchar('\n'); fflush(stdout); DBG */ + + graph_Delete(graph); + + return result; +} + + +/* We use the node info to store the degree of the node */ +static __inline__ NAT ana_NodeDegree(GRAPHNODE Node) +{ + return (NAT)graph_NodeInfo(Node); +} + + +static __inline__ void ana_IncNodeDegree(GRAPHNODE Node) +{ + graph_NodeSetInfo(Node, (POINTER)(ana_NodeDegree(Node)+1)); +} + +static BOOL ana_NodeGreater(GRAPHNODE N1, GRAPHNODE N2) +/************************************************************** + INPUT: Two graph nodes. + RETURNS: TRUE, if N1 is greater than N2. + EFFECT: This function is used to sort the node list + of the graph in ana_CalculateFunctionPrecedence. +***************************************************************/ +{ + return (symbol_Arity(symbol_GetSigSymbol(graph_NodeNumber(N1))) > + symbol_Arity(symbol_GetSigSymbol(graph_NodeNumber(N2)))); +} + + +static BOOL ana_BidirectionalDistributivity(LIST SymbolPairs) +/************************************************************** + INPUT: A list of symbol pairs defining distributivity. + RETURNS: TRUE, if the list contains two pairs (s1, s2) and (s2, s1) + FALSE otherwise. + EFFECT: This function is used to detect symbols that are distributive + in both directions, logical OR and AND for example. +***************************************************************/ +{ + LIST scan, actPair, nextPair; + + for ( ; !list_Empty(SymbolPairs); SymbolPairs = list_Cdr(SymbolPairs)) { + actPair = list_Car(SymbolPairs); + /* If actPair = (s1, s2), check whether there's a pair (s2, s1) in list */ + for (scan = list_Cdr(SymbolPairs); !list_Empty(scan); scan = list_Cdr(scan)) { + nextPair = list_Car(scan); + if (symbol_Equal((SYMBOL)list_PairFirst(actPair),(SYMBOL)list_PairSecond(nextPair)) && + symbol_Equal((SYMBOL)list_PairSecond(actPair),(SYMBOL)list_PairFirst(nextPair))) + return TRUE; + } + } + return FALSE; +} + + +static LIST ana_CalculateFunctionPrecedence(LIST Functions, LIST Clauses, + FLAGSTORE Flags) +/************************************************************** + INPUT: A list of functions, a list of clauses and + a flag store. + RETURNS: A list of function symbols, which should be used + for setting the symbol precedence. The list is sorted + in descending order, that means function with highest + precedence come first. + EFFECT: Analyzes the clauses to build a directed graph G with + function symbol as nodes. An edge (f,g) or in G means + f should have lower precedence than g. + An edge (f,g) or (g,f) is created if there's an equation + equal(f(...), g(...)) in the clause list. + The direction of the edge depends on the degree of the + nodes and the symbol arity. + Then find the strongly connected components of this + graph. + The "Ordering" flag will be set in the flag store. + CAUTION: The value of "ana_PEQUATIONS" must be up to date. +***************************************************************/ +{ + GRAPH graph; + GRAPHNODE n1, n2; + LIST result, scan, scan2, distrPairs; + NAT i, j; + SYMBOL s, Add, Mult; + + if (list_Empty(Functions)) + return Functions; /* Problem contains no functions */ + else if (!ana_PEQUATIONS) { + Functions = list_NumberSort(Functions, (NAT (*)(POINTER)) symbol_PositiveArity); + return Functions; + } + + graph = graph_Create(); + /* First create the nodes: one node for every function symbol. */ + for (; !list_Empty(Functions); Functions = list_Pop(Functions)) + graph_AddNode(graph, symbol_Index((SYMBOL)list_Car(Functions))); + + /* Now sort the node list wrt descending symbol arity. */ + graph_SortNodes(graph, ana_NodeGreater); + + /* A list of pairs (add, multiply) of distributive symbols */ + distrPairs = list_Nil(); + + /* Now add undirected edges: there's an undirected edge between */ + /* two nodes if the symbols occur as top symbols in a positive */ + /* equation. */ + for (scan = Clauses; !list_Empty(scan); scan = list_Cdr(scan)) { + CLAUSE c = list_Car(scan); + for (i = clause_FirstSuccedentLitIndex(c); + i <= clause_LastSuccedentLitIndex(c); i++) { + if (clause_LiteralIsEquality(clause_GetLiteral(c, i))) { + /* Consider only positive equations */ + TERM t1, t2; + + if (fol_DistributiveEquation(clause_GetLiteralAtom(c,i), &Add, &Mult)) { + /* Add a pair (Add, Mult) to <distrTerms> */ + distrPairs = list_Cons(list_PairCreate((POINTER)Add, (POINTER)Mult), + distrPairs); + /*fputs("\nDISTRIBUTIVITY: ", stdout); + term_PrintPrefix(clause_GetLiteralAtom(c,i)); + fputs(" Add=", stdout); symbol_Print(Add); + fputs(" Mult=", stdout); symbol_Print(Mult); fflush(stdout); DBG */ + } + + t1 = term_FirstArgument(clause_GetLiteralAtom(c, i)); + t2 = term_SecondArgument(clause_GetLiteralAtom(c, i)); + + if (!term_IsVariable(t1) && !term_IsVariable(t2) && + !term_EqualTopSymbols(t1, t2) && /* No self loops! */ + !term_HasSubterm(t1, t2) && /* No subterm property */ + !term_HasSubterm(t2, t1)) { + n1 = graph_GetNode(graph, symbol_Index(term_TopSymbol(t1))); + n2 = graph_GetNode(graph, symbol_Index(term_TopSymbol(t2))); + /* Create an undirected edge by adding two directed edges */ + graph_AddEdge(n1, n2); + graph_AddEdge(n2, n1); + /* Use the node info for the degree of the node */ + ana_IncNodeDegree(n1); + ana_IncNodeDegree(n2); + } + } + } + } + + /* putchar('\n'); + for (scan = graph_Nodes(graph); !list_Empty(scan); scan = list_Cdr(scan)) { + n1 = list_Car(scan); + printf("(%s,%d,%u), ", + symbol_Name(symbol_GetSigSymbol(graph_NodeNumber(n1))), + graph_NodeNumber(n1), ana_NodeDegree(n1)); + } + graph_Print(graph); fflush(stdout); DBG */ + + graph_DeleteDuplicateEdges(graph); + + /* Transform the undirected graph into a directed graph. */ + for (scan = graph_Nodes(graph); !list_Empty(scan); scan = list_Cdr(scan)) { + n1 = list_Car(scan); + result = list_Nil(); /* Collect edges from n1 that shall be deleted */ + for (scan2 = graph_NodeNeighbors(n1); !list_Empty(scan2); + scan2 = list_Cdr(scan2)) { + int a1, a2; + n2 = list_Car(scan2); + /* Get the node degrees in the undirected graph with multiple edges */ + i = ana_NodeDegree(n1); + j = ana_NodeDegree(n2); + a1 = symbol_Arity(symbol_GetSigSymbol(graph_NodeNumber(n1))); + a2 = symbol_Arity(symbol_GetSigSymbol(graph_NodeNumber(n2))); + + if (i > j || (i==j && a1 >= a2)) { + /* symbol2 <= symbol1, so remove edge n1 -> n2 */ + result = list_Cons(n2, result); + } + if (i < j || (i==j && a1 <= a2)) { + /* symbol1 <= symbol2, so remove edge n2 -> n1 */ + graph_DeleteEdge(n2, n1); + } + /* NOTE: If (i==j && a1==a2) both edges are deleted! */ + } + /* Now delete edges from n1 */ + for ( ; !list_Empty(result); result = list_Pop(result)) + graph_DeleteEdge(n1, list_Car(result)); + } + + if (!list_Empty(distrPairs) && !ana_BidirectionalDistributivity(distrPairs)) { + /* Enable RPO ordering, otherwise the default KBO will be used. */ + flag_SetFlagValue(Flags, flag_ORD, flag_ORDRPOS); + } + + /* Now examine the list of distribute symbols */ + /* since they've highest priority. */ + for ( ; !list_Empty(distrPairs); distrPairs = list_Pop(distrPairs)) { + scan = list_Car(distrPairs); /* A pair (Add, Mult) */ + /* Addition */ + n1 = graph_GetNode(graph, + symbol_Index((SYMBOL)list_PairFirst(scan))); + /* Multiplication */ + n2 = graph_GetNode(graph, + symbol_Index((SYMBOL)list_PairSecond(scan))); + /* Remove any edges between n1 and n2 */ + graph_DeleteEdge(n1, n2); + graph_DeleteEdge(n2, n1); + /* Add one edge Addition -> Multiplication */ + graph_AddEdge(n1, n2); + list_PairFree(scan); + } + + /* fputs("\n------------------------",stdout); + graph_Print(graph); fflush(stdout); DBG */ + + /* Calculate the strongly connected components of the graph. */ + /* <i> is the number of SCCs. */ + i = graph_StronglyConnectedComponents(graph); + + /* Now create the precedence list by scanning the nodes. */ + /* If there's a link between two strongly connected components */ + /* c1 and c2 then component_num(c1) > component_num(c2), so the */ + /* following code creates a valid precedence list in descending */ + /* order. */ + result = list_Nil(); + while (i-- > 0) { /* for i = numberOfSCCs -1 dowto 0 */ + for (scan = graph_Nodes(graph); !list_Empty(scan); scan = list_Cdr(scan)) { + n1 = list_Car(scan); + if (graph_NodeCompNum(n1) == i) { + /* The symbol represented by the node <n> belongs to component <i> */ + s = symbol_GetSigSymbol(graph_NodeNumber(n1)); + result = list_Cons((POINTER)s, result); + } + } + } + + /* putchar('\n'); + for (scan = result; !list_Empty(scan); scan = list_Cdr(scan)) { + s = (SYMBOL) list_Car(scan); + symbol_Print(s); + fputs(" > ", stdout); + } + putchar('\n'); fflush(stdout); DBG */ + + graph_Delete(graph); + + return result; +} diff --git a/test/spass/analyze.h b/test/spass/analyze.h new file mode 100644 index 0000000000000000000000000000000000000000..a44c893f655a167ee2285038127a507d5bc2b8fe --- /dev/null +++ b/test/spass/analyze.h @@ -0,0 +1,121 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * ANALYSIS OF CLAUSE SETS * */ +/* * * */ +/* * $Module: ANALYZE * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _ANALYZE_ +#define _ANALYZE_ + +#include "search.h" +#include "clause.h" +#include "sort.h" +#include "list.h" +#include "graph.h" + +/**************************************************************/ +/* Global Variables */ +/**************************************************************/ + +extern BOOL ana_EQUATIONS; +extern BOOL ana_SORTRES; +extern BOOL ana_USORTRES; +extern BOOL ana_SORTDECEQUATIONS; + +extern LIST ana_FINITEMONADICPREDICATES; + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +static __inline__ BOOL ana_Equations(void) +{ + return ana_EQUATIONS; +} + +static __inline__ BOOL ana_SortRestrictions(void) +{ + return ana_SORTRES; +} + +static __inline__ BOOL ana_UnsolvedSortRestrictions(void) +{ + return ana_USORTRES; +} + +static __inline__ BOOL ana_SortDecreasing(void) +{ + return ana_SORTDECEQUATIONS; +} + +static __inline__ void ana_Init(void) +{ + ana_FINITEMONADICPREDICATES = list_Nil(); +} + +static __inline__ void ana_Free(void) +{ + list_Delete(ana_FINITEMONADICPREDICATES); +} + +static __inline__ LIST ana_FinMonPredList(void) +{ + return ana_FINITEMONADICPREDICATES; +} + + + + + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +void ana_AnalyzeProblem(PROOFSEARCH, LIST); +void ana_AnalyzeSortStructure(LIST, FLAGSTORE, PRECEDENCE); +void ana_AutoConfiguration(LIST, FLAGSTORE, PRECEDENCE); +void ana_ExploitSortAnalysis(FLAGSTORE); +void ana_Print(FLAGSTORE, PRECEDENCE); + +#endif diff --git a/test/spass/approx.h b/test/spass/approx.h new file mode 100644 index 0000000000000000000000000000000000000000..5e50d39e0ba5b2f3e8dead1573c21d6c4ec27d55 --- /dev/null +++ b/test/spass/approx.h @@ -0,0 +1,61 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CLAUSE APPROXIMATION * */ +/* * * */ +/* * $Module: APPROX * */ +/* * * */ +/* * Copyright (C) 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/* $RCSfile$ */ + +#ifndef _APPROX_ +#define _APPROX_ + +#include "list.h" +#include "clause.h" + +void approx_Init(void); + +LIST approx_MonadicByProjection(LIST, FLAGSTORE, PRECEDENCE); +LIST approx_MonadicByTermEncoding(LIST, FLAGSTORE, PRECEDENCE); +LIST approx_MonadicMakeLinear(LIST, FLAGSTORE, PRECEDENCE); +LIST approx_HornMonadicFlattenHeads(CLAUSE, BOOL, BOOL, FLAGSTORE, PRECEDENCE); +LIST approx_MakeHorn(CLAUSE, FLAGSTORE, PRECEDENCE); + +#endif diff --git a/test/spass/clause.c b/test/spass/clause.c new file mode 100644 index 0000000000000000000000000000000000000000..6b2e3f6f53228c29226fb957d2e8589faa64e6d6 --- /dev/null +++ b/test/spass/clause.c @@ -0,0 +1,5008 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CLAUSES * */ +/* * * */ +/* * $Module: CLAUSE * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "clause.h" + +/**************************************************************/ +/* Global variables and constants */ +/**************************************************************/ + +/* Means weight of literal or clause is undefined */ +const NAT clause_WEIGHTUNDEFINED = NAT_MAX; + +int clause_CLAUSECOUNTER; +NAT clause_STAMPID; + +/* The following array is used for bucket sort on clauses */ +#define clause_MAXWEIGHT 20 +LIST clause_SORT[clause_MAXWEIGHT+1]; + +/**************************************************************/ +/* Inline functions */ +/**************************************************************/ + +static __inline__ void clause_FreeLitArray(CLAUSE Clause) +{ + NAT Length = clause_Length(Clause); + if (Length > 0) + memory_Free(Clause->literals, sizeof(LITERAL) * Length); +} + + +/**************************************************************/ +/* Primitive literal functions */ +/**************************************************************/ + +BOOL clause_LiteralIsLiteral(LITERAL Literal) +/********************************************************* + INPUT: A literal. + RETURNS: TRUE, if 'Literal' is not NULL and has a predicate + symbol as its atoms top symbol. +**********************************************************/ +{ + return ((Literal != NULL) && + symbol_IsPredicate(clause_LiteralPredicate(Literal))); +} + +NAT clause_LiteralComputeWeight(LITERAL Literal, FLAGSTORE Flags) +/********************************************************* + INPUT: A literal and a flag store. + RETURNS: The weight of the literal. + CAUTION: This function does not update the weight of the literal! +**********************************************************/ +{ + TERM Term; + int Bottom; + NAT Number; + +#ifdef CHECK + if (!clause_LiteralIsLiteral(Literal)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralComputeWeight :"); + misc_ErrorReport("Illegal Input. Input not a literal."); + misc_FinishErrorReport(); + } +#endif + + Term = clause_LiteralSignedAtom(Literal); + Bottom = stack_Bottom(); + Number = 0; + + do { + if (term_IsComplex(Term)) { + Number += flag_GetFlagValue(Flags, flag_FUNCWEIGHT); + stack_Push(term_ArgumentList(Term)); + } + else + if (term_IsVariable(Term)) + Number += flag_GetFlagValue(Flags, flag_VARWEIGHT); + else + Number += flag_GetFlagValue(Flags, flag_FUNCWEIGHT); + + while (!stack_Empty(Bottom) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Bottom)) { + Term = (TERM) list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Bottom)); + + return Number; + +} + +LITERAL clause_LiteralCreate(TERM Atom, CLAUSE Clause) +/********************************************************** + INPUT: A Pointer to a signed Predicate-Term and one to a + clause it shall belong to. + RETURNS: An appropriate literal where the other values + are set to default values. + MEMORY: A LITERAL_NODE is allocated. + CAUTION: The weight of the literal is not set correctly! +***********************************************************/ +{ + LITERAL Result; + +#ifdef CHECK + if (!term_IsTerm(Atom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralCreate:"); + misc_ErrorReport("\n Illegal input. Input not a term."); + misc_FinishErrorReport(); + } + if (!symbol_IsPredicate(term_TopSymbol(Atom)) && + (term_TopSymbol(Atom) != fol_Not())) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralCreate:"); + misc_ErrorReport("\n Illegal input. No predicate- or negated term."); + misc_FinishErrorReport(); + } +#endif + + Result = (LITERAL)memory_Malloc(sizeof(LITERAL_NODE)); + + Result->atomWithSign = Atom; + Result->oriented = FALSE; + Result->weight = clause_WEIGHTUNDEFINED; + Result->maxLit = 0; + Result->owningClause = Clause; + + return Result; +} + + +LITERAL clause_LiteralCreateNegative(TERM Atom, CLAUSE Clause) +/********************************************************** + INPUT: A Pointer to a unsigned Predicate-Term and one to a + clause it shall belong to. + RETURNS: An appropriate literal where the other values + are set to default values and the term gets a sign. + MEMORY: A LITERAL_NODE is allocated. + CAUTION: The weight of the literal is not set correctly! +***********************************************************/ +{ + LITERAL Result; + +#ifdef CHECK + if (!term_IsTerm(Atom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralCreateNegative:"); + misc_ErrorReport("\n Illegal input. Input not an atom."); + misc_FinishErrorReport(); + } + if (!symbol_IsPredicate(term_TopSymbol(Atom)) && + (term_TopSymbol(Atom) != fol_Not())) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralCreateNegative:"); + misc_ErrorReport("\n Illegal input. Input term not normalized."); + misc_FinishErrorReport(); + } +#endif + + Result = (LITERAL)memory_Malloc(sizeof(LITERAL_NODE)); + + term_RplacSupertermList(Atom, list_Nil()); + + Result->atomWithSign = term_Create(fol_Not(), list_List(Atom)); + Result->oriented = FALSE; + Result->maxLit = 0; + Result->weight = clause_WEIGHTUNDEFINED; + Result->owningClause = Clause; + + return Result; +} + + +void clause_LiteralDelete(LITERAL Literal) +/********************************************************* + INPUT: A literal, which has an unshared Atom. For Shared + literals clause_LiteralDeleteFromSharing(Lit) is + available. + RETURNS: Nothing. + MEMORY: The Atom of 'Literal' is deleted and its memory + is freed as well as the LITERAL_NODE. +**********************************************************/ +{ +#ifdef CHECK + if (!clause_LiteralIsLiteral(Literal)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralDelete:"); + misc_ErrorReport("\n Illegal input. Input not a literal."); + misc_FinishErrorReport(); + } +#endif + + term_Delete(clause_LiteralSignedAtom(Literal)); + + clause_LiteralFree(Literal); +} + + +void clause_LiteralInsertIntoSharing(LITERAL Lit, SHARED_INDEX ShIndex) +/********************************************************** + INPUT: A Literal with an unshared Atom and an Index. + RETURNS: The literal with a shared Atom inserted into the + 'Index'. + MEMORY: Allocates TERM_NODE memory needed to insert 'Lit' + into the sharing and frees the memory of the + unshared Atom. +***********************************************************/ +{ + + TERM Atom; + +#ifdef CHECK + if (!clause_LiteralIsLiteral(Lit)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralInsertIntoSharing:"); + misc_ErrorReport("\n Illegal literal input."); + misc_FinishErrorReport(); + } +#endif + + Atom = clause_LiteralAtom(Lit); + + clause_LiteralSetAtom(Lit, sharing_Insert(Lit, Atom, ShIndex)); + + term_Delete(Atom); +} + + +void clause_LiteralDeleteFromSharing(LITERAL Lit, SHARED_INDEX ShIndex) +/********************************************************** + INPUT: A Literal and an 'Index'. + RETURNS: Nothing. + MEMORY: Deletes 'Lit' from Sharing, frees no more used + TERM memory and frees the LITERAL_NODE. +********************************************************/ +{ + + TERM Atom; + +#ifdef CHECK + if (!clause_LiteralIsLiteral(Lit)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralDeleteFromSharing:"); + misc_ErrorReport("\n Illegal literal input."); + misc_FinishErrorReport(); + } +#endif + + Atom = clause_LiteralAtom(Lit); + + if (clause_LiteralIsNegative(Lit)) { + list_Free(term_ArgumentList(clause_LiteralSignedAtom(Lit))); + term_Free(clause_LiteralSignedAtom(Lit)); + } + + sharing_Delete(Lit, Atom, ShIndex); + + clause_LiteralFree(Lit); + +} + + +static LIST clause_CopyLitInterval(CLAUSE Clause, int Start, int End) +/************************************************************** + INPUT: A clause and two integers representing + literal indices. + RETURNS: Copies of all literals in <Clause> with index i and + in the interval [Start:End] are prepended to <List>. + MEMORY: All atoms are copied. +***************************************************************/ +{ + TERM Atom; + LIST List; + + List = list_Nil(); + + for ( ; Start <= End; Start++) { + Atom = term_Copy(clause_GetLiteralAtom(Clause, Start)); + List = list_Cons(Atom, List); + } + + return List; +} + + +static LIST clause_CopyLitIntervalExcept(CLAUSE Clause, int Start, int End, + int i) +/************************************************************** + INPUT: A clause and three integers representing + literal indeces. + RETURNS: A list of atoms from literals within the interval + [Start:End] except the literal at index <i>. + MEMORY: All atoms are copied. +***************************************************************/ +{ + TERM Atom; + LIST Result; + + Result = list_Nil(); + for ( ; End >= Start; End--) + if (End != i) { + Atom = term_Copy(clause_GetLiteralAtom(Clause, End)); + Result = list_Cons(Atom, Result); + } + return Result; +} + + +LIST clause_CopyConstraint(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: The list of copied constraint literals from <Clause>. +***************************************************************/ +{ + return clause_CopyLitInterval(Clause, + clause_FirstConstraintLitIndex(Clause), + clause_LastConstraintLitIndex(Clause)); +} + + +LIST clause_CopyAntecedentExcept(CLAUSE Clause, int i) +/************************************************************** + INPUT: A clause. + RETURNS: A list containing copies of all antecedent literals + except <i>. +***************************************************************/ +{ + return clause_CopyLitIntervalExcept(Clause, + clause_FirstAntecedentLitIndex(Clause), + clause_LastAntecedentLitIndex(Clause), + i); +} + +LIST clause_CopySuccedent(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: The list of copied succedent literals from <Clause>. +***************************************************************/ +{ + return clause_CopyLitInterval(Clause, + clause_FirstSuccedentLitIndex(Clause), + clause_LastSuccedentLitIndex(Clause)); +} + + +LIST clause_CopySuccedentExcept(CLAUSE Clause, int i) +/************************************************************** + INPUT: A clause. + RETURNS: A list containing copies of all succedent literals + except <i>. +***************************************************************/ +{ + return clause_CopyLitIntervalExcept(Clause, + clause_FirstSuccedentLitIndex(Clause), + clause_LastSuccedentLitIndex(Clause), + i); +} + + +/**************************************************************/ +/* Specials */ +/**************************************************************/ + +BOOL clause_IsUnorderedClause(CLAUSE Clause) +/********************************************************* + INPUT: A clause. + RETURNS: TRUE, if the invariants concerning splitting etc. hold + Invariants concerning maximality restrictions are not tested. +**********************************************************/ +{ + return ((Clause != NULL) && + clause_CheckSplitLevel(Clause) && + (clause_IsEmptyClause(Clause) || + /* Check the first literal as a "random" sample */ + clause_LiteralIsLiteral(clause_GetLiteral(Clause,clause_FirstLitIndex()))) && + (clause_SplitLevel(Clause) == 0 || Clause->splitfield_length>0) && + clause_DependsOnSplitLevel(Clause,clause_SplitLevel(Clause))); +} + + +BOOL clause_IsClause(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence) +/********************************************************* + INPUT: A clause, a flag store and a precedence. + RETURNS: TRUE, if literals are correctly ordered and the + invariants concerning splitting etc. hold +**********************************************************/ +{ + int i; + LITERAL ActLit; + + if (!clause_IsUnorderedClause(Clause)) + return FALSE; + + for (i=clause_FirstAntecedentLitIndex(Clause);i<=clause_LastSuccedentLitIndex(Clause);i++) { + ActLit = clause_GetLiteral(Clause,i); + if (fol_IsEquality(clause_LiteralSignedAtom(ActLit))) { + ord_RESULT HelpRes; + + HelpRes = + ord_Compare(term_FirstArgument(clause_LiteralSignedAtom(ActLit)), + term_SecondArgument(clause_LiteralSignedAtom(ActLit)), + FlagStore, Precedence); + + if (ord_IsSmallerThan(HelpRes)) + return FALSE; + } + } + + return TRUE; +} + + +BOOL clause_ContainsPositiveEquations(CLAUSE Clause) +/********************************************************* + INPUT: A clause. + RETURNS: TRUE, if the clause contains a positive equality literal. +**********************************************************/ +{ + int i; + + for (i = clause_FirstSuccedentLitIndex(Clause); + i < clause_Length(Clause); + i++) + if (clause_LiteralIsEquality(clause_GetLiteral(Clause, i))) + return TRUE; + + return FALSE; +} + + +BOOL clause_ContainsNegativeEquations(CLAUSE Clause) +/********************************************************* + INPUT: A clause. + RETURNS: TRUE, if the clause contains a positive equality literal. +**********************************************************/ +{ + int i; + + for (i = clause_FirstAntecedentLitIndex(Clause); + i < clause_FirstSuccedentLitIndex(Clause); + i++) + if (clause_LiteralIsEquality(clause_GetLiteral(Clause, i))) + return TRUE; + + return FALSE; +} + + +int clause_ContainsFolAtom(CLAUSE Clause, BOOL *Prop, BOOL *Grd, BOOL *Monadic, + BOOL *NonMonadic) +/********************************************************* + INPUT: A clause. + RETURNS: The number of boolean variables changed. + If <*Prop> is FALSE and the clause contains a propositional + variable, it is changed to TRUE. + If <*Grd> is FALSE and the clause contains a non-propositional + ground atom, it is changed to TRUE. + If <*Monadic> is FALSE and the clause contains a monadic atom, + it is changed to TRUE. + If <*NonMonadic> is FALSE and the clause contains an at least + 2-place non-equality atom, it is changed to TRUE. +**********************************************************/ +{ + int i,Result,Arity; + BOOL Ground; + + Result = 0; + i = clause_FirstLitIndex(); + + while (Result < 4 && + i < clause_Length(Clause) && + (!(*Prop) || !(*Monadic) || !(*NonMonadic))) { + Arity = symbol_Arity(term_TopSymbol(clause_GetLiteralAtom(Clause,i))); + Ground = term_IsGround(clause_GetLiteralAtom(Clause,i)); + if (!(*Prop) && Arity == 0) { + Result++; + *Prop = TRUE; + } + if (!(*Grd) && Arity > 0 && Ground && + !fol_IsEquality(clause_GetLiteralAtom(Clause,i))) { + Result++; + *Grd = TRUE; + } + if (!(*Monadic) && Arity == 1 && !Ground) { + Result++; + *Monadic = TRUE; + } + if (!(*NonMonadic) && Arity > 1 && !Ground && + !fol_IsEquality(clause_GetLiteralAtom(Clause,i))) { + Result++; + *NonMonadic = TRUE; + } + i++; + } + return Result; +} + + +BOOL clause_ContainsVariables(CLAUSE Clause) +/********************************************************* + INPUT: A clause. + RETURNS: TRUE, if the clause contains at least one variable +**********************************************************/ +{ + int i; + TERM Term; + + for (i = clause_FirstLitIndex(); i < clause_Length(Clause); i++) { + Term = clause_GetLiteralAtom(Clause,i); + if (term_NumberOfVarOccs(Term)>0) + return TRUE; + } + + return FALSE; +} + + +void clause_ContainsSortRestriction(CLAUSE Clause, BOOL *Sortres, BOOL *USortres) +/********************************************************* + INPUT: A clause. + RETURNS: TRUE, if the clause contains a negative monadic atom with + a variable argument +**********************************************************/ +{ + int i; + TERM Term; + + for (i = clause_FirstLitIndex(); + i <= clause_LastAntecedentLitIndex(Clause) && (!*Sortres || !*USortres); + i++) { + Term = clause_GetLiteralAtom(Clause,i); + if (symbol_IsBaseSort(term_TopSymbol(Term))) { + *USortres = TRUE; + if (symbol_IsVariable(term_TopSymbol(term_FirstArgument(Term)))) + *Sortres = TRUE; + } + } +} + +BOOL clause_ContainsFunctions(CLAUSE Clause) +/********************************************************* + INPUT: A clause. + RETURNS: TRUE, if the clause contains at least one function symbol +**********************************************************/ +{ + int i; + TERM Term; + + for (i = clause_FirstLitIndex(); i < clause_Length(Clause); i++) { + Term = clause_GetLiteralAtom(Clause,i); + if (term_ContainsFunctions(Term)) + return TRUE; + } + + return FALSE; +} + +BOOL clause_ContainsSymbol(CLAUSE Clause, SYMBOL Symbol) +/********************************************************* + INPUT: A clause and a symbol. + RETURNS: TRUE, if the clause contains the symbol +**********************************************************/ +{ + int i; + + for (i = clause_FirstLitIndex(); i < clause_Length(Clause); i++) + if (term_ContainsSymbol(clause_GetLiteralAtom(Clause,i), Symbol)) + return TRUE; + return FALSE; +} + +NAT clause_NumberOfSymbolOccurrences(CLAUSE Clause, SYMBOL Symbol) +/********************************************************* + INPUT: A clause and a symbol. + RETURNS: the number of occurrences of <Symbol> in <Clause> +**********************************************************/ +{ + int i; + NAT Result; + + Result = 0; + + for (i = clause_FirstLitIndex(); i < clause_Length(Clause); i++) + Result += term_NumberOfSymbolOccurrences(clause_GetLiteralAtom(Clause,i), Symbol); + + return Result; +} + +BOOL clause_ImpliesFiniteDomain(CLAUSE Clause) +/********************************************************* + INPUT: A clause. + RETURNS: TRUE, if the clause consists of a positive disjunction + of equations, where each equation is of the form "x=t" for + some variable "x" and ground term "t" +**********************************************************/ +{ + int i; + TERM Term; + + if (clause_FirstLitIndex() != clause_FirstSuccedentLitIndex(Clause)) + return FALSE; + + for (i = clause_FirstLitIndex(); i < clause_Length(Clause); i++) { + Term = clause_GetLiteralTerm(Clause,i); + if (!symbol_Equal(term_TopSymbol(Term),fol_Equality()) || + (!symbol_IsVariable(term_TopSymbol(term_FirstArgument(Term))) && + !symbol_IsVariable(term_TopSymbol(term_SecondArgument(Term)))) || + (symbol_IsVariable(term_TopSymbol(term_FirstArgument(Term))) && + !term_IsGround(term_SecondArgument(Term))) || + (symbol_IsVariable(term_TopSymbol(term_SecondArgument(Term))) && + !term_IsGround(term_FirstArgument(Term)))) + return FALSE; + } + + return TRUE; +} + +BOOL clause_ImpliesNonTrivialDomain(CLAUSE Clause) +/********************************************************* + INPUT: A clause. + RETURNS: TRUE, if the clause consists of a negative equation + with two syntactically different arguments +**********************************************************/ +{ + if (clause_Length(Clause) == 1 && + !clause_HasEmptyAntecedent(Clause) && + clause_LiteralIsEquality(clause_FirstAntecedentLit(Clause)) && + !term_Equal(term_FirstArgument(clause_LiteralAtom(clause_FirstAntecedentLit(Clause))), + term_SecondArgument(clause_LiteralAtom(clause_FirstAntecedentLit(Clause))))) + return TRUE; + + return FALSE; +} + +LIST clause_FiniteMonadicPredicates(LIST Clauses) +/********************************************************* + INPUT: A list of clauses. + RETURNS: A list of all predicate symbols that are guaranteed + to have a finite extension in any minimal Herbrand model. + These predicates must only positively occur + in unit clauses and must have a ground term argument. +**********************************************************/ +{ + LIST Result, NonFinite, Scan; + CLAUSE Clause; + int i, n; + SYMBOL Pred; + + Result = list_Nil(); + NonFinite = list_Nil(); + + for (Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Clause = (CLAUSE)list_Car(Scan); + n = clause_Length(Clause); + for (i=clause_FirstSuccedentLitIndex(Clause);i<n;i++) { + Pred = term_TopSymbol(clause_GetLiteralAtom(Clause,i)); + if (symbol_Arity(Pred) == 1 && + !list_PointerMember(NonFinite, (POINTER)Pred)) { + if (term_NumberOfVarOccs(clause_GetLiteralAtom(Clause,i)) > 0 || + n > 1) { + NonFinite = list_Cons((POINTER)Pred, NonFinite); + Result = list_PointerDeleteElement(Result, (POINTER)Pred); + } + else { + if (!list_PointerMember(Result, (POINTER)Pred)) + Result = list_Cons((POINTER)Pred, Result); + } + } + } + } + list_Delete(NonFinite); + + Result = list_PointerDeleteElement(Result, (POINTER)fol_Equality()); + + return Result; +} + +NAT clause_NumberOfVarOccs(CLAUSE Clause) +/************************************************************** + INPUT: A Clause. + RETURNS: The number of variable occurrences in the clause. +***************************************************************/ +{ + int i,n; + NAT Result; + + Result = 0; + n = clause_Length(Clause); + + for (i = clause_FirstLitIndex(); i < n; i++) + Result += term_NumberOfVarOccs(clause_GetLiteralTerm(Clause,i)); + + return Result; +} + + +NAT clause_ComputeWeight(CLAUSE Clause, FLAGSTORE Flags) +/************************************************************** + INPUT: A clause and a flag store. + RETURNS: The Weight of the literals in the clause, + up to now the number of variable symbols plus + twice the number of signature symbols. + EFFECT: The weight of the literals is updated, but not the + weight of the clause! +***************************************************************/ +{ + int i, n; + NAT Weight; + LITERAL Lit; + + Weight = 0; + n = clause_Length(Clause); + + for (i = clause_FirstLitIndex(); i < n; i++) { + Lit = clause_GetLiteral(Clause, i); + clause_UpdateLiteralWeight(Lit, Flags); + Weight += clause_LiteralWeight(Lit); + } + return Weight; +} + + +NAT clause_ComputeTermDepth(CLAUSE Clause) +/************************************************************** + INPUT: A Clause. + RETURNS: Maximal depth of a literal in <Clause>. +***************************************************************/ +{ + int i,n; + NAT Depth,Help; + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_ComputeTermDepth:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + Depth = 0; + n = clause_Length(Clause); + + for (i = clause_FirstLitIndex();i < n;i++) { + Help = term_Depth(clause_GetLiteralAtom(Clause,i)); + if (Help > Depth) + Depth = Help; + } + return Depth; +} + +NAT clause_MaxTermDepthClauseList(LIST Clauses) +/************************************************************** + INPUT: A list of clauses. + RETURNS: Maximal depth of a clause in <Clauses>. +***************************************************************/ +{ + NAT Depth,Help; + + Depth = 0; + + while (!list_Empty(Clauses)) { + Help = clause_ComputeTermDepth(list_Car(Clauses)); + if (Help > Depth) + Depth = Help; + Clauses = list_Cdr(Clauses); + } + + return Depth; +} + + +NAT clause_ComputeSize(CLAUSE Clause) +/************************************************************** + INPUT: A Clause. + RETURNS: The Size of the literals in the clause, + up to now the number of symbols. +***************************************************************/ +{ + int i,n; + NAT Size; + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_ComputeSize:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + Size = 0; + n = clause_Length(Clause); + + for (i = clause_FirstLitIndex();i < n;i++) + Size += term_ComputeSize(clause_GetLiteralTerm(Clause,i)); + + return Size; +} + + +BOOL clause_WeightCorrect(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) +/********************************************************* + INPUT: A clause, a flag store and a precedence. + RETURNS: TRUE iff the weight fields of the clause and its + literals are correct. +**********************************************************/ +{ + int i, n; + NAT Weight, Help; + LITERAL Lit; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_WeightCorrect:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + Weight = 0; + n = clause_Length(Clause); + + for (i = clause_FirstLitIndex(); i < n; i++) { + Lit = clause_GetLiteral(Clause, i); + Help = clause_LiteralComputeWeight(Lit, Flags); + if (Help != clause_LiteralWeight(Lit)) + return FALSE; + Weight += Help; + } + + return (clause_Weight(Clause) == Weight); +} + + +LIST clause_InsertWeighed(CLAUSE Clause, LIST UsList, FLAGSTORE Flags, + PRECEDENCE Precedence) +/********************************************************* + INPUT: A clause, a list to insert the clause into, + a flag store and a precedence. + RETURNS: The list where the clause is inserted wrt its + weight (Weight(Car(list)) <= Weight(Car(Cdr(list)))). + MEMORY: A new listnode is allocated. +**********************************************************/ +{ + LIST Scan; + NAT Weight; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_InsertWeighted:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + Weight = clause_Weight(Clause); + + Scan = UsList; + + if (list_Empty(Scan) || + (clause_Weight(list_Car(Scan)) > Weight)) { + return list_Cons(Clause, Scan); + + } else { + while (!list_Empty(list_Cdr(Scan)) && + (clause_Weight(list_Car(list_Cdr(Scan))) <= Weight)) { + Scan = list_Cdr(Scan); + } + list_Rplacd(Scan, list_Cons(Clause, list_Cdr(Scan))); + return UsList; + } +} + + +LIST clause_ListSortWeighed(LIST Clauses) +/********************************************************* + INPUT: A list of clauses. + RETURNS: The clause list sorted with respect to the weight + of clauses, minimal weight first. + EFFECT: The original list is destructively changed! + This function doesn't sort stable! + The function uses bucket sort for clauses with weight + smaller than clause_MAXWEIGHT, and the usual list sort + function for clauses with weight >= clause_MAXWEIGHT. + This implies the function uses time O(n-c + c*log c), + where n is the length of the list and c is the number + of clauses with weight >= clause_MAXWEIGHT. + For c=0 you get time O(n), for c=n you get time (n*log n). +**********************************************************/ +{ + int weight; + LIST Scan; + + for (Scan=Clauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) { + weight = clause_Weight(list_Car(Scan)); + if (weight < clause_MAXWEIGHT) + clause_SORT[weight] = list_Cons(list_Car(Scan),clause_SORT[weight]); + else + clause_SORT[clause_MAXWEIGHT] = list_Cons(list_Car(Scan),clause_SORT[clause_MAXWEIGHT]); + } + Scan = list_NumberSort(clause_SORT[clause_MAXWEIGHT], + (NAT (*)(POINTER)) clause_Weight); + clause_SORT[clause_MAXWEIGHT] = list_Nil(); + for (weight = clause_MAXWEIGHT-1; weight >= 0; weight--) { + Scan = list_Nconc(clause_SORT[weight],Scan); + clause_SORT[weight] = list_Nil(); + } + list_Delete(Clauses); + return Scan; +} + + +LITERAL clause_LiteralCopy(LITERAL Literal) +/********************************************************* + INPUT: A literal. + RETURNS: An unshared copy of the literal, where the owning + clause-slot is set to NULL. + MEMORY: Memory for a new LITERAL_NODE and all its TERMs + subterms is allocated. +**********************************************************/ +{ + + LITERAL Result; + +#ifdef CHECK + if (!clause_LiteralIsLiteral(Literal)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralCopy:"); + misc_ErrorReport("\n Illegal input. Input not a literal."); + misc_FinishErrorReport(); + } +#endif + + Result = (LITERAL)memory_Malloc(sizeof(LITERAL_NODE)); + + Result->atomWithSign = term_Copy(clause_LiteralSignedAtom(Literal)); + Result->oriented = clause_LiteralIsOrientedEquality(Literal); + + Result->maxLit = Literal->maxLit; + Result->weight = Literal->weight; + Result->owningClause = (POINTER)NULL; + + return Result; +} + + +CLAUSE clause_Copy(CLAUSE Clause) +/********************************************************* + INPUT: A Clause. + RETURNS: An unshared copy of the Clause. + MEMORY: Memory for a new CLAUSE_NODE, LITERAL_NODE and + all its TERMs subterms is allocated. +**********************************************************/ +{ + + CLAUSE Result; + int i,c,a,s,l; + + Result = (CLAUSE)memory_Malloc(sizeof(CLAUSE_NODE)); + + Result->clausenumber = clause_Number(Clause); + Result->maxVar = clause_MaxVar(Clause); + Result->flags = Clause->flags; + clause_InitSplitData(Result); + Result->validlevel = clause_SplitLevel(Clause); + clause_SetSplitField(Result, Clause->splitfield, Clause->splitfield_length); + Result->depth = clause_Depth(Clause); + Result->weight = Clause->weight; + Result->parentCls = list_Copy(clause_ParentClauses(Clause)); + Result->parentLits = list_Copy(clause_ParentLiterals(Clause)); + Result->origin = clause_Origin(Clause); + + Result->c = (c = clause_NumOfConsLits(Clause)); + Result->a = (a = clause_NumOfAnteLits(Clause)); + Result->s = (s = clause_NumOfSuccLits(Clause)); + + l = c + a + s; + if (l != 0) + Result->literals = (LITERAL *)memory_Malloc(l * sizeof(LITERAL)); + + for (i = 0; i < l; i++) { + clause_SetLiteral(Result, i, + clause_LiteralCopy(clause_GetLiteral(Clause, i))); + clause_LiteralSetOwningClause((Result->literals[i]), Result); + } + + return Result; +} + + +SYMBOL clause_LiteralMaxVar(LITERAL Literal) +/********************************************************* + INPUT: A literal. + RETURNS: The maximal symbol of the literals variables, + if the literal is ground, symbol_GetInitialStandardVarCounter(). +**********************************************************/ +{ + + TERM Term; + int Bottom; + SYMBOL MaxSym,Help; + +#ifdef CHECK + if (!clause_LiteralIsLiteral(Literal)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralMaxVar:"); + misc_ErrorReport("\n Illegal input. Input not a literal."); + misc_FinishErrorReport(); + } +#endif + + Bottom = stack_Bottom(); + MaxSym = symbol_GetInitialStandardVarCounter(); + Term = clause_LiteralAtom(Literal); + + do { + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + else + if (term_IsVariable(Term)) + MaxSym = ((MaxSym < (Help = term_TopSymbol(Term))) ? + Help : MaxSym); + while (!stack_Empty(Bottom) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Bottom)) { + Term = (TERM) list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Bottom)); + + return MaxSym; +} + + +SYMBOL clause_AtomMaxVar(TERM Term) +/********************************************************* + INPUT: A term. + RETURNS: The maximal symbol of the lcontained variables, + if <Term> is ground, symbol_GetInitialStandardVarCounter(). +**********************************************************/ +{ + int Bottom; + SYMBOL VarSym,Help; + + Bottom = stack_Bottom(); + VarSym = symbol_GetInitialStandardVarCounter(); + + do { + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + else + if (term_IsVariable(Term)) + VarSym = ((VarSym < (Help = term_TopSymbol(Term))) ? + Help : VarSym); + while (!stack_Empty(Bottom) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Bottom)) { + Term = (TERM)list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Bottom)); + + return VarSym; +} + + +void clause_SetMaxLitFlags(CLAUSE Clause, FLAGSTORE FlagStore, + PRECEDENCE Precedence) +/********************************************************** + INPUT: A clause, a flag store and a precedence. + RETURNS: Nothing. + EFFECT: Sets the maxLit-flag for maximal literals. +***********************************************************/ +{ + int i,j,n,fa; + LITERAL ActLit,CompareLit; + BOOL Result, Twin; + ord_RESULT HelpRes; + + n = clause_Length(Clause); + fa = clause_FirstAntecedentLitIndex(Clause); + clause_RemoveFlag(Clause,CLAUSESELECT); + for (i = clause_FirstLitIndex(); i < n; i++) + clause_LiteralFlagReset(clause_GetLiteral(Clause, i)); + if (term_StampOverflow(clause_STAMPID)) + for (i = clause_FirstLitIndex(); i < n; i++) + term_ResetTermStamp(clause_LiteralSignedAtom(clause_GetLiteral(Clause, i))); + term_StartStamp(); + + /*printf("\n Start: "); clause_Print(Clause);*/ + + for (i = fa; i < n; i++) { + ActLit = clause_GetLiteral(Clause, i); + if (!term_HasTermStamp(clause_LiteralSignedAtom(ActLit))) { + Result = TRUE; + Twin = FALSE; + for (j = fa; j < n && Result; j++) + if (i != j) { + CompareLit = clause_GetLiteral(Clause, j); + HelpRes = ord_LiteralCompare(clause_LiteralSignedAtom(ActLit), + clause_LiteralIsOrientedEquality(ActLit), + clause_LiteralSignedAtom(CompareLit), + clause_LiteralIsOrientedEquality(CompareLit), + FALSE, FlagStore, Precedence); + + /*printf("\n\tWe compare: "); + fol_PrintDFG(clause_LiteralAtom(ActLit)); + putchar(' '); + fol_PrintDFG(clause_LiteralAtom(CompareLit)); + printf(" Result: "); ord_Print(HelpRes);*/ + + if (ord_IsEqual(HelpRes)) + Twin = TRUE; + if (ord_IsSmallerThan(HelpRes)) + Result = FALSE; + if (ord_IsGreaterThan(HelpRes)) + term_SetTermStamp(clause_LiteralSignedAtom(CompareLit)); + } + if (Result) { + clause_LiteralSetFlag(ActLit, MAXIMAL); + if (!Twin) + clause_LiteralSetFlag(ActLit, STRICTMAXIMAL); + } + } + } + term_StopStamp(); + /*printf("\n End: "); clause_Print(Clause);*/ +} + + +SYMBOL clause_SearchMaxVar(CLAUSE Clause) +/********************************************************** + INPUT: A clause. + RETURNS: The maximal symbol of the clauses variables. + If the clause is ground, symbol_GetInitialStandardVarCounter(). +***********************************************************/ +{ + int i, n; + SYMBOL Help, MaxSym; + + n = clause_Length(Clause); + + MaxSym = symbol_GetInitialStandardVarCounter(); + + for (i = 0; i < n; i++) { + Help = clause_LiteralMaxVar(clause_GetLiteral(Clause, i)); + if (Help > MaxSym) + MaxSym = Help; + } + return MaxSym; +} + + +void clause_RenameVarsBiggerThan(CLAUSE Clause, SYMBOL MinVar) +/********************************************************** + INPUT: A clause and a variable symbol. + RETURNS: The clause with variables renamed in a way, that + all vars are (excl.) bigger than MinVar. +***********************************************************/ +{ + int i,n; + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_RenameVarsBiggerThan:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (MinVar != symbol_GetInitialStandardVarCounter()) { + n = clause_Length(Clause); + + term_StartMaxRenaming(MinVar); + + for (i = clause_FirstLitIndex(); i < n; i++) + term_Rename(clause_GetLiteralTerm(Clause, i)); + } +} + +void clause_Normalize(CLAUSE Clause) +/********************************************************** + INPUT: A clause. + RETURNS: The term with normalized Variables, DESTRUCTIVE + on the variable subterms' topsymbols. +***********************************************************/ +{ + int i,n; + + n = clause_Length(Clause); + + term_StartMinRenaming(); + + for (i = clause_FirstLitIndex(); i < n; i++) + term_Rename(clause_GetLiteralTerm(Clause, i)); +} + + +void clause_SubstApply(SUBST Subst, CLAUSE Clause) +/********************************************************** + INPUT: A clause. + RETURNS: Nothing. + EFFECTS: Applies the substitution to the clause. +***********************************************************/ +{ + int i,n; + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_SubstApply:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + n = clause_Length(Clause); + + for (i=clause_FirstLitIndex(); i<n; i++) + clause_LiteralSetAtom(clause_GetLiteral(Clause, i), + subst_Apply(Subst,clause_GetLiteralAtom(Clause,i))); +} + + +void clause_ReplaceVariable(CLAUSE Clause, SYMBOL Var, TERM Term) +/********************************************************** + INPUT: A clause, a variable symbol, and a term. + RETURNS: Nothing. + EFFECTS: All occurences of the variable <Var> in <Clause> + are replaced by copies if <Term>. + CAUTION: The maximum variable of the clause is not updated! +***********************************************************/ +{ + int i, li; + +#ifdef CHECK + if (!symbol_IsVariable(Var)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_ReplaceVariable: symbol is not a variable"); + misc_FinishErrorReport(); + } +#endif + + li = clause_LastLitIndex(Clause); + for (i = clause_FirstLitIndex(); i <= li; i++) + term_ReplaceVariable(clause_GetLiteralAtom(Clause,i), Var, Term); +} + + +void clause_UpdateMaxVar(CLAUSE Clause) +/********************************************************** + INPUT: A clause. + RETURNS: Nothing. + EFFECTS: Actualizes the MaxVar slot wrt the actual literals. +***********************************************************/ +{ + clause_SetMaxVar(Clause, clause_SearchMaxVar(Clause)); +} + + + +void clause_OrientEqualities(CLAUSE Clause, FLAGSTORE FlagStore, + PRECEDENCE Precedence) +/********************************************************** + INPUT: An unshared clause, a flag store and a precedence. + RETURNS: Nothing. + EFFECTS: Reorders the arguments of equality literals + wrt. the ordering. Thus first arguments aren't smaller + after the application. +***********************************************************/ +{ + int i,length; + LITERAL EqLit; + ord_RESULT HelpRes; + + /*printf("\n Clause: ");clause_Print(Clause);*/ + + length = clause_Length(Clause); + + for (i = clause_FirstLitIndex(); i < length; i++) { + EqLit = clause_GetLiteral(Clause, i); + + if (clause_LiteralIsEquality(EqLit)) { + HelpRes = ord_Compare(term_FirstArgument(clause_LiteralAtom(EqLit)), + term_SecondArgument(clause_LiteralAtom(EqLit)), + FlagStore, Precedence); + + /*printf("\n\tWe compare: "); + fol_PrintDFG(term_FirstArgument(clause_LiteralAtom(EqLit))); + putchar(' '); + fol_PrintDFG(term_SecondArgument(clause_LiteralAtom(EqLit))); + printf("\nResult: "); ord_Print(HelpRes);*/ + + switch(HelpRes) { + + case ord_SMALLER_THAN: + /* printf("\nSwapping: "); + term_Print(clause_LiteralAtom(EqLit)); DBG */ + term_EqualitySwap(clause_LiteralAtom(EqLit)); + clause_LiteralSetOrientedEquality(EqLit); + /* Swapped = TRUE; */ + break; + case ord_GREATER_THAN: + clause_LiteralSetOrientedEquality(EqLit); + break; + default: + clause_LiteralSetNoOrientedEquality(EqLit); + break; + } + } + else + clause_LiteralSetNoOrientedEquality(EqLit); + } +} + + +void clause_InsertFlatIntoIndex(CLAUSE Clause, st_INDEX Index) +/********************************************************** + INPUT: An unshared clause and an index. + EFFECT: The atoms of <Clause> are inserted into the index. + A link from the atom to its literal via the supertermlist + is established. +***********************************************************/ +{ + int i,n; + LITERAL Lit; + TERM Atom ; + + n = clause_Length(Clause); + + for (i=clause_FirstLitIndex();i<n;i++) { + Lit = clause_GetLiteral(Clause,i); + Atom = clause_LiteralAtom(Lit); + term_RplacSupertermList(Atom, list_List(Lit)); + st_EntryCreate(Index, Atom, Atom, cont_LeftContext()); + } +} + +void clause_DeleteFlatFromIndex(CLAUSE Clause, st_INDEX Index) +/********************************************************** + INPUT: An unshared clause and an index. + EFFECT: The clause is deleted from the index and deleted itself. +***********************************************************/ +{ + int i,n; + LITERAL Lit; + TERM Atom ; + + n = clause_Length(Clause); + + for (i=clause_FirstLitIndex();i<n;i++) { + Lit = clause_GetLiteral(Clause,i); + Atom = clause_LiteralAtom(Lit); + list_Delete(term_SupertermList(Atom)); + term_RplacSupertermList(Atom, list_Nil()); + st_EntryDelete(Index, Atom, Atom, cont_LeftContext()); + } + clause_Delete(Clause); +} + + +void clause_DeleteClauseListFlatFromIndex(LIST Clauses, st_INDEX Index) +/********************************************************** + INPUT: An list of unshared clause and an index. + EFFECT: The clauses are deleted from the index and deleted itself. + The list is deleted. +***********************************************************/ +{ + LIST Scan; + + for (Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) + clause_DeleteFlatFromIndex(list_Car(Scan), Index); + + list_Delete(Clauses); +} + + +/******************************************************************/ +/* Some special functions used by hyper inference/reduction rules */ +/******************************************************************/ + +static void clause_VarToSizeMap(SUBST Subst, NAT* Map, NAT MaxIndex) +/************************************************************** + INPUT: A substitution, an array <Map> of size <MaxIndex>+1. + RETURNS: Nothing. + EFFECT: The index i within the array corresponds to the index + of a variable x_i. For each variable x_i, 0<=i<=MaxIndex + the size of its substitution term is calculated + and written to Map[i]. +***************************************************************/ +{ + NAT *Scan; + +#ifdef CHECK + if (subst_Empty(Subst) || Map == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_VarToSizeMap: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + /* Initialization */ + for (Scan = Map + MaxIndex; Scan >= Map; Scan--) + *Scan = 1; + /* Compute the size of substitution terms */ + for ( ; !subst_Empty(Subst); Subst = subst_Next(Subst)) + Map[subst_Dom(Subst)] = term_ComputeSize(subst_Cod(Subst)); +} + + +static NAT clause_ComputeTermSize(TERM Term, NAT* VarMap) +/************************************************************** + INPUT: A term and a an array of NATs. + RETURNS: The number of symbols in the term. + EFFECT: This function calculates the number of symbols in <Term> + with respect to some substitution s. + A naive way to do this is to apply the substitution + to a copy of the term, and to count the number of symbols + in the copied term. + We use a more sophisticated algorithm, that first stores + the size of every variable's substitution term in <VarMap>. + We then 'scan' the term and for a variable occurrence x_i + we simply add the corresponding value VarMap[i] to the result. + This way we avoid copying the term and the substitution terms, + which is especially useful if we reuse the VarMap several times. +***************************************************************/ +{ + NAT Stack, Size; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_ComputeTermSize: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Size = 0; + Stack = stack_Bottom(); + do { + if (VarMap!=NULL && symbol_IsVariable(term_TopSymbol(Term))) + Size += VarMap[symbol_VarIndex(term_TopSymbol(Term))]; + else { + Size++; + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + } + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + + if (!stack_Empty(Stack)) { + Term = list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); + + return Size; +} + + +LIST clause_MoveBestLiteralToFront(LIST Literals, SUBST Subst, SYMBOL MaxVar, + BOOL (*Better)(LITERAL, NAT, LITERAL, NAT)) +/************************************************************** + INPUT: A list of literals, a substitution, the maximum variable + from the domain of the substitution, and a comparison + function. The function <Better> will be called with two + literals L1 and L2 and two number S1 and S2, where Si is + the size of the atom of Li with respect to variable bindings + in <Subst>. + RETURNS: The same list. + EFFECT: This function moves the first literal L to the front of the + list, so that no other literal L' is better than L with respect + to the function <Better>. + The function exchanges only the literals, the order of list + items within the list is not changed. +***************************************************************/ +{ + NAT *Map, MapSize, BestSize, Size; + LIST Best, Scan; + +#ifdef CHECK + if (!list_IsSetOfPointers(Literals)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_MoveBestLiteralToFront: List contains duplicates"); + misc_FinishErrorReport(); + } +#endif + + if (list_Empty(Literals) || list_Empty(list_Cdr(Literals))) + /* < 2 list items, so nothing to do */ + return Literals; + + Map = NULL; + MapSize = 0; + + if (!subst_Empty(Subst)) { + MapSize = symbol_VarIndex(MaxVar) + 1; + Map = memory_Malloc(sizeof(NAT)*MapSize); + clause_VarToSizeMap(Subst, Map, MapSize-1); + } + Best = Literals; /* Remember list item, not literal itself */ + BestSize = clause_ComputeTermSize(clause_LiteralAtom(list_Car(Best)), Map); + for (Scan = list_Cdr(Literals); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Size = clause_ComputeTermSize(clause_LiteralAtom(list_Car(Scan)), Map); + if (Better(list_Car(Scan), Size, list_Car(Best), BestSize)) { + /* Actual literal is better than the best encountered so far */ + BestSize = Size; + Best = Scan; + } + } + if (Best != Literals) { + /* Move best literal to the front. We just exchange the literals. */ + LITERAL h = list_Car(Literals); + list_Rplaca(Literals, list_Car(Best)); + list_Rplaca(Best, h); + } + /* cleanup */ + if (Map != NULL) + memory_Free(Map, sizeof(NAT)*MapSize); + + return Literals; +} + + +/**************************************************************/ +/* Literal Output Functions */ +/**************************************************************/ + +void clause_LiteralPrint(LITERAL Literal) +/************************************************************** + INPUT: A Literal. + RETURNS: Nothing. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_LiteralIsLiteral(Literal)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralPrint:"); + misc_ErrorReport("\n Illegal input. Input not a literal."); + misc_FinishErrorReport(); + } +#endif + + term_PrintPrefix(clause_LiteralSignedAtom(Literal)); +} + + +void clause_LiteralListPrint(LIST LitList) +/************************************************************** + INPUT: A list of literals. + RETURNS: Nothing. + SUMMARY: Prints the literals to stdout. +***************************************************************/ +{ + while (!(list_Empty(LitList))) { + clause_LiteralPrint(list_First(LitList)); + LitList = list_Cdr(LitList); + + if (!list_Empty(LitList)) + putchar(' '); + } +} + + +void clause_LiteralPrintUnsigned(LITERAL Literal) +/************************************************************** + INPUT: A Literal. + RETURNS: Nothing. + SUMMARY: +***************************************************************/ +{ +#ifdef CHECK + if (!clause_LiteralIsLiteral(Literal)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralPrintUnsigned:"); + misc_ErrorReport("\n Illegal input. Input not a literal."); + misc_FinishErrorReport(); + } +#endif + + term_PrintPrefix(clause_LiteralAtom(Literal)); + fflush(stdout); +} + + +void clause_LiteralPrintSigned(LITERAL Literal) +/************************************************************** + INPUT: A Literal. + RETURNS: Nothing. + SUMMARY: +***************************************************************/ +{ +#ifdef CHECK + if (!clause_LiteralIsLiteral(Literal)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralPrintSigned:"); + misc_ErrorReport("\n Illegal input. Input not a literal."); + misc_FinishErrorReport(); + } +#endif + + term_PrintPrefix(clause_LiteralSignedAtom(Literal)); + fflush(stdout); +} + + +void clause_LiteralFPrint(FILE* File, LITERAL Lit) +/************************************************************** + INPUT: A file and a literal. + RETURNS: Nothing. +************************************************************/ +{ + term_FPrintPrefix(File, clause_LiteralSignedAtom(Lit)); +} + + +LIST clause_GetLiteralSubSetList(CLAUSE Clause, int StartIndex, int EndIndex, + FLAGSTORE FlagStore, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a start literal index, an end index, a + flag store and a precedence. + RETURNS: The list of literals between the start and the end + index. + It is a list of pointers, not a list of indices. +**************************************************************/ +{ + + LIST Result; + int i; + +#ifdef CHECK + if (!clause_IsClause(Clause, FlagStore, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_ReplaceLiteralSubSet:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } + if ((StartIndex < clause_FirstLitIndex()) + || (EndIndex > clause_LastLitIndex(Clause))) { + misc_ErrorReport("\n In clause_ReplaceLiteralSubSet:"); + misc_ErrorReport("\n Illegal input."); + misc_ErrorReport("\n Index out of range."); + misc_FinishErrorReport(); + } +#endif + + Result = list_Nil(); + + for (i=StartIndex; + i<=EndIndex; + i++) { + Result = list_Cons(clause_GetLiteral(Clause, i), Result); + } + + return Result; +} + + +void clause_ReplaceLiteralSubSet(CLAUSE Clause, int StartIndex, + int EndIndex, LIST Replacement, + FLAGSTORE FlagStore, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a start literal index, an end literal + index, a flag store and a precedence. + RETURNS: None. + EFFECT: Replaces the subset of literals in <Clause> with + indices between (and including) <StartIndex> and + <EndIndex> with literals from the <Replacement> + list. +**************************************************************/ +{ + + int i; + LIST Scan; + +#ifdef CHECK + if (!clause_IsClause(Clause, FlagStore, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_ReplaceLiteralSubSet:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } + if ((StartIndex < clause_FirstLitIndex()) + || (EndIndex > clause_LastLitIndex(Clause))) { + misc_ErrorReport("\n In clause_ReplaceLiteralSubSet:"); + misc_ErrorReport("\n Illegal input."); + misc_ErrorReport("\n Index out of range."); + misc_FinishErrorReport(); + } + if (list_Length(Replacement) != (EndIndex - StartIndex + 1)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_ReplaceLiteralSubSet:"); + misc_ErrorReport("\n Illegal input. Replacement list size"); + misc_ErrorReport("\n and set size don't match"); + misc_FinishErrorReport(); + } +#endif + + for (i = StartIndex, Scan = Replacement; + i <= EndIndex; + i++, Scan = list_Cdr(Scan)) { + clause_SetLiteral(Clause, i, list_Car(Scan)); + } +} + +static __inline__ BOOL clause_LiteralsCompare(LITERAL Left, LITERAL Right) +/************************************************************** + INPUT: Two literals. + RETURNS: TRUE if Left <= Right, FALSE otherwise. + EFFECT: Compares literals by comparing their terms' arities. +***************************************************************/ +{ +#ifdef CHECK + if (!(clause_LiteralIsLiteral(Left) && clause_LiteralIsLiteral(Right))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralsCompare:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + return term_CompareAbstractLEQ(clause_LiteralSignedAtom(Left), + clause_LiteralSignedAtom(Right)); +} + +static __inline__ void clause_FixLiteralSubsetOrder(CLAUSE Clause, + int StartIndex, + int EndIndex, + FLAGSTORE FlagStore, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a start index, an end index a flag store + and a precedence. + RETURNS: None. + EFFECT: Sorts literals with indices between (and including) + <StartIndex> and <EndIndex> with respect to an abstract + list representation of terms that identifies function + symbols with their arity. +***************************************************************/ +{ + + LIST literals; + +#ifdef CHECK + if ((StartIndex < clause_FirstLitIndex()) + || (EndIndex > clause_LastLitIndex(Clause))) { + misc_ErrorReport("\n In clause_FixLiteralSubSetOrder:"); + misc_ErrorReport("\n Illegal input."); + misc_ErrorReport("\n Index out of range."); + misc_FinishErrorReport(); + } +#endif + + /* Get the literals */ + literals = clause_GetLiteralSubSetList(Clause, StartIndex, EndIndex, FlagStore, Precedence); + + /* Sort them */ + literals = list_Sort(literals, (BOOL (*) (POINTER, POINTER)) clause_LiteralsCompare); + + /* Replace clause literals in subset with sorted literals */ + clause_ReplaceLiteralSubSet(Clause, StartIndex, EndIndex, literals, FlagStore, Precedence); + + list_Delete(literals); +} + +void clause_FixLiteralOrder(CLAUSE Clause, FLAGSTORE FlagStore, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a flag store, and a precedence. + RETURNS: None. + EFFECT: Fixes literal order in a <Clause>. Different literal + types are ordered separately. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsClause(Clause, FlagStore, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_FixLiteralOrder:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + /* Fix antecedent literal order */ + clause_FixLiteralSubsetOrder(Clause, + clause_FirstAntecedentLitIndex(Clause), + clause_LastAntecedentLitIndex(Clause), + FlagStore, Precedence); + + /* Fix succedent literal order */ + clause_FixLiteralSubsetOrder(Clause, + clause_FirstSuccedentLitIndex(Clause), + clause_LastSuccedentLitIndex(Clause), + FlagStore, Precedence); + + /* Fix constraint literal order */ + clause_FixLiteralSubsetOrder(Clause, + clause_FirstConstraintLitIndex(Clause), + clause_LastConstraintLitIndex(Clause), + FlagStore, Precedence); + + /* Normalize clause, to get variable names right. */ + clause_Normalize(Clause); +} + +static int clause_CompareByWeight(CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two clauses by their weight. +***************************************************************/ +{ + NAT lweight, rweight; + int result; + + lweight = clause_Weight(Left); + rweight = clause_Weight(Right); + + if (lweight < rweight) { + result = -1; + } + else if (lweight > rweight) { + result = 1; + } + else { + result = 0; + } + + return result; +} + +static int clause_CompareByClausePartSize(CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two clauses by the number of literals in + the antecedent, succedent and constraint. +***************************************************************/ +{ + int lsize, rsize; + + lsize = clause_NumOfAnteLits(Left); + rsize = clause_NumOfAnteLits(Right); + if (lsize < rsize) + return -1; + else if (lsize > rsize) + return 1; + + lsize = clause_NumOfSuccLits(Left); + rsize = clause_NumOfSuccLits(Right); + + if (lsize < rsize) + return -1; + else if (lsize > rsize) + return 1; + + lsize = clause_NumOfConsLits(Left); + rsize = clause_NumOfConsLits(Right); + + if (lsize < rsize) + return -1; + else if (lsize > rsize) + return 1; + + return 0; +} + +void clause_CountSymbols(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: None. + EFFECT: Counts the non-variable symbols in the clause, and + increases their counts accordingly. +***************************************************************/ +{ + int i; + + for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) { + LITERAL l; + TERM t; + + l = clause_GetLiteral(Clause, i); + if (clause_LiteralIsPredicate(l)) { + SYMBOL S; + + S = clause_LiteralPredicate(l); + symbol_SetCount(S, symbol_GetCount(S) + 1); + } + + t = clause_GetLiteralAtom(Clause, i); + + term_CountSymbols(t); + } +} + + +LIST clause_ListOfPredicates(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: A list of symbols. + EFFECT: Creates a list of predicates occurring in the clause. + A predicate occurs several times in the list, if + it does so in the clause. +***************************************************************/ +{ + LIST preds; + int i; + + preds = list_Nil(); + + for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) { + LITERAL l; + + l = clause_GetLiteral(Clause, i); + if (clause_LiteralIsPredicate(l)) { + preds = list_Cons((POINTER) clause_LiteralPredicate(l), preds); + } + } + + return preds; +} + +LIST clause_ListOfConstants(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: A list of symbols. + EFFECT: Creates a list of constants occurring in the clause. + A constant occurs several times in the list, if + it does so in the clause. +***************************************************************/ +{ + LIST consts; + int i; + + consts = list_Nil(); + + for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) { + TERM t; + + t = clause_GetLiteralAtom(Clause, i); + + consts = list_Nconc(term_ListOfConstants(t), consts); + } + + return consts; +} + +LIST clause_ListOfVariables(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: A list of variables. + EFFECT: Creates a list of variables occurring in the clause. + A variable occurs several times in the list, if + it does so in the clause. +***************************************************************/ +{ + LIST vars; + int i; + + vars = list_Nil(); + + for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) { + TERM t; + + t = clause_GetLiteralAtom(Clause, i); + + vars = list_Nconc(term_ListOfVariables(t), vars); + } + + return vars; +} + +LIST clause_ListOfFunctions(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: A list of symbols. + EFFECT: Creates a list of functions occurring in the clause. + A function occurs several times in the list, if + it does so in the clause. +***************************************************************/ +{ + LIST funs; + int i; + + funs = list_Nil(); + + for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) { + TERM t; + + t = clause_GetLiteralAtom(Clause, i); + + funs = list_Nconc(term_ListOfFunctions(t), funs); + } + + return funs; +} + +static int clause_CompareByPredicateDistribution(CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two clauses by the frequency of predicates. +***************************************************************/ +{ + LIST lpreds, rpreds; + int result; + + lpreds = clause_ListOfPredicates(Left); + rpreds = clause_ListOfPredicates(Right); + + result = list_CompareMultisetsByElementDistribution(lpreds, rpreds); + + list_Delete(lpreds); + list_Delete(rpreds); + + return result; +} + +static int clause_CompareByConstantDistribution(CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two clauses by the frequency of constants. +***************************************************************/ +{ + LIST lconsts, rconsts; + int result; + + lconsts = clause_ListOfConstants(Left); + rconsts = clause_ListOfConstants(Right); + + result = list_CompareMultisetsByElementDistribution(lconsts, rconsts); + + list_Delete(lconsts); + list_Delete(rconsts); + + return result; +} + +static int clause_CompareByVariableDistribution(CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two clauses by the frequency of variables. +***************************************************************/ +{ + LIST lvars, rvars; + int result; + + lvars = clause_ListOfVariables(Left); + rvars = clause_ListOfVariables(Right); + + result = list_CompareMultisetsByElementDistribution(lvars, rvars); + + list_Delete(lvars); + list_Delete(rvars); + + return result; +} + +static int clause_CompareByFunctionDistribution(CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two clauses by the frequency of functions. +***************************************************************/ +{ + LIST lfuns, rfuns; + int result; + + lfuns = clause_ListOfFunctions(Left); + rfuns = clause_ListOfFunctions(Right); + + result = list_CompareMultisetsByElementDistribution(lfuns, rfuns); + + list_Delete(lfuns); + list_Delete(rfuns); + + return result; +} + +static int clause_CompareByDepth(CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two clauses by their depth. +***************************************************************/ +{ + if (clause_Depth(Left) < clause_Depth(Right)) + return -1; + else if (clause_Depth(Left) > clause_Depth(Right)) + return 1; + + return 0; +} + +static int clause_CompareByMaxVar(CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two clauses by their maximal variable. +***************************************************************/ +{ + if (clause_MaxVar(Left) < clause_MaxVar(Right)) + return -1; + else if (clause_MaxVar(Left) > clause_MaxVar(Right)) + return 1; + + return 0; +} + +static int clause_CompareByLiterals(CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two clauses by comparing their literals + from left to right. +***************************************************************/ +{ + int firstlitleft, lastlitleft; + int firstlitright, lastlitright; + int i, j; + int result; + + result = 0; + + /* Compare sorted literals from right to left */ + + firstlitleft = clause_FirstLitIndex(); + lastlitleft = clause_LastLitIndex(Left); + firstlitright = clause_FirstLitIndex(); + lastlitright = clause_LastLitIndex(Right); + + for (i = lastlitleft, j = lastlitright; + i >= firstlitleft && j >= firstlitright; + --i, --j) { + TERM lterm, rterm; + + lterm = clause_GetLiteralTerm(Left, i); + rterm = clause_GetLiteralTerm(Right, j); + + result = term_CompareAbstract(lterm, rterm); + + if (result != 0) + break; + } + + if (result == 0) { + /* All literals compared equal, so check if someone has + uncompared literals left over. + */ + if ( i > j) { + /* Left clause has uncompared literals left over. */ + result = 1; + } + else if (i < j) { + /* Right clause has uncompared literals left over. */ + result = -1; + } + } + + return result; +} + +static int clause_CompareBySymbolOccurences(CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two clauses by comparing the occurrences of + symbols in their respective literals from left to + right. If a symbol occurs less frequently than + its positional equivalent in the other clause, + then the first clause is smaller. +***************************************************************/ +{ + int firstlitleft, lastlitleft; + int firstlitright, lastlitright; + int i, j; + int result; + + result = 0; + + /* Compare sorted literals from right to left */ + + firstlitleft = clause_FirstLitIndex(); + lastlitleft = clause_LastLitIndex(Left); + firstlitright = clause_FirstLitIndex(); + lastlitright = clause_LastLitIndex(Right); + + for (i = lastlitleft, j = lastlitright; + i >= firstlitleft && j >= firstlitright; + --i, --j) { + TERM lterm, rterm; + LITERAL llit, rlit; + + llit = clause_GetLiteral(Left, i); + rlit = clause_GetLiteral(Right, j); + + if (clause_LiteralIsPredicate(llit)) { + if (clause_LiteralIsPredicate(rlit)) { + if (symbol_GetCount(clause_LiteralPredicate(llit)) + < symbol_GetCount(clause_LiteralPredicate(rlit))) { + return -1; + } + else if (symbol_GetCount(clause_LiteralPredicate(llit)) + > symbol_GetCount(clause_LiteralPredicate(rlit))) { + return 1; + } + } + } + + lterm = clause_GetLiteralTerm(Left, i); + rterm = clause_GetLiteralTerm(Right, j); + + result = term_CompareBySymbolOccurences(lterm, rterm); + + if (result != 0) + break; + } + + return result; +} + +int clause_CompareAbstract(CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two clauses by their weight. If the weight + is equal, it compares the clauses by the arity of + their literals from right to left. + CAUTION: Expects clause literal order to be fixed. +***************************************************************/ +{ + + typedef int (*CLAUSE_COMPARE_FUNCTION) (CLAUSE, CLAUSE); + + static const CLAUSE_COMPARE_FUNCTION clause_compare_functions [] = { + clause_CompareByWeight, + clause_CompareByDepth, + clause_CompareByMaxVar, + clause_CompareByClausePartSize, + clause_CompareByLiterals, + clause_CompareBySymbolOccurences, + clause_CompareByPredicateDistribution, + clause_CompareByConstantDistribution, + clause_CompareByFunctionDistribution, + clause_CompareByVariableDistribution, + }; + + int result; + int i; + int functions; + + result = 0; + functions = sizeof(clause_compare_functions)/sizeof(CLAUSE_COMPARE_FUNCTION); + + for (i = 0; i < functions; i++) { + result = clause_compare_functions[i](Left, Right); + + if ( result != 0) { + return result; + } + } + + return 0; +} + + +/**************************************************************/ +/* Clause functions */ +/**************************************************************/ + +void clause_Init(void) +/************************************************************** + INPUT: None. + RETURNS: Nothing. + SUMMARY: Initializes the clause counter and other variables + from this module. +***************************************************************/ +{ + int i; + clause_SetCounter(1); + clause_STAMPID = term_GetStampID(); + for (i = 0; i <= clause_MAXWEIGHT; i++) + clause_SORT[i] = list_Nil(); +} + + +CLAUSE clause_CreateBody(int ClauseLength) +/************************************************************** + INPUT: The number of literals as integer. + RETURNS: A new generated clause node for 'ClauseLength' + MEMORY: Allocates a CLAUSE_NODE and the needed array for LITERALs. +*************************************************************/ +{ + CLAUSE Result; + + Result = (CLAUSE)memory_Malloc(sizeof(CLAUSE_NODE)); + + Result->clausenumber = clause_IncreaseCounter(); + Result->maxVar = symbol_GetInitialStandardVarCounter(); + Result->flags = 0; + Result->depth = 0; + clause_InitSplitData(Result); + Result->weight = clause_WEIGHTUNDEFINED; + Result->parentCls = list_Nil(); + Result->parentLits = list_Nil(); + + Result->c = 0; + Result->a = 0; + Result->s = 0; + + if (ClauseLength != 0) + Result->literals = + (LITERAL *)memory_Malloc((ClauseLength) * sizeof(LITERAL)); + + clause_SetFromInput(Result); + + return Result; +} + + +CLAUSE clause_Create(LIST Constraint, LIST Antecedent, LIST Succedent, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: Three lists of pointers to atoms, a flag store and + a precedence. + RETURNS: The new generated clause. + MEMORY: Allocates a CLAUSE_NODE and the needed LITERAL_NODEs, + uses the terms from the lists, additionally allocates + termnodes for the fol_Not() in Const. and Ante. +*************************************************************/ +{ + CLAUSE Result; + int i, c, a, s; + + Result = (CLAUSE)memory_Malloc(sizeof(CLAUSE_NODE)); + + Result->clausenumber = clause_IncreaseCounter(); + Result->flags = 0; + Result->depth = 0; + Result->weight = clause_WEIGHTUNDEFINED; + clause_InitSplitData(Result); + Result->parentCls = list_Nil(); + Result->parentLits = list_Nil(); + + Result->c = (c = list_Length(Constraint)); + Result->a = (a = list_Length(Antecedent)); + Result->s = (s = list_Length(Succedent)); + + if (!clause_IsEmptyClause(Result)) + Result->literals = + (LITERAL *) memory_Malloc((c+a+s) * sizeof(LITERAL)); + + for (i = 0; i < c; i++) { + Result->literals[i] = + clause_LiteralCreate(term_Create(fol_Not(), + list_List((TERM)list_Car(Constraint))),Result); + Constraint = list_Cdr(Constraint); + } + + a += c; + for ( ; i < a; i++) { + Result->literals[i] = + clause_LiteralCreate(term_Create(fol_Not(), + list_List((TERM)list_Car(Antecedent))), Result); + Antecedent = list_Cdr(Antecedent); + } + + s += a; + for ( ; i < s; i++) { + Result->literals[i] = + clause_LiteralCreate((TERM) list_Car(Succedent), Result); + Succedent = list_Cdr(Succedent); + } + + clause_OrientAndReInit(Result, Flags, Precedence); + clause_SetFromInput(Result); + + return Result; +} + + +CLAUSE clause_CreateCrude(LIST Constraint, LIST Antecedent, LIST Succedent, + BOOL Con) +/************************************************************** + INPUT: Three lists of pointers to literals (!) and a Flag indicating + whether the clause comes from the conjecture part of of problem. + It is assumed that Constraint and Antecedent literals are negative, + whereas Succedent literals are positive. + RETURNS: The new generated clause, where a clause_OrientAndReInit has still + to be performed, i.e., variables are not normalized, maximal literal + flags not set, equations not oriented, the weight is not set. + MEMORY: Allocates a CLAUSE_NODE and the needed LITERAL_NODEs, + uses the terms from the lists, additionally allocates + termnodes for the fol_Not() in Const. and Ante. +****************************************************************/ +{ + CLAUSE Result; + int i,c,a,s; + + Result = (CLAUSE)memory_Malloc(sizeof(CLAUSE_NODE)); + + Result->clausenumber = clause_IncreaseCounter(); + Result->flags = 0; + if (Con) + clause_SetFlag(Result, CONCLAUSE); + + Result->depth = 0; + Result->weight = clause_WEIGHTUNDEFINED; + clause_InitSplitData(Result); + Result->parentCls = list_Nil(); + Result->parentLits = list_Nil(); + + Result->c = (c = list_Length(Constraint)); + Result->a = (a = list_Length(Antecedent)); + Result->s = (s = list_Length(Succedent)); + + if (!clause_IsEmptyClause(Result)) + Result->literals = (LITERAL *)memory_Malloc((c+a+s) * sizeof(LITERAL)); + + for (i = 0; i < c; i++) { + Result->literals[i] = + clause_LiteralCreate(list_Car(Constraint),Result); + Constraint = list_Cdr(Constraint); + } + + a += c; + for ( ; i < a; i++) { + Result->literals[i] = + clause_LiteralCreate(list_Car(Antecedent), Result); + Antecedent = list_Cdr(Antecedent); + } + + s += a; + for ( ; i < s; i++) { + Result->literals[i] = clause_LiteralCreate(list_Car(Succedent), Result); + Succedent = list_Cdr(Succedent); + } + + clause_SetFromInput(Result); + + return Result; +} + + +CLAUSE clause_CreateUnnormalized(LIST Constraint, LIST Antecedent, + LIST Succedent) +/************************************************************** + INPUT: Three lists of pointers to atoms. + RETURNS: The new generated clause. + MEMORY: Allocates a CLAUSE_NODE and the needed LITERAL_NODEs, + uses the terms from the lists, additionally allocates + termnodes for the fol_Not() in Const. and Ante. + CAUTION: The weight of the clause is not set correctly and + equations are not oriented! +****************************************************************/ +{ + CLAUSE Result; + int i,c,a,s; + + Result = (CLAUSE)memory_Malloc(sizeof(CLAUSE_NODE)); + + Result->clausenumber = clause_IncreaseCounter(); + Result->flags = 0; + Result->depth = 0; + Result->weight = clause_WEIGHTUNDEFINED; + clause_InitSplitData(Result); + Result->parentCls = list_Nil(); + Result->parentLits = list_Nil(); + + Result->c = (c = list_Length(Constraint)); + Result->a = (a = list_Length(Antecedent)); + Result->s = (s = list_Length(Succedent)); + + if (!clause_IsEmptyClause(Result)) { + Result->literals = (LITERAL *)memory_Malloc((c+a+s) * sizeof(LITERAL)); + + for (i = 0; i < c; i++) { + Result->literals[i] = + clause_LiteralCreate(term_Create(fol_Not(), + list_List(list_Car(Constraint))), + Result); + Constraint = list_Cdr(Constraint); + } + + a += c; + for ( ; i < a; i++) { + Result->literals[i] = + clause_LiteralCreate(term_Create(fol_Not(), + list_List(list_Car(Antecedent))), + Result); + Antecedent = list_Cdr(Antecedent); + } + + s += a; + for ( ; i < s; i++) { + Result->literals[i] = + clause_LiteralCreate((TERM)list_Car(Succedent), Result); + Succedent = list_Cdr(Succedent); + } + clause_UpdateMaxVar(Result); + } + + return Result; +} + + +CLAUSE clause_CreateFromLiterals(LIST LitList, BOOL Sorts, BOOL Conclause, + BOOL Ordering, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A list of literals, three boolean flags indicating whether + sort constraint literals should be generated, whether the + clause is a conjecture clause, whether the ordering information + should be established, a flag store and a precedence. + RETURNS: The new generated clause. + EFFECT: The result clause will be normalized and the maximal + variable will be set. If <Ordering> is FALSE no additional + initializations will be done. This mode is intended for + the parser for creating clauses at a time when the ordering + and weight flags aren't determined finally. + Only if <Ordering> is TRUE the equations will be oriented, + the maximal literals will be marked and the clause weight + will be set correctly. + MEMORY: Allocates a CLAUSE_NODE and the needed LITERAL_NODEs, + uses the terms from the lists. +****************************************************************/ +{ + CLAUSE Result; + LIST Antecedent,Succedent,Constraint; + TERM Atom; + + Antecedent = list_Nil(); + Succedent = list_Nil(); + Constraint = list_Nil(); + + while (!list_Empty(LitList)) { + if (term_TopSymbol(list_Car(LitList)) == fol_Not()) { + Atom = term_FirstArgument(list_Car(LitList)); + if (Sorts && symbol_IsBaseSort(term_TopSymbol(Atom)) && term_IsVariable(term_FirstArgument(Atom))) + Constraint = list_Cons(list_Car(LitList),Constraint); + else + Antecedent = list_Cons(list_Car(LitList),Antecedent); + } + else + Succedent = list_Cons(list_Car(LitList),Succedent); + LitList = list_Cdr(LitList); + } + + Constraint = list_NReverse(Constraint); + Antecedent = list_NReverse(Antecedent); + Succedent = list_NReverse(Succedent); + Result = clause_CreateCrude(Constraint, Antecedent, Succedent, Conclause); + + list_Delete(Constraint); + list_Delete(Antecedent); + list_Delete(Succedent); + + if (Ordering) + clause_OrientAndReInit(Result, Flags, Precedence); + else { + clause_Normalize(Result); + clause_UpdateMaxVar(Result); + } + + return Result; +} + +void clause_SetSortConstraint(CLAUSE Clause, BOOL Strong, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a flag indicating whether also negative + monadic literals with a real term argument should be + put in the sort constraint, a flag store and a precedence. + RETURNS: Nothing. + EFFECT: Negative monadic literals are put in the sort constraint. +****************************************************************/ +{ + LITERAL ActLit,Help; + TERM ActAtom; + int i,k,NewConLits; + + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_SetSortConstraint:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + i = clause_LastConstraintLitIndex(Clause); + NewConLits = 0; + + for (k=clause_FirstAntecedentLitIndex(Clause);k<=clause_LastAntecedentLitIndex(Clause);k++) { + ActLit = clause_GetLiteral(Clause,k); + ActAtom = clause_LiteralAtom(ActLit); + if (symbol_IsBaseSort(term_TopSymbol(ActAtom)) && + (Strong || term_IsVariable(term_FirstArgument(ActAtom)))) { + if (++i != k) { + Help = clause_GetLiteral(Clause,i); + clause_SetLiteral(Clause,i,ActLit); + clause_SetLiteral(Clause,k,Help); + } + NewConLits++; + } + } + + clause_SetNumOfConsLits(Clause, clause_NumOfConsLits(Clause) + NewConLits); + clause_SetNumOfAnteLits(Clause, clause_NumOfAnteLits(Clause) - NewConLits); + clause_ReInit(Clause, Flags, Precedence); + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_SetSortConstraint:"); + misc_ErrorReport("\n Illegal computations."); + misc_FinishErrorReport(); + } +#endif + +} + + + +void clause_Delete(CLAUSE Clause) +/************************************************************** + INPUT: A Clause. + RETURNS: Nothing. + MEMORY: Frees the memory of the clause. +***************************************************************/ +{ + int i, n; + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { /* Clause may be a byproduct of some hyper rule */ + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_Delete:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + n = clause_Length(Clause); + + for (i = 0; i < n; i++) + clause_LiteralDelete(clause_GetLiteral(Clause,i)); + + clause_FreeLitArray(Clause); + + list_Delete(clause_ParentClauses(Clause)); + list_Delete(clause_ParentLiterals(Clause)); +#ifdef CHECK + if ((Clause->splitfield != NULL) && (Clause->splitfield_length == 0)) + { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_Delete:"); + misc_ErrorReport("\n Illegal splitfield_length."); + misc_FinishErrorReport(); + } + if ((Clause->splitfield == NULL) && (Clause->splitfield_length != 0)) + { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_Delete:"); + misc_ErrorReport("\n Illegal splitfield."); + misc_FinishErrorReport(); + } +#endif + if (Clause->splitfield != NULL) { + + memory_Free(Clause->splitfield, + sizeof(SPLITFIELDENTRY) * Clause->splitfield_length); + } + clause_Free(Clause); +} + + +/**************************************************************/ +/* Functions to use the sharing for clauses. */ +/**************************************************************/ + +void clause_InsertIntoSharing(CLAUSE Clause, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A Clause, an index, a flag store and a precedence. + RETURNS: Nothing. + SUMMARY: Inserts the unsigned atoms of 'Clause' into the sharing index. +***************************************************************/ +{ + int i, litnum; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_Delete:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } + clause_Check(Clause, Flags, Precedence); +#endif + + litnum = clause_Length(Clause); + + for (i = 0; i < litnum; i++) { + clause_LiteralInsertIntoSharing(clause_GetLiteral(Clause,i), ShIndex); + } +} + + +void clause_DeleteFromSharing(CLAUSE Clause, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A Clause, an Index, a flag store and a precedence. + RETURNS: Nothing. + SUMMARY: Deletes 'Clause' and all its literals from the sharing, + frees the memory of 'Clause'. +***************************************************************/ +{ + int i, length; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_DeleteFromSharing:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + length = clause_Length(Clause); + + for (i = 0; i < length; i++) + clause_LiteralDeleteFromSharing(clause_GetLiteral(Clause,i),ShIndex); + + clause_FreeLitArray(Clause); + + list_Delete(clause_ParentClauses(Clause)); + list_Delete(clause_ParentLiterals(Clause)); +#ifdef CHECK + if ((Clause->splitfield != NULL) && (Clause->splitfield_length == 0)) + { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_DeleteFromSharing:"); + misc_ErrorReport("\n Illegal splitfield_length."); + misc_FinishErrorReport(); + } + if ((Clause->splitfield == NULL) && (Clause->splitfield_length != 0)) + { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_DeleteFromSharing:"); + misc_ErrorReport("\n Illegal splitfield."); + misc_FinishErrorReport(); + } +#endif + if (Clause->splitfield != NULL) { + memory_Free(Clause->splitfield, + sizeof(SPLITFIELDENTRY) * Clause->splitfield_length); + } + clause_Free(Clause); +} + + +void clause_MakeUnshared(CLAUSE Clause, SHARED_INDEX ShIndex) +/************************************************************** + INPUT: A Clause and an Index. + RETURNS: Nothing. + SUMMARY: Deletes the clauses literals from the sharing and + replaces them by unshared copies. +***************************************************************/ +{ + LITERAL ActLit; + TERM SharedAtom, AtomCopy; + int i,LastAnte,length; + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_MakeUnshared:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + LastAnte = clause_LastAntecedentLitIndex(Clause); + length = clause_Length(Clause); + + for (i = clause_FirstLitIndex(); i <= LastAnte; i++) { + ActLit = clause_GetLiteral(Clause, i); + SharedAtom = clause_LiteralAtom(ActLit); + AtomCopy = term_Copy(SharedAtom); + sharing_Delete(ActLit, SharedAtom, ShIndex); + clause_LiteralSetNegAtom(ActLit, AtomCopy); + } + + for ( ; i < length; i++) { + ActLit = clause_GetLiteral(Clause, i); + SharedAtom = clause_LiteralSignedAtom(ActLit); + AtomCopy = term_Copy(SharedAtom); + sharing_Delete(ActLit, SharedAtom, ShIndex); + clause_LiteralSetPosAtom(ActLit, AtomCopy); + } +} + +void clause_MoveSharedClause(CLAUSE Clause, SHARED_INDEX Source, + SHARED_INDEX Destination, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A Clause, two indexes, a flag store, and a precedence. + RETURNS: Nothing. + EFFECT: Deletes <Clause> from <Source> and inserts it into + <Destination>. +***************************************************************/ +{ + LITERAL Lit; + TERM Atom,Copy; + int i,length; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_MoveSharedClause:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + length = clause_Length(Clause); + + for (i = clause_FirstLitIndex(); i < length; i++) { + Lit = clause_GetLiteral(Clause, i); + Atom = clause_LiteralAtom(Lit); + Copy = term_Copy(Atom); /* sharing_Insert works destructively on <Copy>'s superterms */ + clause_LiteralSetAtom(Lit, sharing_Insert(Lit, Copy, Destination)); + sharing_Delete(Lit, Atom, Source); + term_Delete(Copy); + } +} + + +void clause_DeleteSharedLiteral(CLAUSE Clause, int Indice, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A Clause, a literals indice, an Index, a flag store + and a precedence. + RETURNS: Nothing. + SUMMARY: Deletes the shared literal from the clause. + MEMORY: Various. +***************************************************************/ +{ + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_DeleteSharedLiteral:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + clause_MakeUnshared(Clause, ShIndex); + clause_DeleteLiteral(Clause, Indice, Flags, Precedence); + clause_InsertIntoSharing(Clause, ShIndex, Flags, Precedence); +} + + +void clause_DeleteClauseList(LIST ClauseList) +/************************************************************** + INPUT: A list of unshared clauses. + RETURNS: Nothing. + SUMMARY: Deletes all clauses in the list and the list. + MEMORY: Frees the lists and the clauses' memory. + ***************************************************************/ +{ + LIST Scan; + + for (Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (clause_Exists(list_Car(Scan))) + clause_Delete(list_Car(Scan)); + + list_Delete(ClauseList); +} + + +void clause_DeleteSharedClauseList(LIST ClauseList, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A list of clauses, an index, a flag store and + a precedence. + RETURNS: Nothing. + SUMMARY: Deletes all clauses in the list from the sharing. + MEMORY: Frees the lists and the clauses' memory. +***************************************************************/ +{ + LIST Scan; + + for (Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) + clause_DeleteFromSharing(list_Car(Scan), ShIndex, Flags, Precedence); + + list_Delete(ClauseList); +} + + +void clause_DeleteAllIndexedClauses(SHARED_INDEX ShIndex, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: An Index, a flag store and a precedence. + RETURNS: Nothing. + SUMMARY: Deletes all clauses' terms from the sharing, frees their + memory. + MEMORY: Frees the memory of all clauses with terms in the index. +***************************************************************/ +{ + LIST TermList,DelList,Scan; + TERM NewVar; + SYMBOL NewVarSymbol; + + NewVar = term_CreateStandardVariable(); + NewVarSymbol = term_TopSymbol(NewVar); + + TermList = st_GetInstance(cont_LeftContext(), sharing_Index(ShIndex), NewVar); + /* This should yield a list of all terms in the index + and thus the sharing. */ + + while (!list_Empty(TermList)) { + + DelList = sharing_GetDataList(list_Car(TermList), ShIndex); + + for (Scan = DelList; + !list_Empty(Scan); + Scan = list_Cdr(Scan)) + list_Rplaca(Scan, clause_LiteralOwningClause(list_Car(Scan))); + + DelList = list_PointerDeleteDuplicates(DelList); + + for (Scan = DelList; + !list_Empty(Scan); + Scan = list_Cdr(Scan)) + clause_DeleteFromSharing(list_Car(Scan), ShIndex, Flags, Precedence); + + list_Delete(TermList); + + TermList = st_GetInstance(cont_LeftContext(), sharing_Index(ShIndex), NewVar); + + list_Delete(DelList); + } + term_Delete(NewVar); + symbol_Delete(NewVarSymbol); +} + + +void clause_PrintAllIndexedClauses(SHARED_INDEX ShIndex) +/************************************************************** + INPUT: An Index. + RETURNS: Nothing. + SUMMARY: Prints all indexed clauses to stdout. +***************************************************************/ +{ + LIST TermList,ClList,PrintList,Scan; + TERM NewVar; + SYMBOL NewVarSymbol; + + NewVar = term_CreateStandardVariable(); + NewVarSymbol = term_TopSymbol(NewVar); + + TermList = st_GetInstance(cont_LeftContext(), sharing_Index(ShIndex), NewVar); + /* This should yield a list of all terms in the index + and thus the sharing. */ + + PrintList = list_Nil(); + + while (!list_Empty(TermList)) { + + ClList = sharing_GetDataList(list_Car(TermList), ShIndex); + + for (Scan = ClList; + !list_Empty(Scan); + Scan = list_Cdr(Scan)) + list_Rplaca(Scan, clause_LiteralOwningClause(list_Car(Scan))); + + PrintList = list_NPointerUnion(ClList, PrintList); + + Scan = TermList; + TermList = list_Cdr(TermList); + list_Free(Scan); + } + clause_ListPrint(PrintList); + + list_Delete(PrintList); + + term_Delete(NewVar); + symbol_Delete(NewVarSymbol); +} + + +LIST clause_AllIndexedClauses(SHARED_INDEX ShIndex) +/************************************************************** + INPUT: An index + RETURNS: A list of all the clauses in the index + MEMORY: Memory is allocated for the list nodes +***************************************************************/ +{ + LIST clauselist, scan; + clauselist = sharing_GetAllSuperTerms(ShIndex); + for (scan = clauselist; scan != list_Nil(); scan = list_Cdr(scan)) + list_Rplaca(scan, clause_LiteralOwningClause(list_Car(scan))); + clauselist = list_PointerDeleteDuplicates(clauselist); + return clauselist; +} + + +/**************************************************************/ +/* Clause Access Functions */ +/**************************************************************/ + +void clause_DeleteLiteralNN(CLAUSE Clause, int Indice) +/************************************************************** + INPUT: An unshared clause, and a literal index. + RETURNS: Nothing. + EFFECT: The literal is position <Indice> is deleted from <Clause>. + The clause isn't reinitialized afterwards. + MEMORY: The memory of the literal with the 'Indice' and + memory of its atom is freed. +***************************************************************/ +{ + int i, lc, la, length, shift; + LITERAL *Literals; + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause) || (clause_Length(Clause) <= Indice) || + Indice < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_DeleteLiteral:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + lc = clause_LastConstraintLitIndex(Clause); + la = clause_LastAntecedentLitIndex(Clause); + length = clause_Length(Clause); + + /* Create a new literal array */ + if (length > 1) + Literals = (LITERAL*) memory_Malloc(sizeof(LITERAL) * (length-1)); + else + Literals = (LITERAL*) NULL; + + /* Copy literals to the new array */ + shift = 0; + length--; /* The loop iterates over the new array */ + for (i = 0; i < length; i++) { + if (i == Indice) + shift = 1; + Literals[i] = Clause->literals[i+shift]; + } + + /* Free literal and old array and set new one */ + clause_LiteralDelete(clause_GetLiteral(Clause, Indice)); + clause_FreeLitArray(Clause); + Clause->literals = Literals; + + /* Update clause */ + if (Indice <= lc) + clause_SetNumOfConsLits(Clause, clause_NumOfConsLits(Clause) - 1); + else if (Indice <= la) + clause_SetNumOfAnteLits(Clause, clause_NumOfAnteLits(Clause) - 1); + else + clause_SetNumOfSuccLits(Clause, clause_NumOfSuccLits(Clause) - 1); + /* Mark the weight as undefined */ + Clause->weight = clause_WEIGHTUNDEFINED; +} + + +void clause_DeleteLiteral(CLAUSE Clause, int Indice, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: An unshared clause, a literals index, a flag store, + and a precedence. + RETURNS: Nothing. + EFFECT: The literal at position <Indice> is deleted from <Clause>. + In contrast to the function clause_DeleteLiteralNN + the clause is reinitialized afterwards. + MEMORY: The memory of the literal with the 'Indice' and memory + of its atom is freed. +***************************************************************/ +{ + clause_DeleteLiteralNN(Clause, Indice); + clause_ReInit(Clause, Flags, Precedence); +} + + +void clause_DeleteLiterals(CLAUSE Clause, LIST Indices, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: An unshared clause, a list of literal indices a + flag store and a precedence. + RETURNS: Nothing. + EFFECT: The literals given by <Indices> are deleted. + The clause is reinitialized afterwards. + MEMORY: The memory of the literals with the 'Indice' and + memory of its atom is freed. +***************************************************************/ +{ + LITERAL *NewLits; + int i, j, nc, na, ns, lc, la, olength, nlength; + +#ifdef CHECK + LIST Scan; + if (!list_IsSetOfPointers(Indices)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_DeleteLiterals:"); + misc_ErrorReport(" list contains duplicate indices."); + misc_FinishErrorReport(); + } + /* check the literal indices */ + for (Scan = Indices; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + i = (int) list_Car(Scan); + if (i < 0 || i > clause_LastLitIndex(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_DeleteLiterals:"); + misc_ErrorReport(" literal index %d is out ", i); + misc_ErrorReport(" of bounds"); + misc_FinishErrorReport(); + } + } +#endif + + nc = 0; + na = 0; + ns = 0; + lc = clause_LastConstraintLitIndex(Clause); + la = clause_LastAntecedentLitIndex(Clause); + + olength = clause_Length(Clause); + nlength = olength - list_Length(Indices); + + if (nlength != 0) + NewLits = (LITERAL*) memory_Malloc(sizeof(LITERAL) * nlength); + else + NewLits = (LITERAL*) NULL; + + for (i=clause_FirstLitIndex(), j=clause_FirstLitIndex(); i < olength; i++) + + if (list_PointerMember(Indices, (POINTER) i)) + clause_LiteralDelete(clause_GetLiteral(Clause,i)); + else { + + NewLits[j++] = clause_GetLiteral(Clause,i); + + if (i <= lc) + nc++; + else if (i <= la) + na++; + else + ns++; + } + clause_FreeLitArray(Clause); + Clause->literals = NewLits; + + clause_SetNumOfConsLits(Clause, nc); + clause_SetNumOfAnteLits(Clause, na); + clause_SetNumOfSuccLits(Clause, ns); + + clause_ReInit(Clause, Flags, Precedence); +} + + +/**************************************************************/ +/* Clause Comparisons */ +/**************************************************************/ + +BOOL clause_IsHornClause(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: The boolean value TRUE if 'Clause' is a hornclause + FALSE else. + ***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_IsHornClause:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + return (clause_NumOfSuccLits(Clause) <= 1); +} + + +BOOL clause_HasTermSortConstraintLits(CLAUSE Clause) +/************************************************************** + INPUT: A clause, + RETURNS: TRUE iff there is at least one sort constraint atom having + a term as its argument +***************************************************************/ +{ + int i,n; + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_HasTermSortConstraintLits:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + n = clause_LastConstraintLitIndex(Clause); + + for (i = clause_FirstConstraintLitIndex(Clause); i <= n; i++) + if (!term_AllArgsAreVar(clause_GetLiteralAtom(Clause,i))) + return TRUE; + + return FALSE; +} + + +BOOL clause_HasSolvedConstraint(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: The boolean value TRUE if 'Clause' has a solved + constraint, i.e. only variables as sort arguments, + FALSE else. +***************************************************************/ +{ + int i,c; + LIST CVars, LitVars; + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_HasSolvedConstraint:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + CVars = list_Nil(); + c = clause_NumOfConsLits(Clause); + + if (c == 0) + return TRUE; + + if (clause_HasTermSortConstraintLits(Clause)) + return FALSE; + + for (i = 0; i < c; i++) + CVars = list_NPointerUnion(term_VariableSymbols(clause_GetLiteralAtom(Clause, i)), CVars); + + if (i == c) { + c = clause_Length(Clause); + LitVars = list_Nil(); + + for ( ; i < c; i++) + LitVars = list_NPointerUnion(LitVars, term_VariableSymbols(clause_GetLiteralAtom(Clause, i))); + + if (list_Empty(CVars = list_NPointerDifference(CVars, LitVars))) { + list_Delete(LitVars); + return TRUE; + } + list_Delete(LitVars); + } + + list_Delete(CVars); + + return FALSE; +} + + +BOOL clause_HasSelectedLiteral(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A Clause, a flag store and a precedence. + RETURNS: The boolean value TRUE iff <Clause> has a selected literal +***************************************************************/ +{ + int i,negs; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_HasSelectedLiteral:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + negs = clause_LastAntecedentLitIndex(Clause); + + for (i=clause_FirstAntecedentLitIndex(Clause); i <= negs; i++) + if (clause_LiteralGetFlag(clause_GetLiteral(Clause,i), LITSELECT)) + return TRUE; + + return FALSE; +} + + +BOOL clause_IsDeclarationClause(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: The boolean value TRUE, if 'Clause' has only variables + as arguments in constraint literals. +***************************************************************/ +{ + int i,length; + LITERAL Lit; + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_IsDeclarationClause:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (!clause_HasSolvedConstraint(Clause)) + return FALSE; + + length = clause_Length(Clause); + + for (i=clause_FirstSuccedentLitIndex(Clause);i<length;i++) { + Lit = clause_GetLiteral(Clause,i); + if (clause_LiteralIsMaximal(Lit) && + symbol_IsBaseSort(term_TopSymbol(clause_LiteralSignedAtom(Lit)))) + return TRUE; + } + + return FALSE; +} + + +BOOL clause_IsSortTheoryClause(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A Clause, a flag store and a precedence. + RETURNS: The boolean value TRUE, if 'Clause' has only variables + as arguments in constraint literals, no antecedent literals + and exactly one monadic succedent literal. +***************************************************************/ +{ + LITERAL Lit; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_IsSortTheoryClause:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + if (clause_NumOfAnteLits(Clause) > 0 || + clause_NumOfSuccLits(Clause) > 1 || + !clause_HasSolvedConstraint(Clause)) + return FALSE; + + Lit = clause_GetLiteral(Clause,clause_FirstSuccedentLitIndex(Clause)); + if (symbol_IsBaseSort(term_TopSymbol(clause_LiteralSignedAtom(Lit)))) + return TRUE; + + return FALSE; +} + +BOOL clause_IsPotentialSortTheoryClause(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A Clause, a flag store and a precedence. + RETURNS: The boolean value TRUE, if 'Clause' has monadic literals + only variables as arguments in antecedent/constraint literals, + no other antecedent literals and exactly one monadic succedent + literal. +***************************************************************/ +{ + LITERAL Lit; + int i; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_IsPotentialSortTheoryClause:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + if (clause_NumOfSuccLits(Clause) != 1) + return FALSE; + + for (i=clause_FirstLitIndex();i<clause_FirstSuccedentLitIndex(Clause);i++) { + Lit = clause_GetLiteral(Clause,i); + if (!symbol_IsBaseSort(term_TopSymbol(clause_LiteralAtom(Lit))) || + !term_IsVariable(term_FirstArgument(clause_LiteralAtom(Lit)))) + return FALSE; + } + + Lit = clause_GetLiteral(Clause,clause_FirstSuccedentLitIndex(Clause)); + if (symbol_IsBaseSort(term_TopSymbol(clause_LiteralSignedAtom(Lit)))) + return TRUE; + + return FALSE; +} + + +BOOL clause_HasOnlyVarsInConstraint(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A Clause, a flag store and a precedence. + RETURNS: The boolean value TRUE, if 'Clause' has only variables + as arguments in constraint literals. +***************************************************************/ +{ + int i,nc; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_HasOnlyVarsInConstraint:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + nc = clause_NumOfConsLits(Clause); + + for (i = 0; i < nc && term_AllArgsAreVar(clause_GetLiteralAtom(Clause,i)); i++) + /* empty */; + + return (i == nc); +} + + +BOOL clause_HasSortInSuccedent(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A Clause, a flag store and a precedence. + RETURNS: The boolean value TRUE, if 'Clause' has a maximal succedent + sort literal; FALSE, else. +***************************************************************/ +{ + LITERAL Lit; + int i,l; + BOOL result = FALSE; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_HasSortInSuccedent:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + l = clause_Length(Clause); + + for (i = clause_FirstSuccedentLitIndex(Clause); i < l && !result ; i++) { + Lit = clause_GetLiteral(Clause, i); + result = (symbol_Arity(term_TopSymbol(clause_LiteralAtom(Lit))) == 1); + } + return result; +} + + +BOOL clause_LitsHaveCommonVar(LITERAL Lit1, LITERAL Lit2) +/************************************************************** + INPUT: Two literals. + RETURNS: The boolean value TRUE, if 'Lit1' and 'Lit2' have + common variables, FALSE, else. +***************************************************************/ +{ + LIST Vars1, Vars2; + BOOL Result; + + Vars1 = term_VariableSymbols(clause_LiteralAtom(Lit1)); + Vars2 = term_VariableSymbols(clause_LiteralAtom(Lit2)); + Result = list_HasIntersection(Vars1, Vars2); + list_Delete(Vars1); + list_Delete(Vars2); + + return Result; +} + + +/**************************************************************/ +/* Clause Input and Output Functions */ +/**************************************************************/ + +void clause_Print(CLAUSE Clause) +/************************************************************** + INPUT: A Clause. + RETURNS: Nothing. + SUMMARY: The clause is printed to stdout. +***************************************************************/ +{ + RULE Origin; + LITERAL Lit; + int i,c,a,s; + +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_Print:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + if (!clause_Exists(Clause)) + fputs("(CLAUSE)NULL", stdout); + else { + printf("%d",clause_Number(Clause)); + + Origin = clause_Origin(Clause); + printf("[%d:", clause_SplitLevel(Clause)); + +#ifdef CHECK + if (Clause->splitfield_length <= 1) + fputs("0.", stdout); + else + for (i=Clause->splitfield_length-1; i > 0; i--) + printf("%lu.", Clause->splitfield[i]); + if (Clause->splitfield_length == 0) + putchar('1'); + else + printf("%lu", (Clause->splitfield[0] | 1)); + printf(":%c%c:%c:%d:%d:", clause_GetFlag(Clause, CONCLAUSE) ? 'C' : 'A', + clause_GetFlag(Clause, WORKEDOFF) ? 'W' : 'U', + clause_GetFlag(Clause, NOPARAINTO) ? 'N' : 'P', + clause_Weight(Clause), clause_Depth(Clause)); +#endif + + clause_PrintOrigin(Clause); + + if (Origin == INPUT) { + ; + } else { + putchar(':'); + clause_PrintParentClauses(Clause); + } + putchar(']'); + + c = clause_NumOfConsLits(Clause); + a = clause_NumOfAnteLits(Clause); + s = clause_NumOfSuccLits(Clause); + + for (i = 0; i < c; i++) { + putchar(' '); + Lit = clause_GetLiteral(Clause, i); + clause_LiteralPrintUnsigned(Lit); + } + fputs(" || ", stdout); + + a += c; + for ( ; i < a; i++) { + + Lit = clause_GetLiteral(Clause, i); + clause_LiteralPrintUnsigned(Lit); + if (clause_LiteralIsMaximal(Lit)) { + putchar('*'); + if (clause_LiteralIsOrientedEquality(Lit)) + putchar('*'); + } + if (clause_LiteralGetFlag(Lit,LITSELECT)) + putchar('+'); + if (i+1 < a) + putchar(' '); + } + fputs(" -> ",stdout); + + s += a; + for ( ; i < s; i++) { + + Lit = clause_GetLiteral(Clause, i); + clause_LiteralPrintUnsigned(Lit); + if (clause_LiteralIsMaximal(Lit)) { + putchar('*'); + if (clause_LiteralIsOrientedEquality(Lit)) + putchar('*'); + } +#ifdef CHECK + if (clause_LiteralGetFlag(Lit,LITSELECT)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_Print: Clause has selected positive literal.\n"); + misc_FinishErrorReport(); + } +#endif + if (i+1 < s) + putchar(' '); + } + putchar('.'); + } +} + + +void clause_PrintMaxLitsOnly(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A Clause, a flag store and a precedence. + RETURNS: Nothing. + SUMMARY: +***************************************************************/ +{ + int i,c,a,s; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_PrinMaxLitsOnly:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + c = clause_NumOfConsLits(Clause); + a = clause_NumOfAnteLits(Clause); + s = clause_NumOfSuccLits(Clause); + + for (i = 0; i < c; i++) { + if (clause_LiteralIsMaximal(clause_GetLiteral(Clause, i))) + clause_LiteralPrint(clause_GetLiteral(Clause, i)); + if (clause_LiteralGetFlag(clause_GetLiteral(Clause, i),STRICTMAXIMAL)) { + clause_LiteralPrint(clause_GetLiteral(Clause, i)); + fputs("(strictly)", stdout); + } + } + fputs(" || ", stdout); + + a += c; + for ( ; i < a; i++) { + if (clause_LiteralIsMaximal(clause_GetLiteral(Clause, i))) + clause_LiteralPrint(clause_GetLiteral(Clause, i)); + if (clause_LiteralGetFlag(clause_GetLiteral(Clause, i),STRICTMAXIMAL)) { + clause_LiteralPrint(clause_GetLiteral(Clause, i)); + fputs("(strictly)", stdout); + } + } + fputs(" -> ", stdout); + + s += a; + for ( ; i < s; i++) { + if (clause_LiteralIsMaximal(clause_GetLiteral(Clause, i))) + clause_LiteralPrint(clause_GetLiteral(Clause, i)); + if (clause_LiteralGetFlag(clause_GetLiteral(Clause, i),STRICTMAXIMAL)) { + clause_LiteralPrint(clause_GetLiteral(Clause, i)); + fputs("(strictly)", stdout); + } + } + puts("."); /* with newline */ +} + + +void clause_FPrint(FILE* File, CLAUSE Clause) +/************************************************************** + INPUT: A file and a clause. + RETURNS: Nothing. + SUMMARY: Prints any clause to the file 'File'. + CAUTION: Uses the term_Output functions. +***************************************************************/ +{ + int i, c, a, s; + + c = clause_NumOfConsLits(Clause); + a = clause_NumOfAnteLits(Clause); + s = clause_NumOfSuccLits(Clause); + + for (i = 0; i < c; i++) + term_FPrint(File, clause_GetLiteralAtom(Clause, i)); + + fputs(" || ", stdout); + + a += c; + for ( ; i < a; i++) + term_FPrint(File, clause_GetLiteralAtom(Clause, i)); + + fputs(" -> ", stdout); + + s += a; + for ( ; i < s; i++) + term_FPrint(File, clause_GetLiteralAtom(Clause, i)); + + putc('.', File); +} + + +void clause_ListPrint(LIST ClauseList) +/************************************************************** + INPUT: A list of clauses. + RETURNS: Nothing. + SUMMARY: Prints the clauses to stdout. + CAUTION: Uses the clause_Print function. +***************************************************************/ +{ + while (!(list_Empty(ClauseList))) { + clause_Print(list_First(ClauseList)); + ClauseList = list_Cdr(ClauseList); + if (!list_Empty(ClauseList)) + putchar('\n'); + } +} + + +void clause_PrintParentClauses(CLAUSE Clause) +/************************************************************** + INPUT: A Clause. + RETURNS: Nothing. + SUMMARY: Prints the clauses parentclauses and -literals to stdout. +***************************************************************/ +{ + LIST Scan1,Scan2; + + if (!list_Empty(clause_ParentClauses(Clause))) { + + Scan1 = clause_ParentClauses(Clause); + Scan2 = clause_ParentLiterals(Clause); + printf("%d.%d", (int)list_Car(Scan1), (int)list_Car(Scan2)); + + for (Scan1 = list_Cdr(Scan1), Scan2 = list_Cdr(Scan2); + !list_Empty(Scan1); + Scan1 = list_Cdr(Scan1), Scan2 = list_Cdr(Scan2)) + printf(",%d.%d", (int)list_Car(Scan1), (int)list_Car(Scan2)); + } +} + + +RULE clause_GetOriginFromString(const char* RuleName) +/************************************************************** + INPUT: A string containing the abbreviated name of a rule. + RETURNS: The RULE corresponding to the <RuleName>. +***************************************************************/ +{ + if (string_Equal(RuleName, "App")) return CLAUSE_DELETION; + else if (string_Equal(RuleName, "EmS")) return EMPTY_SORT; + else if (string_Equal(RuleName, "SoR")) return SORT_RESOLUTION; + else if (string_Equal(RuleName, "EqR")) return EQUALITY_RESOLUTION; + else if (string_Equal(RuleName, "EqF")) return EQUALITY_FACTORING; + else if (string_Equal(RuleName, "MPm")) return MERGING_PARAMODULATION; + else if (string_Equal(RuleName, "SpR")) return SUPERPOSITION_RIGHT; + else if (string_Equal(RuleName, "SPm")) return PARAMODULATION; + else if (string_Equal(RuleName, "OPm")) return ORDERED_PARAMODULATION; + else if (string_Equal(RuleName, "SpL")) return SUPERPOSITION_LEFT; + else if (string_Equal(RuleName, "Res")) return GENERAL_RESOLUTION; + else if (string_Equal(RuleName, "SHy")) return SIMPLE_HYPER; + else if (string_Equal(RuleName, "OHy")) return ORDERED_HYPER; + else if (string_Equal(RuleName, "URR")) return UR_RESOLUTION; + else if (string_Equal(RuleName, "Fac")) return GENERAL_FACTORING; + else if (string_Equal(RuleName, "Spt")) return SPLITTING; + else if (string_Equal(RuleName, "Inp")) return INPUT; + else if (string_Equal(RuleName, "Rew")) return REWRITING; + else if (string_Equal(RuleName, "CRw")) return CONTEXTUAL_REWRITING; + else if (string_Equal(RuleName, "Con")) return CONDENSING; + else if (string_Equal(RuleName, "AED")) return ASSIGNMENT_EQUATION_DELETION; + else if (string_Equal(RuleName, "Obv")) return OBVIOUS_REDUCTIONS; + else if (string_Equal(RuleName, "SSi")) return SORT_SIMPLIFICATION; + else if (string_Equal(RuleName, "MRR")) return MATCHING_REPLACEMENT_RESOLUTION; + else if (string_Equal(RuleName, "UnC")) return UNIT_CONFLICT; + else if (string_Equal(RuleName, "Def")) return DEFAPPLICATION; + else if (string_Equal(RuleName, "Ter")) return TERMINATOR; + else { + misc_StartErrorReport(); + misc_ErrorReport("\nIn clause_GetOriginFromString: Unknown clause origin."); + misc_FinishErrorReport(); + return CLAUSE_DELETION; /* Just for the compiler, code is not reachable */ + } +} + +void clause_FPrintOrigin(FILE* File, CLAUSE Clause) +/************************************************************** + INPUT: A Clause. + RETURNS: Nothing. + SUMMARY: Prints the clause's origin to the file. +***************************************************************/ +{ + RULE Result; + + Result = clause_Origin(Clause); + + switch(Result) { + case CLAUSE_DELETION: fputs("App", File); break; + case EMPTY_SORT: fputs("EmS", File); break; + case SORT_RESOLUTION: fputs("SoR", File); break; + case EQUALITY_RESOLUTION: fputs("EqR", File); break; + case EQUALITY_FACTORING: fputs("EqF", File); break; + case MERGING_PARAMODULATION: fputs("MPm", File); break; + case SUPERPOSITION_RIGHT: fputs("SpR", File); break; + case PARAMODULATION: fputs("SPm", File); break; + case ORDERED_PARAMODULATION: fputs("OPm", File); break; + case SUPERPOSITION_LEFT: fputs("SpL", File); break; + case GENERAL_RESOLUTION: fputs("Res", File); break; + case SIMPLE_HYPER: fputs("SHy", File); break; + case ORDERED_HYPER: fputs("OHy", File); break; + case UR_RESOLUTION: fputs("URR", File); break; + case GENERAL_FACTORING: fputs("Fac", File); break; + case SPLITTING: fputs("Spt", File); break; + case INPUT: fputs("Inp", File); break; + case REWRITING: fputs("Rew", File); break; + case CONTEXTUAL_REWRITING: fputs("CRw", File); break; + case CONDENSING: fputs("Con", File); break; + case ASSIGNMENT_EQUATION_DELETION: fputs("AED", File); break; + case OBVIOUS_REDUCTIONS: fputs("Obv", File); break; + case SORT_SIMPLIFICATION: fputs("SSi", File); break; + case MATCHING_REPLACEMENT_RESOLUTION: fputs("MRR", File); break; + case UNIT_CONFLICT: fputs("UnC", File); break; + case DEFAPPLICATION: fputs("Def", File); break; + case TERMINATOR: fputs("Ter", File); break; + case TEMPORARY: fputs("Temporary", File); break; + default: + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_FPrintOrigin: Clause has no origin."); + misc_FinishErrorReport(); + } +} + + +void clause_PrintOrigin(CLAUSE Clause) +/************************************************************** + INPUT: A Clause. + RETURNS: Nothing. + SUMMARY: Prints the clauses origin to stdout. +***************************************************************/ +{ + clause_FPrintOrigin(stdout, Clause); +} + + +void clause_PrintVerbose(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A Clause, a flag store and a precedence. + RETURNS: Nothing. + SUMMARY: Prints almost all the information kept in the + clause structure. +***************************************************************/ +{ + int c,a,s; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_PrintVerbose:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + c = clause_NumOfConsLits(Clause); + a = clause_NumOfAnteLits(Clause); + s = clause_NumOfSuccLits(Clause); + + printf(" c = %d a = %d s = %d", c,a,s); + printf(" Weight : %d", clause_Weight(Clause)); + printf(" Depth : %d", clause_Depth(Clause)); + printf(" %s %s ", + (clause_GetFlag(Clause,WORKEDOFF) ? "WorkedOff" : "Usable"), + (clause_GetFlag(Clause,CLAUSESELECT) ? "Selected" : "NotSelected")); + + clause_Print(Clause); +} + + +CLAUSE clause_GetNumberedCl(int number, LIST ClList) +/************************************************************** + INPUT: + RETURNS: + CAUTION: +***************************************************************/ +{ + while (!list_Empty(ClList) && + clause_Number((CLAUSE)list_Car(ClList)) != number) + ClList = list_Cdr(ClList); + + if (list_Empty(ClList)) + return NULL; + else + return list_Car(ClList); +} + +static __inline__ BOOL clause_NumberLower(CLAUSE A, CLAUSE B) +{ + return (BOOL) (clause_Number(A) < clause_Number(B)); +} + +LIST clause_NumberSort(LIST List) +/************************************************************** + INPUT: A list of clauses. + RETURNS: The same list where the elements are sorted wrt their number. + CAUTION: Destructive. +***************************************************************/ +{ + return list_Sort(List, (BOOL (*) (POINTER, POINTER)) clause_NumberLower); +} + + +LIST clause_NumberDelete(LIST List, int Number) +/************************************************************** + INPUT: A list of clauses and an integer. + RETURNS: The same list where the clauses with <Number> are deleted. + CAUTION: Destructive. +***************************************************************/ +{ + LIST Scan1,Scan2; + + for (Scan1 = List; !list_Empty(Scan1); ) + if (clause_Number(list_Car(Scan1))==Number) { + + Scan2 = Scan1; + Scan1 = list_Cdr(Scan1); + List = list_PointerDeleteOneElement(List, list_Car(Scan2)); + } else + Scan1 = list_Cdr(Scan1); + + return List; +} + + +static NAT clause_NumberOfMaxLits(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: The number of maximal literals in a clause. +***************************************************************/ +{ + NAT Result,i,n; + + Result = 0; + n = clause_Length(Clause); + + for (i = clause_FirstAntecedentLitIndex(Clause); i < n; i++) + if (clause_LiteralIsMaximal(clause_GetLiteral(Clause,i))) + Result++; + + return Result; +} + +/* Unused ! */ +NAT clause_NumberOfMaxAntecedentLits(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: The number of maximal antecedent literals in a clause. +***************************************************************/ +{ + NAT Result,i,n; + + Result = 0; + n = clause_LastAntecedentLitIndex(Clause); + + for (i = clause_FirstAntecedentLitIndex(Clause); i <= n; i++) + if (clause_LiteralIsMaximal(clause_GetLiteral(Clause,i))) + Result++; + + return Result; +} + + +void clause_SelectLiteral(CLAUSE Clause, FLAGSTORE Flags) +/************************************************************** + INPUT: A clause and a flag store. + RETURNS: Nothing. + EFFECT: If the clause contains more than 2 maximal literals, + at least one antecedent literal, the literal with + the highest weight is selected. +***************************************************************/ +{ + if (clause_HasSolvedConstraint(Clause) && + !clause_GetFlag(Clause,CLAUSESELECT) && + clause_NumOfAnteLits(Clause) > 0 && + (flag_GetFlagValue(Flags, flag_SELECT) == flag_SELECTALWAYS || + (flag_GetFlagValue(Flags, flag_SELECT) == flag_SELECTIFSEVERALMAXIMAL && + clause_NumberOfMaxLits(Clause) > 1))) { + NAT i,n; + LITERAL Lit; + + n = clause_LastAntecedentLitIndex(Clause); + i = clause_FirstAntecedentLitIndex(Clause); + Lit = clause_GetLiteral(Clause,i); + i++; + + for ( ; i <= n; i++) + if (clause_LiteralWeight(Lit) + < clause_LiteralWeight(clause_GetLiteral(Clause,i))) + Lit = clause_GetLiteral(Clause,i); + + clause_LiteralSetFlag(Lit,LITSELECT); + clause_SetFlag(Clause,CLAUSESELECT); + } +} + + +void clause_SetSpecialFlags(CLAUSE Clause, BOOL SortDecreasing, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a flag indicating whether all equations are + sort decreasing, a flag store and a precedence. + RETURNS: void. + EFFECT: If the clause is a sort theory clause and its declaration + top symbol is a set declaration sort, i.e., it occurred in a + declaration right from the beginning, the paramodulation/superposition + steps into the clause are forbidden by setting the + NOPARAINTO clause flag +***************************************************************/ +{ + if (SortDecreasing && + clause_IsSortTheoryClause(Clause, Flags, Precedence) && + symbol_HasProperty(term_TopSymbol(clause_GetLiteralTerm(Clause,clause_FirstSuccedentLitIndex(Clause))), + DECLSORT)) + clause_SetFlag(Clause,NOPARAINTO); +} + + +BOOL clause_ContainsPotPredDef(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence, NAT* Index, LIST* Pair) +/************************************************************** + INPUT: A clause, a flag store, a precedence and a pointer to an index. + RETURNS: TRUE iff a succedent literal of the clause is a predicate + having only variables as arguments, the predicate occurs only + once in the clause and no other variables but the predicates' + occur. + In that case Index is set to the index of the predicate and + Pair contains two lists : the literals for which positive + occurrences must be found and a list of literals for which negative + occurrences must be found for a complete definition. +***************************************************************/ +{ + NAT i; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_ContainsPotPredDef:"); + misc_ErrorReport("\n Illegal input. Input not a clause."); + misc_FinishErrorReport(); + } +#endif + + /* Iterate over all succedent literals */ + for (i=clause_FirstSuccedentLitIndex(Clause); i < clause_Length(Clause); i++) { + LITERAL lit; + TERM atom; + LIST pair; + + lit = clause_GetLiteral(Clause, i); + atom = clause_LiteralSignedAtom(lit); + if (symbol_IsPredicate(term_TopSymbol(atom))) { + LIST l; + BOOL ok; + ok = TRUE; + pair = list_PairCreate(list_Nil(), list_Nil()); + + /* Make sure all arguments of predicate are variables */ + for (l=term_ArgumentList(atom); !list_Empty(l); l=list_Cdr(l)) { + if (!term_IsStandardVariable((TERM) list_Car(l))) { + ok = FALSE; + break; + } + } + if (ok) { + /* Make sure predicate occurs only once in clause */ + NAT j, count; + count = 0; + for (j=0; (j < clause_Length(Clause)) && (count < 2); j++) { + TERM t; + t = clause_GetLiteralAtom(Clause, j); + if (symbol_Equal(term_TopSymbol(t), term_TopSymbol(atom))) + count++; + } + if (count > 1) + ok = FALSE; + } + if (ok) { + /* Build lists of positive and negative literals */ + /* At the same time check if other variables than those among + the predicates arguments are found */ + NAT j; + LIST predvars, vars; + predvars = fol_FreeVariables(atom); + + /* Build list of literals for which positive occurrences are required */ + for (j=0; (j < clause_FirstSuccedentLitIndex(Clause)) && ok; j++) { + list_Rplaca(pair, list_Cons(clause_GetLiteralAtom(Clause, j), list_PairFirst(pair))); + vars = fol_FreeVariables(clause_GetLiteralTerm(Clause, j)); + for (l = vars; !list_Empty(l); l = list_Cdr(l)) { + if (!term_ListContainsTerm(predvars, list_Car(l))) { + ok = FALSE; + break; + } + } + list_Delete(vars); + } + + /* Build list of literals for which negative occurrences are required */ + for (j = clause_FirstSuccedentLitIndex(Clause); + (j < clause_Length(Clause)) && ok; j++) { + if (j != i) { + list_Rplacd(pair, list_Cons(clause_GetLiteralAtom(Clause, j), list_PairSecond(pair))); + vars = fol_FreeVariables(clause_GetLiteralAtom(Clause, j)); + for (l=vars; !list_Empty(l); l=list_Cdr(l)) { + if (!term_ListContainsTerm(predvars, list_Car(l))) { + ok = FALSE; + break; + } + } + list_Delete(vars); + } + } + list_Delete(predvars); + } + + if (ok) { + *Index = i; + *Pair = pair; + return TRUE; + } + else { + list_Delete(list_PairFirst(pair)); + list_Delete(list_PairSecond(pair)); + list_PairFree(pair); + } + } + } + return FALSE; +} + +BOOL clause_IsPartOfDefinition(CLAUSE Clause, TERM Predicate, int *Index, + LIST Pair) +/************************************************************** + INPUT: A clause, a term, a pointer to an int and a pair of term lists. + RETURNS: TRUE iff the predicate occurs among the negative literals of + the clause and the other negative and positive literals are found + in the pairs' lists. + In that case they are removed from the lists. + Index is set to the index of the defined predicate in Clause. +***************************************************************/ +{ + NAT predindex, i; + BOOL ok; + + ok = TRUE; + + /* Check whether Predicate is among antecedent or constraint literals */ + for (predindex=clause_FirstLitIndex(); + predindex < clause_FirstSuccedentLitIndex(Clause); + predindex++) + if (term_Equal(Predicate, clause_GetLiteralAtom(Clause, predindex))) + break; + if (predindex == clause_FirstSuccedentLitIndex(Clause)) + return FALSE; + *Index = predindex; + + /* Check if other negative literals are required for definition */ + for (i=clause_FirstLitIndex(); + (i < clause_FirstSuccedentLitIndex(Clause)) && ok; i++) { + if (i != predindex) + if (!term_ListContainsTerm((LIST) list_PairSecond(Pair), + clause_GetLiteralAtom(Clause, i))) + ok = FALSE; + } + + /* Check if positive literals are required for definition */ + for (i=clause_FirstSuccedentLitIndex(Clause); + (i < clause_Length(Clause)) && ok; i++) + if (!term_ListContainsTerm((LIST) list_PairFirst(Pair), + clause_GetLiteralAtom(Clause, i))) + ok = FALSE; + + if (!ok) + return FALSE; + else { + /* Complement for definition found, remove literals from pair lists */ + for (i=0; i < clause_FirstSuccedentLitIndex(Clause); i++) + if (i != predindex) + list_Rplacd(Pair, + list_DeleteElement((LIST) list_PairSecond(Pair), + clause_GetLiteralAtom(Clause, i), + (BOOL (*)(POINTER, POINTER)) term_Equal)); + for (i=clause_FirstSuccedentLitIndex(Clause); i < clause_Length(Clause); i++) + list_Rplaca(Pair, + list_DeleteElement((LIST) list_PairFirst(Pair), + clause_GetLiteralAtom(Clause, i), + (BOOL (*)(POINTER, POINTER)) term_Equal)); + return TRUE; + } +} + +void clause_FPrintRule(FILE* File, CLAUSE Clause) +/************************************************************** + INPUT: A file and a clause. + RETURNS: Nothing. + SUMMARY: Prints any term of the clause to file in rule format. + CAUTION: Uses the term_Output functions. +***************************************************************/ +{ + int i,n; + TERM Literal; + LIST scan,antecedent,succedent,constraints; + + n = clause_Length(Clause); + + constraints = list_Nil(); + antecedent = list_Nil(); + succedent = list_Nil(); + + for (i = 0; i < n; i++) { + Literal = clause_GetLiteralTerm(Clause,i); + if (symbol_Equal(term_TopSymbol(Literal),fol_Not())) { + if (symbol_Arity(term_TopSymbol(fol_Atom(Literal))) == 1 && + symbol_IsVariable(term_TopSymbol(term_FirstArgument(fol_Atom(Literal))))) + constraints = list_Cons(Literal,constraints); + else + antecedent = list_Cons(Literal,antecedent); + } + else + succedent = list_Cons(Literal,succedent); + } + + for (scan = constraints; !list_Empty(scan); scan = list_Cdr(scan)) { + term_FPrint(File, fol_Atom(list_Car(scan))); + putc(' ', File); + } + fputs("||", File); + for (scan = antecedent; !list_Empty(scan); scan = list_Cdr(scan)) { + putc(' ', File); + term_FPrint(File,fol_Atom(list_Car(scan))); + if (list_Empty(list_Cdr(scan))) + putc(' ', File); + } + fputs("->", File); + for (scan = succedent; !list_Empty(scan); scan = list_Cdr(scan)) { + putc(' ', File); + term_FPrint(File,list_Car(scan)); + } + fputs(".\n", File); + + list_Delete(antecedent); + list_Delete(succedent); + list_Delete(constraints); +} + + +void clause_FPrintOtter(FILE* File, CLAUSE clause) +/************************************************************** + INPUT: A file and a clause. + RETURNS: Nothing. + SUMMARY: Prints any clause to File. + CAUTION: Uses the other clause_Output functions. +***************************************************************/ +{ + int n,j; + LITERAL Lit; + TERM Atom; + + n = clause_Length(clause); + + if (n == 0) + fputs(" $F ", File); + else { + for (j = 0; j < n; j++) { + Lit = clause_GetLiteral(clause,j); + Atom = clause_LiteralAtom(Lit); + if (clause_LiteralIsNegative(Lit)) + putc('-', File); + if (fol_IsEquality(Atom)) { + if (clause_LiteralIsNegative(Lit)) + putc('(', File); + term_FPrintOtterPrefix(File,term_FirstArgument(Atom)); + fputs(" = ", File); + term_FPrintOtterPrefix(File,term_SecondArgument(Atom)); + if (clause_LiteralIsNegative(Lit)) + putc(')', File); + } + else + term_FPrintOtterPrefix(File,Atom); + if (j <= (n-2)) + fputs(" | ", File); + } + } + + fputs(".\n", File); +} + + +void clause_FPrintCnfDFG(FILE* File, BOOL OnlyProductive, LIST Axioms, + LIST Conjectures, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A file, a list of axiom clauses and a list of conjecture clauses. + A flag indicating whether only potentially productive clauses should + be printed. + A flag store. + A precedence. + RETURNS: Nothing. + SUMMARY: Prints a the respective clause lists to <File> dependent + on <OnlyProductive>. +***************************************************************/ +{ + LIST scan; + CLAUSE Clause; + + if (Axioms) { + fputs("list_of_clauses(axioms, cnf).\n", File); + for (scan=Axioms;!list_Empty(scan);scan=list_Cdr(scan)) { + Clause = (CLAUSE)list_Car(scan); + if (!OnlyProductive || + (clause_HasSolvedConstraint(Clause) && + !clause_HasSelectedLiteral(Clause, Flags, Precedence))) + clause_FPrintDFG(File,Clause,FALSE); + } + fputs("end_of_list.\n\n", File); + } + + if (Conjectures) { + fputs("list_of_clauses(conjectures, cnf).\n", File); + for (scan=Conjectures;!list_Empty(scan);scan=list_Cdr(scan)) { + Clause = (CLAUSE)list_Car(scan); + if (!OnlyProductive || + (clause_HasSolvedConstraint(Clause) && + !clause_HasSelectedLiteral(Clause, Flags, Precedence))) + clause_FPrintDFG(File,Clause,FALSE); + } + fputs("end_of_list.\n\n", File); + } +} + + +static void clause_FPrintDescription(FILE* File, const char* Name, + const char* Author, const char* Status, + const char* Description) +{ + fputs("list_of_descriptions.\n", File); + fprintf(File, "name(%s).\n", Name); + fprintf(File, "author(%s).\n", Author); + fprintf(File, "status(%s).\n", Status); + fprintf(File, "description(%s).\n", Description); + fputs("end_of_list.\n", File); +} + +void clause_FPrintCnfDFGProblem(FILE* File, const char* Name, + const char* Author, const char* Status, + const char* Description, LIST Clauses) +/************************************************************** + INPUT: A file, the problems name, author, status and description + to be included in the description block given as strings + and a list of clauses. + RETURNS: Nothing. + SUMMARY: Prints a complete DFG problem clause file to <File>. +***************************************************************/ +{ + LIST Scan; + + fputs("begin_problem(Unknown).\n\n", File); + clause_FPrintDescription(File, Name, Author, Status, Description); + putc('\n', File); + fputs("list_of_symbols.\n", File); + fol_FPrintDFGSignature(File); + fputs("end_of_list.\n\n", File); + fputs("list_of_clauses(axioms, cnf).\n", File); + + for (Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (!clause_GetFlag(list_Car(Scan),CONCLAUSE)) + clause_FPrintDFG(File,list_Car(Scan),FALSE); + + fputs("end_of_list.\n\n", File); + fputs("list_of_clauses(conjectures, cnf).\n", File); + + for (Scan=Clauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) + if (clause_GetFlag(list_Car(Scan),CONCLAUSE)) + clause_FPrintDFG(File,list_Car(Scan),FALSE); + + fputs("end_of_list.\n\n", File); + fputs("\nend_problem.\n\n", File); +} + + +void clause_FPrintCnfFormulasDFGProblem(FILE* File, BOOL OnlyProductive, + const char* Name, const char* Author, + const char* Status, + const char* Description, LIST Axioms, + LIST Conjectures, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A file, a list of axiom clauses and a list of conjecture clauses. + A flag indicating whether only potentially productive clauses should + be printed. + A bunch of strings that are printed to the description. + A flag store. + A precedence. + RETURNS: Nothing. + SUMMARY: Prints the respective clause lists as a complete DFG formulae output + to <File>. +***************************************************************/ +{ + LIST scan; + CLAUSE Clause; + + fputs("begin_problem(Unknown).\n\n", File); + clause_FPrintDescription(File, Name, Author, Status, Description); + fputs("\nlist_of_symbols.\n", File); + fol_FPrintDFGSignature(File); + fputs("end_of_list.\n\n", File); + + if (Axioms) { + fputs("list_of_formulae(axioms).\n", File); + for (scan=Axioms; !list_Empty(scan); scan=list_Cdr(scan)) { + Clause = (CLAUSE)list_Car(scan); + if (!OnlyProductive || + (clause_HasSolvedConstraint(Clause) && + !clause_HasSelectedLiteral(Clause, Flags, Precedence))) + clause_FPrintFormulaDFG(File,Clause,FALSE); + } + fputs("end_of_list.\n\n", File); + } + + if (Conjectures) { + fputs("list_of_formulae(conjectures).\n", File); + for (scan=Conjectures; !list_Empty(scan); scan=list_Cdr(scan)) { + Clause = (CLAUSE)list_Car(scan); + if (!OnlyProductive || + (clause_HasSolvedConstraint(Clause) && + !clause_HasSelectedLiteral(Clause, Flags, Precedence))) + clause_FPrintFormulaDFG(File,Clause,FALSE); + } + fputs("end_of_list.\n\n", File); + } + + fputs("list_of_settings(SPASS).\n{*\n", File); + fol_FPrintPrecedence(File, Precedence); + fputs("\n*}\nend_of_list.\n\nend_problem.\n\n", File); +} + +void clause_FPrintCnfOtter(FILE* File, LIST Clauses, FLAGSTORE Flags) +/************************************************************** + INPUT: A file, a list of clauses and a flag store. + RETURNS: Nothing. + SUMMARY: Prints the clauses to <File> in a format readable by Otter. +***************************************************************/ +{ + LIST scan; + int i; + BOOL Equality; + CLAUSE Clause; + + Equality = FALSE; + + for (scan=Clauses;!list_Empty(scan) && !Equality; scan=list_Cdr(scan)) { + Clause = (CLAUSE)list_Car(scan); + for (i=clause_FirstAntecedentLitIndex(Clause);i<clause_Length(Clause);i++) + if (fol_IsEquality(clause_GetLiteralAtom(Clause,i))) { + Equality = TRUE; + i = clause_Length(Clause); + } + } + + fol_FPrintOtterOptions(File, Equality, + flag_GetFlagValue(Flags, flag_TDFG2OTTEROPTIONS)); + + if (Clauses) { + fputs("list(usable).\n", File); + if (Equality) + fputs("x=x.\n", File); + for (scan=Clauses;!list_Empty(scan);scan=list_Cdr(scan)) + clause_FPrintOtter(File,list_Car(scan)); + fputs("end_of_list.\n\n", File); + } +} + + +void clause_FPrintCnfDFGDerivables(FILE* File, LIST Clauses, BOOL Type) +/************************************************************** + INPUT: A file, a list of clauses and a bool flag Type. + RETURNS: Nothing. + SUMMARY: If <Type> is true then all axiom clauses in <Clauses> are + written to <File>. Otherwise all conjecture clauses in + <Clauses> are written to <File>. +***************************************************************/ +{ + CLAUSE Clause; + + while (Clauses) { + Clause = (CLAUSE)list_Car(Clauses); + if ((Type && !clause_GetFlag(Clause,CONCLAUSE)) || + (!Type && clause_GetFlag(Clause,CONCLAUSE))) + clause_FPrintDFG(File,Clause,FALSE); + Clauses = list_Cdr(Clauses); + } +} + + +void clause_FPrintDFGStep(FILE* File, CLAUSE Clause, BOOL Justif) +/************************************************************** + INPUT: A file, a clause and a boolean value. + RETURNS: Nothing. + SUMMARY: Prints any clause together with a label (the clause number) + to File. If <Justif> is TRUE also the labels of the parent + clauses are printed. + CAUTION: Uses the other clause_Output functions. +***************************************************************/ +{ + int n,j; + LITERAL Lit; + TERM Atom; + LIST Variables,Iter; + + n = clause_Length(Clause); + + fputs(" step(", File); + fprintf(File, "%d,", clause_Number(Clause)); + + Variables = list_Nil(); + + for (j = 0; j < n; j++) + Variables = + list_NPointerUnion(Variables, + term_VariableSymbols(clause_GetLiteralAtom(Clause,j))); + + if (!list_Empty(Variables)) { + symbol_FPrint(File, fol_All()); + fputs("([", File); + for (Iter = Variables; !list_Empty(Iter); Iter = list_Cdr(Iter)) { + symbol_FPrint(File, (SYMBOL) list_Car(Iter)); + if (!list_Empty(list_Cdr(Iter))) + putc(',', File); + } + fputs("],", File); + } + + symbol_FPrint(File, fol_Or()); + putc('(', File); + + for (j = 0; j < n; j++) { + Lit = clause_GetLiteral(Clause,j); + Atom = clause_LiteralSignedAtom(Lit); + term_FPrintPrefix(File,Atom); + if (j+1 < n) + putc(',', File); + } + if (n==0) + symbol_FPrint(File,fol_False()); + + if (!list_Empty(Variables)) { + list_Delete(Variables); + putc(')', File); + } + fputs("),", File); + clause_FPrintOrigin(File, Clause); + + fputs(",[", File); + for (Iter = clause_ParentClauses(Clause); + !list_Empty(Iter); + Iter = list_Cdr(Iter)) { + fprintf(File, "%d", (int)list_Car(Iter)); + if (!list_Empty(list_Cdr(Iter))) + putc(',', File); + } + putc(']', File); + fprintf(File, ",[splitlevel:%d]", clause_SplitLevel(Clause)); + + fputs(").\n", File); +} + +void clause_FPrintDFG(FILE* File, CLAUSE Clause, BOOL Justif) +/************************************************************** + INPUT: A file, a clause and a boolean value. + RETURNS: Nothing. + SUMMARY: Prints any clause together with a label (the clause number) + to File. If Justif is TRUE also the labels of the parent + clauses are printed. + CAUTION: Uses the other clause_Output functions. +***************************************************************/ +{ + int n,j; + LITERAL Lit; + TERM Atom; + LIST Variables,Iter; + + n = clause_Length(Clause); + + fputs(" clause(", File); + Variables = list_Nil(); + + for (j = 0; j < n; j++) + Variables = + list_NPointerUnion(Variables, + term_VariableSymbols(clause_GetLiteralAtom(Clause,j))); + + if (!list_Empty(Variables)) { + symbol_FPrint(File, fol_All()); + fputs("([", File); + for (Iter = Variables; !list_Empty(Iter); Iter = list_Cdr(Iter)) { + symbol_FPrint(File, (SYMBOL) list_Car(Iter)); + if (!list_Empty(list_Cdr(Iter))) + putc(',', File); + } + fputs("],", File); + } + + symbol_FPrint(File, fol_Or()); + putc('(', File); + + for (j = 0; j < n; j++) { + Lit = clause_GetLiteral(Clause,j); + Atom = clause_LiteralSignedAtom(Lit); + term_FPrintPrefix(File,Atom); + if (j+1 < n) + putc(',', File); + } + if (n==0) + symbol_FPrint(File,fol_False()); + + if (!list_Empty(Variables)) { + list_Delete(Variables); + putc(')', File); + } + fprintf(File, "),%d", clause_Number(Clause)); + + if (Justif) { + putc(',', File); + clause_FPrintOrigin(File, Clause); + fputs(",[", File); + for (Iter = clause_ParentClauses(Clause); + !list_Empty(Iter); + Iter = list_Cdr(Iter)) { + fprintf(File, "%d", (int)list_Car(Iter)); + if (!list_Empty(list_Cdr(Iter))) + putc(',', File); + } + putc(']', File); + fprintf(File, ",%d", clause_SplitLevel(Clause)); + } + + fputs(").\n", File); +} + +void clause_FPrintFormulaDFG(FILE* File, CLAUSE Clause, BOOL Justif) +/************************************************************** + INPUT: A file, a clause and a boolean value. + RETURNS: Nothing. + SUMMARY: Prints any clause together with a label (the clause number) + as DFG Formula to File. If Justif is TRUE also the labels of the + parent clauses are printed. + CAUTION: Uses the other clause_Output functions. +***************************************************************/ +{ + int n,j; + LITERAL Lit; + TERM Atom; + LIST Variables,Iter; + + n = clause_Length(Clause); + + fputs(" formula(", File); + Variables = list_Nil(); + + for (j = 0; j < n; j++) + Variables = + list_NPointerUnion(Variables, + term_VariableSymbols(clause_GetLiteralAtom(Clause,j))); + + if (!list_Empty(Variables)) { + symbol_FPrint(File, fol_All()); + fputs("([", File); + for (Iter = Variables; !list_Empty(Iter); Iter = list_Cdr(Iter)) { + symbol_FPrint(File, (SYMBOL) list_Car(Iter)); + if (!list_Empty(list_Cdr(Iter))) + putc(',', File); + } + fputs("],", File); + } + + if (n>1) { + symbol_FPrint(File, fol_Or()); + putc('(', File); + } + + for (j = 0; j < n; j++) { + Lit = clause_GetLiteral(Clause,j); + Atom = clause_LiteralSignedAtom(Lit); + term_FPrintPrefix(File,Atom); + if (j+1 < n) + putc(',', File); + } + if (n==0) + symbol_FPrint(File,fol_False()); + + if (!list_Empty(Variables)) { + list_Delete(Variables); + putc(')', File); + } + + if (n>1) + fprintf(File, "),%d", clause_Number(Clause)); + else + fprintf(File, ",%d", clause_Number(Clause)); + + if (Justif) { + putc(',', File); + clause_FPrintOrigin(File, Clause); + fputs(",[", File); + for (Iter = clause_ParentClauses(Clause); + !list_Empty(Iter); + Iter = list_Cdr(Iter)) { + fprintf(File, "%d", (int)list_Car(Iter)); + if (!list_Empty(list_Cdr(Iter))) + putc(',', File); + } + putc(']', File); + fprintf(File, ",%d", clause_SplitLevel(Clause)); + } + + fputs(").\n", File); +} + + +void clause_Check(CLAUSE Clause, FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a flag store and a precedence. + RETURNS: Nothing. + EFFECT: Checks whether the clause is in a proper state. If + not, a core is dumped. +***************************************************************/ +{ + CLAUSE Copy; + if (!clause_Exists(Clause)) + return; + + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_Check: Clause not consistent !\n"); + misc_FinishErrorReport(); + } + + Copy = clause_Copy(Clause); + clause_OrientAndReInit(Copy, Flags, Precedence); + if ((clause_Weight(Clause) != clause_Weight(Copy)) || + (clause_MaxVar(Clause) != clause_MaxVar(Copy))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_Check: Weight or maximal variable not properly set.\n"); + misc_FinishErrorReport(); + } + clause_Delete(Copy); +} + +/* The following are output procedures for clauses with parent pointers */ + + +void clause_PParentsFPrintParentClauses(FILE* File, CLAUSE Clause, BOOL ParentPts) +/************************************************************** + INPUT: A file, a clause and a boolean flag indicating whether + the clause's parents are given by numbers or pointers. + RETURNS: Nothing. + SUMMARY: Prints the clauses parent clauses and -literals to the file. + If <ParentPts> is TRUE the parent clauses are defined + by pointers, else by numbers. +***************************************************************/ +{ + LIST Scan1,Scan2; + int length; + int ParentNum; + + if (!list_Empty(clause_ParentClauses(Clause))) { + + Scan1 = clause_ParentClauses(Clause); + Scan2 = clause_ParentLiterals(Clause); + + if (ParentPts) + ParentNum = clause_Number(list_Car(Scan1)); + else + ParentNum = (int)list_Car(Scan1); + + fprintf(File, "%d.%d", ParentNum, (int)list_Car(Scan2)); + + if (!list_Empty(list_Cdr(Scan1))) { + + length = list_Length(Scan1) - 2; + putc(',', File); + Scan1 = list_Cdr(Scan1); + Scan2 = list_Cdr(Scan2); + + if (ParentPts) + ParentNum = clause_Number(list_Car(Scan1)); + else + ParentNum = (int)list_Car(Scan1); + + fprintf(File, "%d.%d", ParentNum, (int)list_Car(Scan2)); + + for (Scan1 = list_Cdr(Scan1), Scan2 = list_Cdr(Scan2); + !list_Empty(Scan1); + Scan1 = list_Cdr(Scan1), Scan2 = list_Cdr(Scan2)) { + + length -= 2; + + if (ParentPts) + ParentNum = clause_Number(list_Car(Scan1)); + else + ParentNum = (int)list_Car(Scan1); + + fprintf(File, ",%d.%d", ParentNum, (int)list_Car(Scan2)); + } + } + } +} + +void clause_PParentsLiteralFPrintUnsigned(FILE* File, LITERAL Literal) +/************************************************************** + INPUT: A Literal. + RETURNS: Nothing. + SUMMARY: +***************************************************************/ +{ +#ifdef CHECK + if (!clause_LiteralIsLiteral(Literal)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_PParentsLiteralFPrintUnsigned:"); + misc_ErrorReport("\n Illegal input. Input not a literal."); + misc_FinishErrorReport(); + } +#endif + + term_FPrintPrefix(File, clause_LiteralAtom(Literal)); + fflush(stdout); +} + +void clause_PParentsFPrintGen(FILE* File, CLAUSE Clause, BOOL ParentPts) +/************************************************************** + INPUT: A file, a clause, a boolean flag. + RETURNS: Nothing. + EFFECTS: Prints the clause to file in SPASS format. If <ParentPts> + is TRUE, the parents of <Clause> are interpreted as pointers. +***************************************************************/ +{ + LITERAL Lit; + int i,c,a,s; + + if (!clause_Exists(Clause)) + fputs("(CLAUSE)NULL", File); + else { + fprintf(File, "%d",clause_Number(Clause)); + + fprintf(File, "[%d:", clause_SplitLevel(Clause)); + +#ifdef CHECK + if (Clause->splitfield_length <= 1) + fputs("0.", File); + else + for (i=Clause->splitfield_length-1; i > 0; i--) + fprintf(File, "%lu.", Clause->splitfield[i]); + if (Clause->splitfield_length == 0) + putc('1', File); + else + fprintf(File, "%lu", (Clause->splitfield[0] | 1)); + fprintf(File,":%c%c:%c:%d:%d:", clause_GetFlag(Clause, CONCLAUSE) ? 'C' : 'A', + clause_GetFlag(Clause, WORKEDOFF) ? 'W' : 'U', + clause_GetFlag(Clause, NOPARAINTO) ? 'N' : 'P', + clause_Weight(Clause), clause_Depth(Clause)); +#endif + + clause_FPrintOrigin(File, Clause); + + if (!list_Empty(clause_ParentClauses(Clause))) { + putc(':', File); + clause_PParentsFPrintParentClauses(File, Clause, ParentPts); + } + putc(']', File); + + c = clause_NumOfConsLits(Clause); + a = clause_NumOfAnteLits(Clause); + s = clause_NumOfSuccLits(Clause); + + for (i = 0; i < c; i++) { + Lit = clause_GetLiteral(Clause, i); + clause_PParentsLiteralFPrintUnsigned(File, Lit); + if (i+1 < c) + putc(' ', File); + } + fputs(" || ", File); + + a += c; + for ( ; i < a; i++) { + + Lit = clause_GetLiteral(Clause, i); + clause_PParentsLiteralFPrintUnsigned(File, Lit); + if (clause_LiteralIsMaximal(Lit)) { + putc('*', File); + if (clause_LiteralIsOrientedEquality(Lit)) + putc('*', File); + } + if (clause_LiteralGetFlag(Lit,LITSELECT)) + putc('+', File); + if (i+1 < a) + putc(' ', File); + } + fputs(" -> ",File); + + s += a; + for ( ; i < s; i++) { + + Lit = clause_GetLiteral(Clause, i); + clause_PParentsLiteralFPrintUnsigned(File, Lit); + if (clause_LiteralIsMaximal(Lit)) { + putc('*', File); + if (clause_LiteralIsOrientedEquality(Lit)) + putc('*', File); + } +#ifdef CHECK + if (clause_LiteralGetFlag(Lit, LITSELECT)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_PParentsFPrintGen: Clause has selected positive literal.\n"); + misc_FinishErrorReport(); + } +#endif + if (i+1 < s) + putc(' ', File); + } + putc('.', File); + } +} + +void clause_PParentsFPrint(FILE* File, CLAUSE Clause) +/************************************************************** + INPUT: A file handle and a clause. + RETURNS: Nothing. + EFFECTS: Prints out the clause to file in SPASS output format +***************************************************************/ +{ + clause_PParentsFPrintGen(File, Clause, TRUE); +} + +void clause_PParentsListFPrint(FILE* File, LIST L) +/************************************************************** + INPUT: A file handle, a list of clauses with parent pointers + RETURNS: Nothing. + EFFECTS: Print the list to <file>. +***************************************************************/ +{ + while (!list_Empty(L)) { + clause_PParentsFPrint(File, list_Car(L)); + putc('\n', File); + L = list_Cdr(L); + } +} + + +void clause_PParentsPrint(CLAUSE Clause) +/************************************************************** + INPUT: A clause with parent pointers + RETURNS: Nothing. + EFFECTS: The clause is printed to stdout. +***************************************************************/ +{ + clause_PParentsFPrint(stdout, Clause); +} + +void clause_PParentsListPrint(LIST L) +/************************************************************** + INPUT: A file handle, a list of clauses with parent pointers + RETURNS: Nothing. + EFFECTS: Print the clause list to stdout. +***************************************************************/ +{ + clause_PParentsListFPrint(stdout, L); +} diff --git a/test/spass/clause.h b/test/spass/clause.h new file mode 100644 index 0000000000000000000000000000000000000000..d163d35d614128479c88eb1a9774a0aedefc96d8 --- /dev/null +++ b/test/spass/clause.h @@ -0,0 +1,1589 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CLAUSES * */ +/* * * */ +/* * $Module: CLAUSE * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _CLAUSE_ +#define _CLAUSE_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "sharing.h" +#include "foldfg.h" +#include "order.h" +#include "subst.h" +#include "flags.h" +#include "symbol.h" + +/**************************************************************/ +/* Data Structures and Constants */ +/**************************************************************/ + +/* Means weight of literal or clause is undefined */ +extern const NAT clause_WEIGHTUNDEFINED; + +extern int clause_CLAUSECOUNTER; + +typedef enum {MAXIMAL=1, STRICTMAXIMAL=2, LITSELECT=4} MAXFLAG; + +typedef enum {CLAUSE_DELETION, EMPTY_SORT, SORT_RESOLUTION, + EQUALITY_RESOLUTION, EQUALITY_FACTORING, MERGING_PARAMODULATION, + PARAMODULATION, ORDERED_PARAMODULATION, + SUPERPOSITION_RIGHT, SUPERPOSITION_LEFT, + SIMPLE_HYPER, ORDERED_HYPER, UR_RESOLUTION, + GENERAL_RESOLUTION, GENERAL_FACTORING, SPLITTING, INPUT, + CONDENSING, ASSIGNMENT_EQUATION_DELETION, OBVIOUS_REDUCTIONS, + SORT_SIMPLIFICATION, REWRITING, CONTEXTUAL_REWRITING, + MATCHING_REPLACEMENT_RESOLUTION, UNIT_CONFLICT, DEFAPPLICATION, + TERMINATOR, TEMPORARY +} RULE; + +typedef unsigned long SPLITFIELDENTRY; +typedef SPLITFIELDENTRY* SPLITFIELD; + +typedef enum {WORKEDOFF=1,CLAUSESELECT=2,DOCCLAUSE=4,CONCLAUSE=8,BLOCKED=16, + NOPARAINTO=32, MARKED=64, HIDDEN=128} CLAUSE_FLAGS; + + +/* As there are a lot of implications a clauses properties may have */ +/* for the prover, this information should be kept with the clause. */ +/* That for a flagfield is foreseen, most likely an integer used */ +/* like the sort-Bitfield existing for term, now used for varoccs. */ + +typedef struct CLAUSE_HELP{ + int clausenumber; + NAT weight; /* The sum of the weight of all literals */ + NAT depth; /* The depth of the clause in the derivation */ + NAT validlevel; /* Level of splitting where clause is valid. */ + SPLITFIELD splitfield; + unsigned splitfield_length; + + LIST parentCls, parentLits; /* Parents clauses' clause and lit numbers.*/ + NAT flags; + SYMBOL maxVar; /* The maximal variable symbol in the clause */ + struct LITERAL_HELP{ + NAT maxLit; /* for clause intern literal ordering */ + NAT weight; /* weight of the <atomWithSign> below */ + BOOL oriented; /* Flag, TRUE if clause is oriented, i.e. equalities + with bigger first arg and all other predicates */ + struct CLAUSE_HELP *owningClause; + TERM atomWithSign; /* Pointer to the term, where an unshared + Term for the sign of negative literals + is supplied additionally. */ + } **literals; /* An Array of (c+a+s) literalpointers in this order. */ + int c; /* number of constraint literals */ + int a; /* number of antecedent literals */ + int s; /* number of succedent literals */ + RULE origin; +} *CLAUSE, CLAUSE_NODE; + +typedef struct LITERAL_HELP *LITERAL, LITERAL_NODE; + + +/**************************************************************/ +/* Functions Prototypes */ +/**************************************************************/ + +/**************************************************************/ +/* Functions on clauses and literals creation and deletion. */ +/**************************************************************/ + +void clause_Init(void); + +CLAUSE clause_CreateBody(int); +CLAUSE clause_Create(LIST, LIST, LIST, FLAGSTORE, PRECEDENCE); +CLAUSE clause_CreateCrude(LIST, LIST, LIST, BOOL); +CLAUSE clause_CreateUnnormalized(LIST, LIST, LIST); +CLAUSE clause_CreateFromLiterals(LIST, BOOL, BOOL, BOOL, FLAGSTORE, PRECEDENCE); +void clause_Delete(CLAUSE); + +LITERAL clause_LiteralCreate(TERM, CLAUSE); +LITERAL clause_LiteralCreateNegative(TERM, CLAUSE); /* Unused */ +void clause_LiteralDelete(LITERAL); + +LIST clause_CopyConstraint(CLAUSE); +LIST clause_CopyAntecedentExcept(CLAUSE, int); +LIST clause_CopySuccedent(CLAUSE); +LIST clause_CopySuccedentExcept(CLAUSE, int); + + +/**************************************************************/ +/* Functions to use the sharing for clauses and literals. */ +/**************************************************************/ + +void clause_InsertIntoSharing(CLAUSE, SHARED_INDEX, FLAGSTORE, PRECEDENCE); +void clause_DeleteFromSharing(CLAUSE, SHARED_INDEX, FLAGSTORE, PRECEDENCE); + +void clause_MakeUnshared(CLAUSE, SHARED_INDEX); +void clause_MoveSharedClause(CLAUSE, SHARED_INDEX, SHARED_INDEX, FLAGSTORE, PRECEDENCE); +void clause_DeleteSharedLiteral(CLAUSE, int, SHARED_INDEX, FLAGSTORE, PRECEDENCE); + +void clause_LiteralInsertIntoSharing(LITERAL, SHARED_INDEX); +void clause_LiteralDeleteFromSharing(LITERAL, SHARED_INDEX); /* Used only in clause.c */ + +void clause_DeleteClauseList(LIST); +void clause_DeleteSharedClauseList(LIST, SHARED_INDEX, FLAGSTORE, PRECEDENCE); +void clause_DeleteAllIndexedClauses(SHARED_INDEX, FLAGSTORE, PRECEDENCE); /* Necessary? */ +void clause_PrintAllIndexedClauses(SHARED_INDEX); /* For Debugging */ +LIST clause_AllIndexedClauses(SHARED_INDEX); + +/**************************************************************/ +/* Clause Comparisons */ +/**************************************************************/ + +BOOL clause_IsHornClause(CLAUSE); +int clause_CompareAbstract(CLAUSE, CLAUSE); + +/**************************************************************/ +/* Clause and literal Input and Output Functions */ +/**************************************************************/ + +void clause_Print(CLAUSE); +void clause_PrintVerbose(CLAUSE, FLAGSTORE, PRECEDENCE); +void clause_PrintMaxLitsOnly(CLAUSE, FLAGSTORE, PRECEDENCE); /* For Debugging */ +void clause_FPrint(FILE*, CLAUSE); /* For Debugging */ +void clause_FPrintRule(FILE*, CLAUSE); +void clause_FPrintOtter(FILE*, CLAUSE); /* Unused */ +void clause_FPrintCnfDFG(FILE* , BOOL, LIST, LIST, FLAGSTORE, PRECEDENCE); +void clause_FPrintCnfDFGProblem(FILE* , const char*, const char*, const char*, const char*, LIST); +void clause_FPrintCnfFormulasDFGProblem(FILE* , BOOL, const char*, const char*, const char*, const char*, LIST, LIST, FLAGSTORE, PRECEDENCE); +void clause_FPrintCnfDFGDerivables(FILE*, LIST, BOOL); +void clause_FPrintDFG(FILE*, CLAUSE, BOOL); +void clause_FPrintDFGStep(FILE*, CLAUSE, BOOL); +void clause_FPrintFormulaDFG(FILE*, CLAUSE, BOOL); +void clause_FPrintCnfOtter(FILE*, LIST, FLAGSTORE); + +void clause_LiteralPrint(LITERAL); /* For Debugging */ +void clause_LiteralListPrint(LIST); /* For Debugging */ +void clause_LiteralPrintUnsigned(LITERAL); /* For Debugging */ +void clause_LiteralPrintSigned(LITERAL); /* For Debugging */ +void clause_LiteralFPrint(FILE*, LITERAL); /* For Debugging */ + +void clause_ListPrint(LIST); + +void clause_PrintParentClauses(CLAUSE); /* For Debugging */ +void clause_PrintOrigin(CLAUSE); /* For Debugging */ +void clause_FPrintOrigin(FILE*, CLAUSE); + +/**************************************************************/ +/* Specials */ +/**************************************************************/ + +CLAUSE clause_Copy(CLAUSE); +LITERAL clause_LiteralCopy(LITERAL); + +static __inline__ LIST clause_CopyClauseList(LIST List) +{ + return list_CopyWithElement(List, (POINTER (*)(POINTER)) clause_Copy); +} + +void clause_DeleteLiteral(CLAUSE, int, FLAGSTORE, PRECEDENCE); +void clause_DeleteLiteralNN(CLAUSE, int); +void clause_DeleteLiterals(CLAUSE, LIST, FLAGSTORE, PRECEDENCE); /* Unused */ +LIST clause_GetLiteralSubSetList(CLAUSE, int, int, FLAGSTORE, PRECEDENCE); +void clause_ReplaceLiteralSubSet(CLAUSE, int, int, LIST, FLAGSTORE, PRECEDENCE); +void clause_FixLiteralOrder(CLAUSE, FLAGSTORE, PRECEDENCE); + +SYMBOL clause_AtomMaxVar(TERM); +void clause_SetMaxLitFlags(CLAUSE, FLAGSTORE, PRECEDENCE); +SYMBOL clause_LiteralMaxVar(LITERAL); /* Used only in clause.c */ +SYMBOL clause_SearchMaxVar(CLAUSE); +void clause_UpdateMaxVar(CLAUSE); + +void clause_RenameVarsBiggerThan(CLAUSE, SYMBOL); +void clause_Normalize(CLAUSE); +void clause_SetSortConstraint(CLAUSE, BOOL, FLAGSTORE, PRECEDENCE); +void clause_SubstApply(SUBST, CLAUSE); +void clause_ReplaceVariable(CLAUSE, SYMBOL, TERM); +void clause_OrientEqualities(CLAUSE, FLAGSTORE, PRECEDENCE); +NAT clause_NumberOfVarOccs(CLAUSE); +NAT clause_NumberOfSymbolOccurrences(CLAUSE, SYMBOL); +NAT clause_ComputeWeight(CLAUSE, FLAGSTORE); +NAT clause_LiteralComputeWeight(LITERAL, FLAGSTORE); +NAT clause_ComputeTermDepth(CLAUSE); +NAT clause_MaxTermDepthClauseList(LIST); +NAT clause_ComputeSize(CLAUSE); +BOOL clause_WeightCorrect(CLAUSE, FLAGSTORE, PRECEDENCE); /* Unused */ + +LIST clause_MoveBestLiteralToFront(LIST, SUBST, SYMBOL, + BOOL (*)(LITERAL, NAT, LITERAL, NAT)); + + +LIST clause_InsertWeighed(CLAUSE, LIST, FLAGSTORE, PRECEDENCE); +LIST clause_ListSortWeighed(LIST); + +BOOL clause_HasTermSortConstraintLits(CLAUSE); +BOOL clause_HasSolvedConstraint(CLAUSE); +BOOL clause_IsDeclarationClause(CLAUSE); +BOOL clause_IsSortTheoryClause(CLAUSE, FLAGSTORE, PRECEDENCE); +BOOL clause_IsPartOfDefinition(CLAUSE, TERM, int*, LIST); +BOOL clause_IsPotentialSortTheoryClause(CLAUSE, FLAGSTORE, PRECEDENCE); +BOOL clause_HasOnlyVarsInConstraint(CLAUSE, FLAGSTORE, PRECEDENCE); +BOOL clause_HasSortInSuccedent(CLAUSE, FLAGSTORE, PRECEDENCE); +BOOL clause_ContainsPotPredDef(CLAUSE, FLAGSTORE, PRECEDENCE, NAT*, LIST*); +BOOL clause_LitsHaveCommonVar(LITERAL, LITERAL); + +void clause_SelectLiteral(CLAUSE, FLAGSTORE); +void clause_SetSpecialFlags(CLAUSE,BOOL, FLAGSTORE, PRECEDENCE); + +BOOL clause_LiteralIsLiteral(LITERAL); +BOOL clause_IsClause(CLAUSE, FLAGSTORE, PRECEDENCE); +BOOL clause_IsUnorderedClause(CLAUSE); +BOOL clause_ContainsPositiveEquations(CLAUSE); +BOOL clause_ContainsNegativeEquations(CLAUSE); +int clause_ContainsFolAtom(CLAUSE,BOOL*,BOOL*,BOOL*,BOOL*); +BOOL clause_ContainsVariables(CLAUSE); +BOOL clause_ContainsFunctions(CLAUSE); +BOOL clause_ContainsSymbol(CLAUSE, SYMBOL); +void clause_ContainsSortRestriction(CLAUSE,BOOL*,BOOL*); +BOOL clause_ImpliesFiniteDomain(CLAUSE); +BOOL clause_ImpliesNonTrivialDomain(CLAUSE); +LIST clause_FiniteMonadicPredicates(LIST); + +CLAUSE clause_GetNumberedCl(int, LIST); +LIST clause_NumberSort(LIST); +LIST clause_NumberDelete(LIST,int); +void clause_Check(CLAUSE, FLAGSTORE, PRECEDENCE); + +void clause_DeleteFlatFromIndex(CLAUSE, st_INDEX); +void clause_InsertFlatIntoIndex(CLAUSE, st_INDEX); +void clause_DeleteClauseListFlatFromIndex(LIST, st_INDEX); + +RULE clause_GetOriginFromString(const char*); + +void clause_CountSymbols(CLAUSE); + +LIST clause_ListOfPredicates(CLAUSE); +LIST clause_ListOfConstants(CLAUSE); +LIST clause_ListOfVariables(CLAUSE); +LIST clause_ListOfFunctions(CLAUSE); + +/* special output functions for clauses with parent pointers */ +void clause_PParentsFPrint(FILE*, CLAUSE); +void clause_PParentsListFPrint(FILE*, LIST L); +void clause_PParentsPrint(CLAUSE); +void clause_PParentsListPrint(LIST); +void clause_PParentsFPrintGen(FILE*, CLAUSE, BOOL); + + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +/**************************************************************/ +/* Accessing Literals 1 */ +/**************************************************************/ + +static __inline__ TERM clause_LiteralSignedAtom(LITERAL L) +{ + return L->atomWithSign; +} + + +static __inline__ CLAUSE clause_LiteralOwningClause(LITERAL L) +{ + return L->owningClause; +} + +static __inline__ void clause_LiteralSetOwningClause(LITERAL L, CLAUSE C) +{ + L->owningClause = C; +} + + +static __inline__ void clause_LiteralSetOrientedEquality(LITERAL L) +{ + L->oriented = TRUE; +} + +static __inline__ void clause_LiteralSetNoOrientedEquality(LITERAL L) +{ + L->oriented = FALSE; +} + + +static __inline__ NAT clause_LiteralWeight(LITERAL L) +{ +#ifdef CHECK + if (L->weight == clause_WEIGHTUNDEFINED) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_LiteralWeight:"); + misc_ErrorReport(" Tried to access undefined weight."); + misc_FinishErrorReport(); + } +#endif + return L->weight; +} + + +static __inline__ void clause_UpdateLiteralWeight(LITERAL L, FLAGSTORE Flags) +{ + L->weight = clause_LiteralComputeWeight(L, Flags); +} + + +static __inline__ void clause_LiteralFlagReset(LITERAL L) +{ + L->maxLit = 0; +} + +static __inline__ BOOL clause_LiteralGetFlag(LITERAL L, MAXFLAG Flag) +{ + return ((L->maxLit & Flag) != 0); +} + +static __inline__ void clause_LiteralSetFlag(LITERAL L, MAXFLAG Flag) +{ + L->maxLit = (L->maxLit) | Flag; +} + +static __inline__ BOOL clause_LiteralIsMaximal(LITERAL L) +{ + return clause_LiteralGetFlag(L, MAXIMAL); +} + + + +static __inline__ BOOL clause_LiteralIsOrientedEquality(LITERAL L) +{ + return L->oriented; +} + + +static __inline__ BOOL clause_LiteralIsNotOrientedEquality(LITERAL L) +{ + return !(L->oriented); +} + + +/**************************************************************/ +/* Literal Comparison 1 */ +/**************************************************************/ + +static __inline__ BOOL clause_LiteralIsNegative(LITERAL L) +{ + return (term_TopSymbol(clause_LiteralSignedAtom(L)) == fol_Not()); +} + +static __inline__ BOOL clause_LiteralIsPositive(LITERAL L) +{ + return !clause_LiteralIsNegative(L); +} + + +static __inline__ BOOL clause_LiteralsAreComplementary(LITERAL L1, LITERAL L2) +{ + return ((clause_LiteralIsNegative(L1) && + clause_LiteralIsPositive(L2)) || + (clause_LiteralIsNegative(L2) && + clause_LiteralIsPositive(L1))); /* xor */ +} + +static __inline__ BOOL clause_HyperLiteralIsBetter(LITERAL Dummy1, NAT S1, + LITERAL Dummy2, NAT S2) +/************************************************************** + INPUT: Two literals and its sizes wrt. some substitution. + RETURNS: TRUE, if the first literal is 'better' than the second literal, + FALSE otherwise. + EFFECT: A literal is 'better' than another, if S1 > Ss. + Since we have to find unifiable complementary literals + for every remaining antecedent literal, it seems to be + a good idea to try the most 'difficult' literal first, + in order to stop the search as early as possible.. + Here we prefer the literal with the highest number + of symbols.. + This function is used as parameter for the function + clause_MoveBestLiteralToFront. + CAUTION: The parameters <Dummy1> and <Dummy2> are unused, they're just + added to keep the compiler quiet. +***************************************************************/ +{ + return (S1 > S2); +} + + +/**************************************************************/ +/* Accessing Literals 2 */ +/**************************************************************/ + +static __inline__ TERM clause_LiteralAtom(LITERAL L) +{ + if (clause_LiteralIsNegative(L)) + return term_FirstArgument(clause_LiteralSignedAtom(L)); + else + return clause_LiteralSignedAtom(L); +} + + +static __inline__ SYMBOL clause_LiteralPredicate(LITERAL L) +{ + return term_TopSymbol(clause_LiteralAtom(L)); +} + +static __inline__ BOOL clause_LiteralIsPredicate(LITERAL L) +{ + return !fol_IsEquality(clause_LiteralAtom(L)); +} + +static __inline__ BOOL clause_LiteralIsEquality(LITERAL L) +{ + return fol_IsEquality(clause_LiteralAtom(L)); +} + +static __inline__ BOOL clause_LiteralIsSort(LITERAL L) +{ + SYMBOL S; + S = clause_LiteralPredicate(L); + return (symbol_IsPredicate(S) && + (symbol_Arity(S) == 1)); +} + + +static __inline__ void clause_LiteralSetAtom(LITERAL L, TERM A) +{ + if (clause_LiteralIsNegative(L)) + list_Rplaca(term_ArgumentList(clause_LiteralSignedAtom(L)),A); + else + L->atomWithSign = A; +} + +static __inline__ void clause_LiteralSetNegAtom(LITERAL L, TERM A) +{ + list_Rplaca(term_ArgumentList(clause_LiteralSignedAtom(L)), A); +} + +static __inline__ void clause_LiteralSetPosAtom(LITERAL L, TERM A) +{ + L->atomWithSign = A; +} + +static __inline__ void clause_NLiteralSetLiteral(LITERAL L, TERM LIT) +{ + L->atomWithSign = LIT; +} + +/**************************************************************/ +/* Memory management */ +/**************************************************************/ + +static __inline__ void clause_LiteralFree(LITERAL L) +{ + memory_Free(L, sizeof(LITERAL_NODE)); +} + + +/**************************************************************/ +/* Functions to access literals. */ +/**************************************************************/ + +static __inline__ LITERAL clause_GetLiteral(CLAUSE C, int Index) +{ + return C->literals[Index]; +} + +static __inline__ void clause_SetLiteral(CLAUSE C, int Index, LITERAL L) +{ + C->literals[Index]= L; +} + +static __inline__ TERM clause_GetLiteralTerm(CLAUSE C, int Index) +{ + return clause_LiteralSignedAtom(clause_GetLiteral(C, Index)); +} + +static __inline__ TERM clause_GetLiteralAtom(CLAUSE C, int Index) +{ + return clause_LiteralAtom(clause_GetLiteral(C, Index)); +} + +static __inline__ int clause_NumOfConsLits(CLAUSE Clause) +{ + return Clause->c; +} + +static __inline__ int clause_NumOfAnteLits(CLAUSE Clause) +{ + return Clause->a; +} + +static __inline__ int clause_NumOfSuccLits(CLAUSE Clause) +{ + return Clause->s; +} + +static __inline__ void clause_SetNumOfConsLits(CLAUSE Clause, int Number) +{ + Clause->c = Number; +} + +static __inline__ void clause_SetNumOfAnteLits(CLAUSE Clause, int Number) +{ + Clause->a = Number; +} + +static __inline__ void clause_SetNumOfSuccLits(CLAUSE Clause, int Number) +{ + Clause->s = Number; +} + +static __inline__ int clause_Length(CLAUSE Clause) +{ + return (clause_NumOfConsLits(Clause) + + clause_NumOfAnteLits(Clause) + + clause_NumOfSuccLits(Clause)); +} + + +static __inline__ int clause_LastLitIndex(CLAUSE Clause) +{ + return clause_Length(Clause) - 1; +} + +static __inline__ int clause_FirstLitIndex(void) +{ + return 0; +} + +static __inline__ int clause_FirstConstraintLitIndex(CLAUSE Clause) +{ + return 0; +} + +static __inline__ int clause_FirstAntecedentLitIndex(CLAUSE Clause) +{ + return clause_NumOfConsLits(Clause); +} + +static __inline__ int clause_FirstSuccedentLitIndex(CLAUSE Clause) +{ + return (clause_NumOfAnteLits(Clause) + clause_NumOfConsLits(Clause)); +} + + +static __inline__ int clause_LastConstraintLitIndex(CLAUSE Clause) +{ + return clause_NumOfConsLits(Clause) - 1; +} + +static __inline__ int clause_LastAntecedentLitIndex(CLAUSE Clause) +{ + return clause_FirstSuccedentLitIndex(Clause) - 1; +} + +static __inline__ int clause_LastSuccedentLitIndex(CLAUSE Clause) +{ + return clause_Length(Clause) - 1; +} + +static __inline__ LIST clause_GetLiteralList(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: A new list is created containing all literals of the + clause. The list contains pointers, not literal indexes. +***************************************************************/ +{ + LIST Result; + int i; + + Result = list_Nil(); + for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) + Result = list_Cons(clause_GetLiteral(Clause, i), Result); + return Result; +} + + +static __inline__ LIST clause_GetLiteralListExcept(CLAUSE Clause, int Index) +/************************************************************** + INPUT: A clause. + RETURNS: A new list is created containing all literals of the + clause except the literal at <Index>. The list contains + pointers, not literal indexes. +***************************************************************/ +{ + LIST Result; + int i; + + Result = list_Nil(); + for (i=clause_FirstLitIndex(); i<=clause_LastLitIndex(Clause); i++) + if (i != Index) + Result = list_Cons(clause_GetLiteral(Clause, i), Result); + return Result; +} + + +/**************************************************************/ +/* Clause Access Macros */ +/**************************************************************/ + +static __inline__ int clause_Counter(void) +{ + return clause_CLAUSECOUNTER; +} + +static __inline__ void clause_SetCounter(int Value) +{ +#ifdef CHECK + if (Value < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_SetCounter: new counter value is negative."); + misc_FinishErrorReport(); + } +#endif + clause_CLAUSECOUNTER = Value; +} + +static __inline__ int clause_IncreaseCounter(void) +{ +#ifdef CHECK + if (clause_CLAUSECOUNTER == INT_MAX) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_IncreaseCounter: counter overflow."); + misc_FinishErrorReport(); + } +#endif + return clause_CLAUSECOUNTER++; +} + +static __inline__ void clause_DecreaseCounter(void) +{ +#ifdef CHECK + if (clause_CLAUSECOUNTER == 0) { + misc_FinishErrorReport(); + misc_ErrorReport("\n In clause_DecreaseCounter: counter underflow."); + misc_FinishErrorReport(); + } +#endif + clause_CLAUSECOUNTER--; +} + +static __inline__ NAT clause_Depth(CLAUSE Clause) +{ + return Clause->depth; +} + +static __inline__ void clause_SetDepth(CLAUSE Clause, NAT NewDepth) +{ + Clause->depth = NewDepth; +} + + +static __inline__ NAT clause_Weight(CLAUSE Clause) +{ +#ifdef CHECK + if (Clause->weight == clause_WEIGHTUNDEFINED) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_Weight: Tried to access undefined weight."); + misc_FinishErrorReport(); + } +#endif + return Clause->weight; +} + +static __inline__ void clause_UpdateWeight(CLAUSE Clause, FLAGSTORE Flags) +{ + Clause->weight = clause_ComputeWeight(Clause, Flags); +} + + +static __inline__ int clause_Number(const CLAUSE Clause) +{ + return Clause->clausenumber; +} + +static __inline__ void clause_SetNumber(CLAUSE Clause, int Number) +{ + Clause->clausenumber = Number; +} + +static __inline__ void clause_NewNumber(CLAUSE Clause) +{ + Clause->clausenumber = clause_IncreaseCounter(); +} + + +static __inline__ NAT clause_SplitLevel(CLAUSE Clause) +{ + return Clause->validlevel; +} + +static __inline__ BOOL clause_CheckSplitLevel(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: TRUE, if the splitlevel invariant for the clause is fulfilled. + EFFECT: Checks, if the validlevel of the clause is the order + of the highest set bit in the SPLITFIELD entry + of the clause. +***************************************************************/ +{ + if (Clause->validlevel == 0) + return (Clause->splitfield == NULL); + else { + int i, j; + for (i = Clause->splitfield_length-1; i >= 0; i--) + if (Clause->splitfield[i] != 0) + break; + for (j = sizeof(SPLITFIELDENTRY)*CHAR_BIT-1; j >= 0; j--) + if (Clause->splitfield[i] & ((SPLITFIELDENTRY)1 << j)) + break; + return (Clause->validlevel == (i*sizeof(SPLITFIELDENTRY)*CHAR_BIT+j)); + } +} + +static __inline__ LIST clause_ParentClauses(CLAUSE Clause) +{ + return Clause->parentCls; +} + +static __inline__ LIST clause_ParentLiterals(CLAUSE Clause) +{ + return Clause->parentLits; +} + + +static __inline__ SYMBOL clause_MaxVar(CLAUSE Clause) +{ + return Clause->maxVar; +} + +static __inline__ void clause_SetMaxVar(CLAUSE Clause, SYMBOL Variable) +{ + Clause->maxVar = Variable; +} + + +static __inline__ RULE clause_Origin(CLAUSE Clause) +{ + return Clause->origin; +} + +static __inline__ BOOL clause_Exists(CLAUSE Clause) +{ + return (Clause != (CLAUSE)NULL); +} + +static __inline__ BOOL clause_LiteralExists(LITERAL L) +{ + return (L != (LITERAL)NULL); +} + +static __inline__ CLAUSE clause_Null(void) +{ + return (CLAUSE) NULL; +} + +static __inline__ void clause_SetSplitLevel(CLAUSE Clause, NAT Level) +{ + Clause->validlevel = Level; +} + +static __inline__ void clause_InitSplitData(CLAUSE C) +{ + C->splitfield = NULL; + C->splitfield_length = 0; + clause_SetSplitLevel(C, 0); +} + +static __inline__ void clause_SetSplitField(CLAUSE Clause, SPLITFIELD B, + unsigned Length) +{ + unsigned i; + if (Clause->splitfield_length != Length) { + if (Clause->splitfield != NULL) { + memory_Free(Clause->splitfield, + sizeof(SPLITFIELDENTRY) * Clause->splitfield_length); + } + if (Length != 0) { + Clause->splitfield = memory_Malloc(sizeof(SPLITFIELDENTRY) * Length); + } + else + Clause->splitfield = NULL; + Clause->splitfield_length = Length; + } + for (i=0; i < Length; i++) + Clause->splitfield[i] = B[i]; +} + + +static __inline__ NAT clause_ComputeSplitFieldAddress(NAT n, NAT* field) +{ + *field = 0; + while (n >= (sizeof(SPLITFIELDENTRY) * CHAR_BIT)) { + (*field)++; + n -= sizeof(SPLITFIELDENTRY) * CHAR_BIT; + } + return n; +} + +static __inline__ void clause_ExpandSplitField(CLAUSE C, NAT Length) +{ + SPLITFIELD NewField; + NAT i; + if (C->splitfield_length < Length) { + NewField = memory_Malloc(sizeof(SPLITFIELDENTRY) * Length); + for (i=0; i < C->splitfield_length; i++) + NewField[i] = C->splitfield[i]; + for (i=C->splitfield_length; i < Length; i++) + NewField[i] = 0; + if (C->splitfield != NULL) { + memory_Free(C->splitfield, + sizeof(SPLITFIELDENTRY) * C->splitfield_length); + } + C->splitfield = NewField; + C->splitfield_length = Length; + } +} + +static __inline__ void clause_UpdateSplitField(CLAUSE C1, CLAUSE C2) + /* Add the split data of <C2> to <C1> */ +{ + unsigned i; + if (C1->splitfield_length < C2->splitfield_length) + clause_ExpandSplitField(C1, C2->splitfield_length); + for (i=0; i < C2->splitfield_length; i++) + C1->splitfield[i] = C1->splitfield[i] | C2->splitfield[i]; +} + +static __inline__ void clause_ClearSplitField(CLAUSE C) +{ + int i; + + for (i=C->splitfield_length-1; i >=0; i--) + C->splitfield[i] = 0; +} + +static __inline__ void clause_SetSplitFieldBit(CLAUSE Clause, NAT n) +{ + unsigned field; + + n = clause_ComputeSplitFieldAddress(n, &field); + if (field >= Clause->splitfield_length) + clause_ExpandSplitField(Clause, field + 1); + Clause->splitfield[field] = (Clause->splitfield[field]) | + ((SPLITFIELDENTRY)1 << n); +} + +static __inline__ BOOL clause_GetFlag(CLAUSE Clause, CLAUSE_FLAGS Flag) +{ + return (Clause->flags & Flag) != 0; +} + +static __inline__ void clause_SetFlag(CLAUSE Clause, CLAUSE_FLAGS Flag) +{ + Clause->flags = Clause->flags | Flag; +} + +static __inline__ void clause_RemoveFlag(CLAUSE Clause, CLAUSE_FLAGS Flag) +{ + if (Clause->flags & Flag) + Clause->flags = Clause->flags - Flag; +} + +static __inline__ void clause_ClearFlags(CLAUSE Clause) +{ + Clause->flags = 0; +} + + +static __inline__ BOOL clause_DependsOnSplitLevel(CLAUSE C, NAT N) +{ + if (N==0) + return TRUE; + else { + unsigned field; + N = clause_ComputeSplitFieldAddress(N, &field); + if (field >= C->splitfield_length) + return FALSE; + else + return (C->splitfield[field] & ((SPLITFIELDENTRY)1 << N)) != 0; + } +} + +static __inline__ void clause_SetSplitDataFromFather(CLAUSE Result, + CLAUSE Father) +{ + if (clause_GetFlag(Father, CONCLAUSE)) + clause_SetFlag(Result, CONCLAUSE); + clause_SetSplitLevel(Result, clause_SplitLevel(Father)); + clause_SetSplitField(Result, Father->splitfield, Father->splitfield_length); +} + +static __inline__ void clause_UpdateSplitDataFromNewSplitting(CLAUSE Result, + CLAUSE Father, + NAT Level) +{ + unsigned field; + NAT i; + + clause_SetSplitLevel(Result, Level); + Level = clause_ComputeSplitFieldAddress(Level, &field); + + if (field >= Result->splitfield_length) { + if (Result->splitfield != NULL) + memory_Free(Result->splitfield, + sizeof(SPLITFIELDENTRY) * Result->splitfield_length); + Result->splitfield = memory_Malloc((field + 1) * sizeof(SPLITFIELDENTRY)); + Result->splitfield_length = field + 1; + } + if (clause_GetFlag(Father, CONCLAUSE)) + clause_SetFlag(Result, CONCLAUSE); + for (i=0; i < Father->splitfield_length; i++) + Result->splitfield[i] = Father->splitfield[i]; + for (i=Father->splitfield_length; i < Result->splitfield_length; i++) + Result->splitfield[i] = 0; + Result->splitfield[field] = (Result->splitfield[field] | ((SPLITFIELDENTRY)1 << Level)); +} + +static __inline__ void clause_UpdateSplitDataFromPartner(CLAUSE Result, + CLAUSE Partner) +{ + if (clause_GetFlag(Partner, CONCLAUSE)) + clause_SetFlag(Result, CONCLAUSE); + if (clause_SplitLevel(Partner) == 0) + return; + /* Set Split level to misc_Max(Partner, Result) */ + clause_SetSplitLevel(Result, clause_SplitLevel(Partner) > clause_SplitLevel(Result) + ? clause_SplitLevel(Partner) + : clause_SplitLevel(Result)); + clause_UpdateSplitField(Result, Partner); +} + +static __inline__ void clause_SetSplitDataFromList(CLAUSE Result, LIST List) +{ + CLAUSE TempClause; + LIST Scan; + NAT l; + Scan = List; + l = Result->splitfield_length; + while (!list_Empty(Scan)) { + TempClause = (CLAUSE) list_Top(Scan); + if (clause_GetFlag(TempClause, CONCLAUSE)) + clause_SetFlag(Result, CONCLAUSE); + clause_SetSplitLevel(Result, + clause_SplitLevel(TempClause) > clause_SplitLevel(Result) + ? clause_SplitLevel(TempClause) + : clause_SplitLevel(Result)); + if (l < TempClause->splitfield_length) + l = TempClause->splitfield_length; + Scan = list_Cdr(Scan); + } + if (l > Result->splitfield_length) { + if (Result->splitfield != NULL) + memory_Free(Result->splitfield, + sizeof(SPLITFIELDENTRY) * Result->splitfield_length); + Result->splitfield = memory_Malloc(sizeof(SPLITFIELDENTRY) * l); + Result->splitfield_length = l; + } + + for (l=0; l < Result->splitfield_length; l++) + Result->splitfield[l] = 0; + + while (!list_Empty(List)) { + TempClause= (CLAUSE) list_Top(List); + List = list_Cdr(List); + for (l=0; l < TempClause->splitfield_length; l++) + Result->splitfield[l] = Result->splitfield[l] | TempClause->splitfield[l]; + } +} + + +static __inline__ void clause_SetSplitDataFromParents(CLAUSE Result, + CLAUSE Mother, + CLAUSE Father) +{ + NAT i; + if (clause_GetFlag(Father, CONCLAUSE) || clause_GetFlag(Mother, CONCLAUSE)) + clause_SetFlag(Result, CONCLAUSE); + if ((clause_SplitLevel(Father) == 0) && (clause_SplitLevel(Mother) == 0)) + return; + clause_SetSplitLevel(Result, clause_SplitLevel(Mother) > clause_SplitLevel(Father) + ? clause_SplitLevel(Mother) + : clause_SplitLevel(Father)); + + if (Mother->splitfield_length > Father->splitfield_length) { + if (Result->splitfield != NULL) + memory_Free(Result->splitfield, + sizeof(SPLITFIELDENTRY) * Result->splitfield_length); + Result->splitfield = memory_Malloc(sizeof(SPLITFIELDENTRY) * + Mother->splitfield_length); + Result->splitfield_length = Mother->splitfield_length; + for (i=0; i < Father->splitfield_length; i++) + Result->splitfield[i] = + Mother->splitfield[i] | Father->splitfield[i]; + for (i=Father->splitfield_length; i < Mother->splitfield_length; i++) + Result->splitfield[i] = Mother->splitfield[i]; + } + else { + if (Result->splitfield != NULL) + memory_Free(Result->splitfield, + sizeof(SPLITFIELDENTRY) * Result->splitfield_length); + Result->splitfield = memory_Malloc(sizeof(SPLITFIELDENTRY) * + Father->splitfield_length); + Result->splitfield_length = Father->splitfield_length; + for (i=0; i < Mother->splitfield_length; i++) + Result->splitfield[i] = + Mother->splitfield[i] | Father->splitfield[i]; + for (i=Mother->splitfield_length; i < Father->splitfield_length; i++) + Result->splitfield[i] = Father->splitfield[i]; + } +} + +static __inline__ void clause_SetParentClauses(CLAUSE Clause, LIST PClauses) +{ + Clause->parentCls = PClauses; +} + +static __inline__ void clause_AddParentClause(CLAUSE Clause, int PClause) +{ + Clause->parentCls = list_Cons((POINTER) PClause, Clause->parentCls); +} + +static __inline__ void clause_SetParentLiterals(CLAUSE Clause, LIST PLits) +{ + Clause->parentLits = PLits; +} + +static __inline__ void clause_AddParentLiteral(CLAUSE Clause, int PLit) +{ + Clause->parentLits = list_Cons((POINTER) PLit, Clause->parentLits); +} + + +static __inline__ BOOL clause_ValidityIsNotSmaller(CLAUSE C1, CLAUSE C2) +{ + return (C1->validlevel <= C2->validlevel); +} + +static __inline__ BOOL clause_IsMoreValid(CLAUSE C1, CLAUSE C2) +{ + return (C1->validlevel < C2->validlevel); +} + + +static __inline__ BOOL clause_CompareAbstractLEQ (CLAUSE Left, CLAUSE Right) +/************************************************************** + INPUT: Two clauses. + RETURNS: TRUE if left <= right, FALSE otherwise. + EFFECTS: Internal function used to compare clauses for + sorting. + CAUTION: Expects clause literal order to be fixed. +***************************************************************/ +{ + return (BOOL) (clause_CompareAbstract(Left, Right) <= 0); +} + + +static __inline__ BOOL clause_IsFromRewriting(CLAUSE Clause) +{ + return Clause->origin == REWRITING; +} + +static __inline__ BOOL clause_IsFromCondensing(CLAUSE Clause) +{ + return Clause->origin == CONDENSING; +} + +static __inline__ BOOL clause_IsFromObviousReductions(CLAUSE Clause) +{ + return Clause->origin == OBVIOUS_REDUCTIONS; +} + +static __inline__ BOOL clause_IsFromSortSimplification(CLAUSE Clause) +{ + return Clause->origin == SORT_SIMPLIFICATION; +} + +static __inline__ BOOL clause_IsFromMatchingReplacementResolution(CLAUSE Clause) +{ + return Clause->origin == MATCHING_REPLACEMENT_RESOLUTION; +} + +static __inline__ BOOL clause_IsFromClauseDeletion(CLAUSE Clause) +{ + return Clause->origin == CLAUSE_DELETION; +} + +static __inline__ BOOL clause_IsFromEmptySort(CLAUSE Clause) +{ + return Clause->origin == EMPTY_SORT; +} + +static __inline__ BOOL clause_IsFromSortResolution(CLAUSE Clause) +{ + return Clause->origin == SORT_RESOLUTION; +} + +static __inline__ BOOL clause_IsFromUnitConflict(CLAUSE Clause) +{ + return Clause->origin == UNIT_CONFLICT; +} + +static __inline__ BOOL clause_IsFromEqualityResolution(CLAUSE Clause) +{ + return Clause->origin == EQUALITY_RESOLUTION; +} + +static __inline__ BOOL clause_IsFromEqualityFactoring(CLAUSE Clause) +{ + return Clause->origin == EQUALITY_FACTORING; +} + +static __inline__ BOOL clause_IsFromMergingParamodulation(CLAUSE Clause) +{ + return Clause->origin == MERGING_PARAMODULATION; +} + +static __inline__ BOOL clause_IsFromSuperpositionRight(CLAUSE Clause) +{ + return Clause->origin == SUPERPOSITION_RIGHT; +} + +static __inline__ BOOL clause_IsFromSuperpositionLeft(CLAUSE Clause) +{ + return Clause->origin == SUPERPOSITION_LEFT; +} + +static __inline__ BOOL clause_IsFromGeneralResolution(CLAUSE Clause) +{ + return Clause->origin == GENERAL_RESOLUTION; +} + +static __inline__ BOOL clause_IsFromGeneralFactoring(CLAUSE Clause) +{ + return Clause->origin == GENERAL_FACTORING; +} + +static __inline__ BOOL clause_IsFromSplitting(CLAUSE Clause) +{ + return Clause->origin == SPLITTING; +} + +static __inline__ BOOL clause_IsFromDefApplication(CLAUSE Clause) +{ + return Clause->origin == DEFAPPLICATION; +} + +static __inline__ BOOL clause_IsFromTerminator(CLAUSE Clause) +{ + return Clause->origin == TERMINATOR; +} + +static __inline__ BOOL clause_IsTemporary(CLAUSE Clause) +{ + return Clause->origin == TEMPORARY; +} + +static __inline__ BOOL clause_IsFromInput(CLAUSE Clause) +{ + return Clause->origin == INPUT; +} + + +static __inline__ BOOL clause_HasReducedPredecessor(CLAUSE Clause) +{ + RULE origin = clause_Origin(Clause); + + return (origin == CONDENSING || + origin == REWRITING || + origin == SPLITTING || + origin == ASSIGNMENT_EQUATION_DELETION || + origin == SORT_SIMPLIFICATION || + origin == OBVIOUS_REDUCTIONS); +} + +static __inline__ BOOL clause_IsSplitFather(CLAUSE C1, CLAUSE C2) +{ + return (C1->clausenumber == (int)list_Car(C2->parentCls)); +} + + +static __inline__ void clause_SetFromRewriting(CLAUSE Clause) +{ + Clause->origin = REWRITING; +} + +static __inline__ void clause_SetFromContextualRewriting(CLAUSE Clause) +{ + Clause->origin = CONTEXTUAL_REWRITING; +} + +static __inline__ void clause_SetFromUnitConflict(CLAUSE Clause) +{ + Clause->origin = UNIT_CONFLICT; +} + +static __inline__ void clause_SetFromCondensing(CLAUSE Clause) +{ + Clause->origin = CONDENSING; +} + +static __inline__ void clause_SetFromAssignmentEquationDeletion(CLAUSE Clause) +{ + Clause->origin = ASSIGNMENT_EQUATION_DELETION; +} + +static __inline__ void clause_SetFromObviousReductions(CLAUSE Clause) +{ + Clause->origin = OBVIOUS_REDUCTIONS; +} + +static __inline__ void clause_SetFromSortSimplification(CLAUSE Clause) +{ + Clause->origin = SORT_SIMPLIFICATION; +} + +static __inline__ void clause_SetFromMatchingReplacementResolution(CLAUSE Clause) +{ + Clause->origin = MATCHING_REPLACEMENT_RESOLUTION; +} + +static __inline__ void clause_SetFromClauseDeletion(CLAUSE Clause) +{ + Clause->origin = CLAUSE_DELETION; +} + +static __inline__ void clause_SetFromEmptySort(CLAUSE Clause) +{ + Clause->origin = EMPTY_SORT; +} + +static __inline__ void clause_SetFromSortResolution(CLAUSE Clause) +{ + Clause->origin = SORT_RESOLUTION; +} + +static __inline__ void clause_SetFromEqualityResolution(CLAUSE Clause) +{ + Clause->origin = EQUALITY_RESOLUTION; +} + +static __inline__ void clause_SetFromEqualityFactoring(CLAUSE Clause) +{ + Clause->origin = EQUALITY_FACTORING; +} + +static __inline__ void clause_SetFromMergingParamodulation(CLAUSE Clause) +{ + Clause->origin = MERGING_PARAMODULATION; +} + +static __inline__ void clause_SetFromParamodulation(CLAUSE Clause) +{ + Clause->origin = PARAMODULATION; +} +static __inline__ void clause_SetFromOrderedParamodulation(CLAUSE Clause) +{ + Clause->origin = ORDERED_PARAMODULATION; +} +static __inline__ void clause_SetFromSuperpositionRight(CLAUSE Clause) +{ + Clause->origin = SUPERPOSITION_RIGHT; +} + +static __inline__ void clause_SetFromSuperpositionLeft(CLAUSE Clause) +{ + Clause->origin = SUPERPOSITION_LEFT; +} + +static __inline__ void clause_SetFromGeneralResolution(CLAUSE Clause) +{ + Clause->origin = GENERAL_RESOLUTION; +} + +static __inline__ void clause_SetFromOrderedHyperResolution(CLAUSE Clause) +{ + Clause->origin = ORDERED_HYPER; +} + +static __inline__ void clause_SetFromSimpleHyperResolution(CLAUSE Clause) +{ + Clause->origin = SIMPLE_HYPER; +} + +static __inline__ void clause_SetFromURResolution(CLAUSE Clause) +{ + Clause->origin = UR_RESOLUTION; +} + +static __inline__ void clause_SetFromGeneralFactoring(CLAUSE Clause) +{ + Clause->origin = GENERAL_FACTORING; +} + +static __inline__ void clause_SetFromSplitting(CLAUSE Clause) +{ + Clause->origin = SPLITTING; +} + +static __inline__ void clause_SetFromDefApplication(CLAUSE Clause) +{ + Clause->origin = DEFAPPLICATION; +} + +static __inline__ void clause_SetFromTerminator(CLAUSE Clause) +{ + Clause->origin = TERMINATOR; +} + +static __inline__ void clause_SetTemporary(CLAUSE Clause) +{ + Clause->origin = TEMPORARY; +} + + +static __inline__ void clause_SetFromInput(CLAUSE Clause) +{ + Clause->origin = INPUT; +} + + +static __inline__ LITERAL clause_FirstConstraintLit(CLAUSE Clause) +{ + return Clause->literals[0]; +} + +static __inline__ LITERAL clause_FirstAntecedentLit(CLAUSE Clause) +{ + return Clause->literals[clause_FirstAntecedentLitIndex(Clause)]; +} + +static __inline__ LITERAL clause_FirstSuccedentLit(CLAUSE Clause) +{ + return Clause->literals[clause_FirstSuccedentLitIndex(Clause)]; +} + +static __inline__ LITERAL clause_LastConstraintLit(CLAUSE Clause) +{ + return Clause->literals[clause_LastConstraintLitIndex(Clause)]; +} + +static __inline__ LITERAL clause_LastAntecedentLit(CLAUSE Clause) +{ + return Clause->literals[clause_LastAntecedentLitIndex(Clause)]; +} + +static __inline__ LITERAL clause_LastSuccedentLit(CLAUSE Clause) +{ + return Clause->literals[clause_LastSuccedentLitIndex(Clause)]; +} + + +static __inline__ BOOL clause_HasEmptyConstraint(CLAUSE Clause) +{ + return clause_NumOfConsLits(Clause) == 0; +} + +static __inline__ BOOL clause_HasEmptyAntecedent(CLAUSE Clause) +{ + return clause_NumOfAnteLits(Clause) == 0; +} + +static __inline__ BOOL clause_HasEmptySuccedent(CLAUSE Clause) +{ + return clause_NumOfSuccLits(Clause) == 0; +} + + +static __inline__ BOOL clause_IsGround(CLAUSE Clause) +{ +#ifdef CHECK + if (!symbol_Equal(clause_MaxVar(Clause), clause_SearchMaxVar(Clause))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In clause_IsGround: Clause is corrupted."); + misc_FinishErrorReport(); + } +#endif + return (symbol_VarIndex(clause_MaxVar(Clause)) == + symbol_GetInitialStandardVarCounter()); +} + +static __inline__ BOOL clause_IsEmptyClause(CLAUSE C) +{ + return (C != (CLAUSE)NULL && + clause_HasEmptyAntecedent(C) && + clause_HasEmptySuccedent(C) && + clause_HasEmptyConstraint(C)); +} + +static __inline__ int clause_LiteralGetIndex(LITERAL L) +{ + int j = 0; + + while (clause_GetLiteral(clause_LiteralOwningClause(L), j) != L) + j++; + + return j; +} + +static __inline__ BOOL clause_LiteralIsFromConstraint(LITERAL Literal) +{ + int index = clause_LiteralGetIndex(Literal); + CLAUSE clause = clause_LiteralOwningClause(Literal); + + return (index <= clause_LastConstraintLitIndex(clause) && + index >= clause_FirstConstraintLitIndex(clause)); +} + +static __inline__ BOOL clause_LiteralIsFromAntecedent(LITERAL Literal) +{ + int index = clause_LiteralGetIndex(Literal); + CLAUSE clause = clause_LiteralOwningClause(Literal); + + return (index <= clause_LastAntecedentLitIndex(clause) && + index >= clause_FirstAntecedentLitIndex(clause)); +} + +static __inline__ BOOL clause_LiteralIsFromSuccedent(LITERAL Literal) +{ + int index; + CLAUSE clause; + index = clause_LiteralGetIndex(Literal); + clause = clause_LiteralOwningClause(Literal); + return (index <= clause_LastSuccedentLitIndex(clause) && + index >= clause_FirstSuccedentLitIndex(clause)); +} + +static __inline__ BOOL clause_IsSimpleSortClause(CLAUSE Clause) +{ + return (clause_HasEmptyAntecedent(Clause) && + (clause_NumOfSuccLits(Clause) == 1) && + clause_LiteralIsSort(clause_GetLiteral(Clause, + clause_NumOfConsLits(Clause))) && + clause_HasSolvedConstraint(Clause)); +} + +static __inline__ BOOL clause_IsSubsortClause(CLAUSE Clause) +{ + return (clause_IsSimpleSortClause(Clause) && + term_IsVariable(term_FirstArgument( + clause_LiteralSignedAtom( + clause_GetLiteral(Clause, clause_NumOfConsLits(Clause)))))); +} + + +static __inline__ BOOL clause_HasSuccLits(CLAUSE Clause) +{ + return (clause_NumOfSuccLits(Clause) > 1); +} + +static __inline__ BOOL clause_HasGroundSuccLit(CLAUSE Clause) +{ + int i, l; + + l = clause_Length(Clause); + for (i = clause_FirstSuccedentLitIndex(Clause); i < l; i++) + if (term_IsGround(Clause->literals[i]->atomWithSign)) + return TRUE; + + return FALSE; +} + +static __inline__ LITERAL clause_GetGroundSuccLit(CLAUSE Clause) +{ + int i, l; + + l = clause_Length(Clause); + for (i = clause_FirstSuccedentLitIndex(Clause); i < l; i++) + if (term_IsGround(Clause->literals[i]->atomWithSign)) + return Clause->literals[i]; + + return (LITERAL)NULL; +} + + +static __inline__ void clause_Free(CLAUSE Clause) +{ + memory_Free(Clause, sizeof(CLAUSE_NODE)); +} + + +static __inline__ void clause_ReInit(CLAUSE Clause, + FLAGSTORE Flags, + PRECEDENCE Precedence) +{ + clause_Normalize(Clause); + clause_SetMaxLitFlags(Clause, Flags, Precedence); + clause_UpdateWeight(Clause, Flags); + clause_UpdateMaxVar(Clause); +} + +static __inline__ void clause_OrientAndReInit(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence) +{ + clause_OrientEqualities(Clause, Flags, Precedence); + clause_ReInit(Clause, Flags, Precedence); +} + +static __inline__ void clause_SetDataFromFather(CLAUSE Result, CLAUSE Father, + int i, FLAGSTORE Flags, + PRECEDENCE Precedence) +{ + clause_OrientAndReInit(Result, Flags, Precedence); + clause_SetSplitDataFromFather(Result, Father); + clause_SetDepth(Result, clause_Depth(Father) + 1); + clause_AddParentClause(Result, clause_Number(Father)); + clause_AddParentLiteral(Result, i); +} + + +static __inline__ void clause_SetDataFromParents(CLAUSE Result, CLAUSE Father, + int i, CLAUSE Mother, int j, + FLAGSTORE Flags, + PRECEDENCE Precedence) +{ + clause_OrientAndReInit(Result, Flags, Precedence); + clause_SetSplitDataFromParents(Result, Father, Mother); + clause_SetDepth(Result, + misc_Max(clause_Depth(Father), clause_Depth(Mother)) +1); + clause_AddParentClause(Result, clause_Number(Father)); + clause_AddParentLiteral(Result, i); + clause_AddParentClause(Result, clause_Number(Mother)); + clause_AddParentLiteral(Result, j); +} + + +#endif + diff --git a/test/spass/clock.c b/test/spass/clock.c new file mode 100644 index 0000000000000000000000000000000000000000..7106669ae44cd7fa7f4a88c48313231d54c4eef0 --- /dev/null +++ b/test/spass/clock.c @@ -0,0 +1,215 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CLOCK * */ +/* * * */ +/* * $Module: CLOCK * */ +/* * * */ +/* * Copyright (C) 1996, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "clock.h" + + +/**************************************************************/ +/* Global Variables */ +/**************************************************************/ + +float clock_Akku[clock_TYPESIZE]; +CLOCK_TMS clock_Counters[clock_TYPESIZE]; + +#ifdef WIN +float clock_Ping; +#endif + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +void clock_Init(void) +/********************************************************* + INPUT: None. + EFFECT: Initializes the clock Module. + RETURNS: None. + MEMORY: None. +**********************************************************/ +{ + int i; + + for (i=0;i<clock_TYPESIZE;i++) { + clock_InitCounter(i); + } +#ifdef WIN + clock_Ping = 0; +#endif +} + + + +void clock_InitCounter(CLOCK_CLOCKS ClockCounter) +/********************************************************* + INPUT: A clock counter. + EFFECT: The clock counter <ClockCounter> is initialized. + RETURNS: None. + MEMORY: None. +**********************************************************/ +{ + clock_Akku[ClockCounter] = 0; +} + + +void clock_StartCounter(CLOCK_CLOCKS ClockCounter) +/********************************************************* + INPUT: A clock counter. + EFFECT: The clock counter <ClockCounter> is started. + RETURNS: None. + MEMORY: None. +**********************************************************/ +{ +#ifndef CLOCK_NO_TIMING + ftime(&(clock_Counters[ClockCounter])); +#endif +} + + +void clock_StopPassedTime(CLOCK_CLOCKS ClockCounter) +/********************************************************* + INPUT: A clock counter. + EFFECT: Stores the number of seconds passed since given + counter was started in the according + accumulator. + RETURNS: None. + MEMORY: None. +**********************************************************/ +{ +#ifndef CLOCK_NO_TIMING + CLOCK_TMS newtime; + ftime(&newtime); + clock_Akku[ClockCounter] = clock_GetSeconds(ClockCounter); +#endif +} + + +void clock_StopAddPassedTime(CLOCK_CLOCKS ClockCounter) +/********************************************************* + INPUT: A clock counter. + EFFECT: Adds the number of seconds passed since given + counter was started to the according + accumulator. + RETURNS: None. + MEMORY: None. +**********************************************************/ +{ +#ifndef CLOCK_NO_TIMING + CLOCK_TMS newtime; + ftime(&newtime); + clock_Akku[ClockCounter] += clock_GetSeconds(ClockCounter); +#endif +} + + +float clock_GetSeconds(CLOCK_CLOCKS ClockCounter) +/********************************************************* + INPUT: A clock counter. + EFFECT: Computes the number of seconds spent by the + counter. + RETURNS: The number of seconds spent by the counter as + a float. + MEMORY: None. +**********************************************************/ +{ +#ifndef CLOCK_NO_TIMING + CLOCK_TMS newtime; + ftime(&newtime); + return ((float) (newtime.time - clock_Counters[ClockCounter].time) + + (((newtime.millitm - clock_Counters[ClockCounter].millitm)) + /(float)1000)); +#else + return 0; +#endif +} + +#ifdef WIN +void clock_PingOneSecond(void) +/********************************************************* + INPUT: None but assumes the clock_OVERALL to be properly + initialized. + EFFECT: If between the previous call to this function or + to clock_Init more one second is passed, the + function prints a "PING" to stdout. + Needed only for the windows implementation. + CAUTION: Only needed to get around Windows95/98 scheduling + problems. +**********************************************************/ +{ + if (clock_GetSeconds(clock_OVERALL) > clock_Ping + 1) { + clock_Ping++; + puts("\n PING "); + } +} +#endif + + + +void clock_PrintTime(CLOCK_CLOCKS ClockCounter) +/********************************************************* + INPUT: A clock counter. + EFFECT: The time is printed in format hh:mm:ss.dd to stdout + RETURNS: None. + MEMORY: None. +**********************************************************/ +{ +#ifndef CLOCK_NO_TIMING + NAT hours, minutes; + float seconds; + + seconds = clock_Akku[ClockCounter]; + hours = (NAT)seconds/3600; + seconds -= hours*3600; + minutes = (NAT)seconds/60; + seconds -= (minutes*60); + if (seconds >= 10.0) + printf("%u:%02u:%2.2f",hours,minutes,seconds); + else + printf("%u:%02u:0%2.2f",hours,minutes,seconds); +#else + fputs(" No Timing on this machine. ",stdout); +#endif +} diff --git a/test/spass/clock.h b/test/spass/clock.h new file mode 100644 index 0000000000000000000000000000000000000000..6e6757426944f2e4bedee4fb832bb4b4f21dda72 --- /dev/null +++ b/test/spass/clock.h @@ -0,0 +1,78 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CLOCK * */ +/* * * */ +/* * $Module: CLOCK * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1999, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/* $RCSfile$ */ + +#ifndef _CLOCK_ +#define _CLOCK_ + +#include "misc.h" +#include <sys/types.h> +#include <sys/timeb.h> + +typedef enum { + clock_BACKTRACK, + clock_OVERALL, + clock_INPUT, + clock_CNF, + clock_REDUCTION, + clock_INFERENCE, + clock_TYPESIZE +} CLOCK_CLOCKS; + +typedef struct timeb CLOCK_TMS; + +void clock_Init(void); +void clock_InitCounter(CLOCK_CLOCKS); +void clock_StartCounter(CLOCK_CLOCKS); +void clock_StopPassedTime(CLOCK_CLOCKS); +void clock_StopAddPassedTime(CLOCK_CLOCKS); +float clock_GetSeconds(CLOCK_CLOCKS); +void clock_PrintTime(CLOCK_CLOCKS); + +#ifdef WIN +void clock_PingOneSecond(void); +#endif + +#endif diff --git a/test/spass/closure.c b/test/spass/closure.c new file mode 100644 index 0000000000000000000000000000000000000000..cfebc7afccc2ab4909e55d14009350b54892af1a --- /dev/null +++ b/test/spass/closure.c @@ -0,0 +1,441 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CONGRUENCE CLOSURE ALGORITHM * */ +/* * * */ +/* * $Module: CLOSURE * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/**************************************************************/ +/* Include */ +/**************************************************************/ + +#include "closure.h" + + +/**************************************************************/ +/* Global constants and variable */ +/**************************************************************/ + +/* standard initial size of a closure's stacks */ +static const int cc_RASSTDSIZE = 64; +/* cc_RASSTDSIZE * ld(cc_RASSTDSIZE) */ +static const int cc_SIZELDSIZE = 384; +/* the virtual term "true" has number 0 */ +static const ELEMENT cc_NOOFTRUE = 0; + + +static struct { + PARTITION partition; + TABLE table; + RAS car, cdr, size, pending, combine; +} cc_CLOSURE; + +/* the closure consists of a partition, a signature table, stacks for */ +/* (circularly linked) lists of predecessors of equivalence classes (i. e. */ +/* terms with direct subterms from this class), for the sizes of these lists, */ +/* for pending terms (the ones to be worked off) and for terms to be combined */ +/* in the same equivalence class */ + + +/**************************************************************/ +/* Inline functions */ +/**************************************************************/ + +static __inline__ PARTITION cc_GetPartition(void) +{ + return cc_CLOSURE.partition; +} + + +static __inline__ void cc_SetPartition(PARTITION partition) +{ + cc_CLOSURE.partition = partition; +} + + +static __inline__ TABLE cc_GetTable(void) +{ + return cc_CLOSURE.table; +} + + +static __inline__ void cc_SetTable(TABLE table) +{ + cc_CLOSURE.table = table; +} + + +static __inline__ RAS cc_GetCars(void) +{ + return cc_CLOSURE.car; +} + + +static __inline__ TERM cc_GetCar(int index) +{ + return (TERM) ras_Get(cc_GetCars(), index); +} + + +static __inline__ void cc_SetCars(RAS car) +{ + cc_CLOSURE.car = car; +} + + +static __inline__ RAS cc_GetCdrs(void) +{ + return cc_CLOSURE.cdr; +} + + +static __inline__ int cc_GetCdr(int index) +{ + return (int) ras_Get(cc_GetCdrs(), index); +} + + +static __inline__ void cc_SetCdrs(RAS cdr) +{ + cc_CLOSURE.cdr = cdr; +} + + +static __inline__ void cc_SetCdr(int index, int cdr) +{ + ras_Set(cc_GetCdrs(), index, (POINTER) cdr); +} + + +static __inline__ RAS cc_GetSizes(void) +{ + return cc_CLOSURE.size; +} + + +static __inline__ int cc_GetSize(int index) +{ + return (int) ras_Get(cc_GetSizes(), index); +} + + +static __inline__ void cc_SetSizes(RAS size) +{ + cc_CLOSURE.size = size; +} + + +static __inline__ void cc_SetSize(int index, int size) +{ + ras_Set(cc_GetSizes(), index, (POINTER) size); +} + + +static __inline__ RAS cc_GetPending(void) +{ + return cc_CLOSURE.pending; +} + + +static __inline__ void cc_SetPending(RAS pending) +{ + cc_CLOSURE.pending = pending; +} + + +static __inline__ RAS cc_GetCombine(void) +{ + return cc_CLOSURE.combine; +} + + +static __inline__ void cc_SetCombine(RAS combine) +{ + cc_CLOSURE.combine = combine; +} + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +static int cc_Number(int actno, TERM term, TERM pred) +/*************************************************************** + INPUT: the actual number of terms, the term to be numbered + and its predecessor (may be the empty term + term_Null()) + RETURNS: the new number of terms after recursively numbering + the term and its subterms + EFFECT: stores a term's number as its size, partially + initializes its predecessor list and pushes all + subterms to the pending stack +***************************************************************/ +{ + LIST terms; + +#ifdef CHECK + if (actno < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cc_Number: negative actual number of terms."); + misc_FinishErrorReport(); + } +#endif + + term_SetSize(term, actno++); + cc_SetCars(ras_Push(cc_GetCars(), pred)); + cc_SetPending(ras_Push(cc_GetPending(), term)); + for (terms = term_ArgumentList(term); !list_Empty(terms); terms = + list_Cdr(terms)) + actno = cc_Number(actno, list_Car(terms), term); + return actno; +} + + +static void cc_Union(ECLASS c1, ECLASS c2) +/*************************************************************** + EFFECT: unions c1 and c2, therefore the signatures of the + predecessors of one class change, so these + predecessors have to be deleted from the signature + table and become pending again; sets new class's + predecessor list and its size to the concatenation of + the old lists resp. the sum of the old sizes +***************************************************************/ +{ + int aux, size; + TERM term; + +#ifdef CHECK + if (part_Find(cc_GetPartition(), c1) != c1) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cc_Union: first class corrupted, i. e. is not "); + misc_ErrorReport("the representative."); + misc_FinishErrorReport(); + } + if (part_Find(cc_GetPartition(), c2) != c2) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cc_Union: second class corrupted, i. e. is not "); + misc_ErrorReport("the representative."); + misc_FinishErrorReport(); + } +#endif + + if (c1 != c2) { + + /* make c1 the class with the bigger (or at least not smaller) list: */ + if (cc_GetSize(c1) < cc_GetSize(c2)) { + aux = c1; + c1 = c2; + c2 = aux; + } + + /* delete c2's predecessors from signature table and add them to pending: */ + for (size = cc_GetSize(c2), aux = c2; size > 0; size--) { + term = cc_GetCar(aux); + aux = cc_GetCdr(aux); + table_Delete(cc_GetTable(), term); + cc_SetPending(ras_Push(cc_GetPending(), term)); + } + + if (cc_GetSize(c2) > 0) { /* then GetSize(c1) ( >= GetSize(c2) ) > 0 too */ + + /* union circularly linked lists by exchanging cdrs: */ + aux = cc_GetCdr(c1); + cc_SetCdr(c1, cc_GetCdr(c2)); + cc_SetCdr(c2, aux); + + cc_SetSize(c1, cc_GetSize(c1) + cc_GetSize(c2)); + } + part_Union(cc_GetPartition(), c1, c2); + } +} + + +static void cc_InitData(CLAUSE clause) +/*************************************************************** + INPUT: the clause to investigate + EFFECT: pushes clause's atoms and their subterms on the + pending stack, initializes each predecessor list with + the list containing only a term's father, and unions + the equivalence classes of the terms of the same + antecedent equation +***************************************************************/ +{ + int last, actno, i, ld; + TERM atom; + RAS cdr, size; + + cc_SetCars(ras_InitWithSize(cc_GetCars(), cc_RASSTDSIZE)); + cc_SetPending(ras_InitWithSize(cc_GetPending(), cc_RASSTDSIZE)); + ras_FastPush(cc_GetCars(), term_Null()); /* "true" has no predecessors */ + actno = 1; + last = clause_LastLitIndex(clause); + for (i = clause_FirstLitIndex(); i <= last; i++) { + atom = clause_GetLiteralAtom(clause, i); + if (fol_IsEquality(atom)) { + actno = cc_Number(actno, term_FirstArgument(atom), term_Null()); + actno = cc_Number(actno, term_SecondArgument(atom), term_Null()); + } + else + actno = cc_Number(actno, atom, term_Null()); + } + cc_SetPartition(part_Init(cc_GetPartition(), actno)); + cc_SetTable(table_Init(cc_GetTable(), symbol_ActIndex() - 1, + clause_MaxVar(clause), actno - 1)); + cdr = ras_InitWithSize(cc_GetCdrs(), actno); + size = ras_InitWithSize(cc_GetSizes(), actno); + for (i = 0; i < actno; i++) { + ras_FastPush(cdr, (POINTER) i); /* form a cycle */ + ras_FastPush(size, (POINTER) (cc_GetCar(i) == term_Null()? 0 : 1)); + } + cc_SetCdrs(cdr); + cc_SetSizes(size); + + /* compute ceil(ld(actno)) avoiding mathbib-logarithm's rounding errors: */ + for (ld = 0, i = actno - 1; i > 0; i >>= 1) + ld++; + + cc_SetCombine(ras_InitWithSize(cc_GetCombine(), actno * ld + 1)); + + /* for every antecedent equation union equivalence classes of its terms */ + /* (a non-equational atom is represented as the equation atom = "true"): */ + last = clause_LastAntecedentLitIndex(clause); + for (i = clause_FirstLitIndex(); i <= last; i++) { + atom = clause_GetLiteralAtom(clause, i); + if (fol_IsEquality(atom)) + cc_Union(term_Size(term_FirstArgument(atom)), /* clause not shared, therefore */ + term_Size(term_SecondArgument(atom))); /* here no cc_Find needed */ + else + cc_Union(term_Size(atom), part_Find(cc_GetPartition(), cc_NOOFTRUE)); + } + +} + + +static BOOL cc_Outit(CLAUSE clause) +/*************************************************************** + RETURNS: the decision, if the clause is a tautology +***************************************************************/ +{ + int last, i; + BOOL result; + TERM atom; + +#ifdef CHECK + if (!ras_Empty(cc_GetPending())) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cc_Outit: there are terms left to work off."); + misc_FinishErrorReport(); + } +#endif + + last = clause_LastLitIndex(clause); + for (i = clause_FirstSuccedentLitIndex(clause), result = FALSE; + i <= last && !result; i++) { + atom = clause_GetLiteralAtom(clause, i); + if (fol_IsEquality(atom)) + result = part_Equivalent(cc_GetPartition(), + term_Size(term_FirstArgument(atom)), + term_Size(term_SecondArgument(atom))); + else + result = part_Equivalent(cc_GetPartition(), term_Size(atom), cc_NOOFTRUE); + } + return result; +} + + +/**************************************************************/ +/* Main functions */ +/**************************************************************/ + +void cc_Init(void) +{ + cc_SetPartition(part_Create(cc_RASSTDSIZE)); + cc_SetTable(table_Create(cc_RASSTDSIZE, cc_RASSTDSIZE, cc_RASSTDSIZE)); + cc_SetCars(ras_CreateWithSize(cc_RASSTDSIZE)); + cc_SetCdrs(ras_CreateWithSize(cc_RASSTDSIZE)); + cc_SetSizes(ras_CreateWithSize(cc_RASSTDSIZE)); + cc_SetPending(ras_CreateWithSize(cc_RASSTDSIZE)); + cc_SetCombine(ras_CreateWithSize(cc_SIZELDSIZE)); +} + + +void cc_Free(void) +{ + part_Free(cc_GetPartition()); + table_Free(cc_GetTable()); + ras_Free(cc_GetCars()); + ras_Free(cc_GetCdrs()); + ras_Free(cc_GetSizes()); + ras_Free(cc_GetPending()); + ras_Free(cc_GetCombine()); +} + + +BOOL cc_Tautology(CLAUSE clause) +/*************************************************************** + INPUT: the clause to test + RETURNS: the decision, if the clause - where all variables are + regarded as skolem constants - is a tautology, using + the congruence closure algorithm of Downey, Sethi and + Tarjan + CAUTION: overrides the sizes of the clause's terms +***************************************************************/ +{ + TERM term, query; + + cc_InitData(clause); + while (!ras_Empty(cc_GetPending())) { + + /* propagate the closure: */ + while (!ras_Empty(cc_GetPending())) { + term = ras_Pop(cc_GetPending()); + query = table_QueryAndEnter(cc_GetTable(), cc_GetPartition(), term); + if (query != term_Null()) { + ras_FastPush(cc_GetCombine(), term); + ras_FastPush(cc_GetCombine(), query); + } + } + while (!ras_Empty(cc_GetCombine())) + cc_Union(part_Find(cc_GetPartition(), term_Size(ras_Pop(cc_GetCombine()))), + part_Find(cc_GetPartition(), term_Size(ras_Pop(cc_GetCombine())))); + } + return cc_Outit(clause); +} + diff --git a/test/spass/closure.h b/test/spass/closure.h new file mode 100644 index 0000000000000000000000000000000000000000..0a6d5c046e1c31c5beccafa6fa2c22a1f9fd8484 --- /dev/null +++ b/test/spass/closure.h @@ -0,0 +1,67 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CONGRUENCE CLOSURE ALGORITHM * */ +/* * * */ +/* * $Module: CLOSURE * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +#ifndef _CLOSURE_ +#define _CLOSURE_ + + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "clause.h" +#include "table.h" +#include "ras.h" + + +/**************************************************************/ +/* Prototype */ +/**************************************************************/ + +void cc_Init(void); +void cc_Free(void); +BOOL cc_Tautology(CLAUSE); + + +#endif + diff --git a/test/spass/cnf.c b/test/spass/cnf.c new file mode 100644 index 0000000000000000000000000000000000000000..bf52a264f35919a7670f5d55bdeb4d994f2c8193 --- /dev/null +++ b/test/spass/cnf.c @@ -0,0 +1,4787 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CNF TRANSLATOR * */ +/* * * */ +/* * $Module: CNF * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "cnf.h" +#include "rules-inf.h" +#include "rules-red.h" + + +static TERM cnf_AntiPrenexPath(TERM, TERM); +static TERM cnf_ApplyDefinitionInternOnce(TERM, TERM, TERM, TERM, BOOL*); + +static SYMBOL cnf_GetDualSymbol(SYMBOL symbol); + +static TERM cnf_IsDefinition(TERM); + +static void cnf_OptimizedSkolemFormula(PROOFSEARCH, TERM, char*, BOOL, TERM, + LIST*, LIST*, BOOL, HASH, int); +static int cnf_PredicateOccurrences(TERM, SYMBOL); + +static void cnf_RplacVar(TERM, LIST, LIST); + +static LIST cnf_SatUnit(PROOFSEARCH, LIST); +static LIST cnf_SkolemFunctionFormula(TERM, LIST, LIST, PRECEDENCE); + +/* For every variable the depth in the current term, required for */ +/* strong skolemization */ +static int* cnf_VARIABLEDEPTHARRAY; +/* Holds a copy of the ProofSearch--Object built by cnf_Flotter */ +/* during cnf_QueryFlotter */ +static PROOFSEARCH cnf_SEARCHCOPY; + +/* Proofsearch--Object for the function cnf_HaveProof. We need this */ +/* to reduce the number of term stamps required. */ +static PROOFSEARCH cnf_HAVEPROOFPS; + + +void cnf_Init(FLAGSTORE Flags) +/*************************************************************** + INPUT: A flag store. + RETURNS: None. + SUMMARY: Initializes the CNF Module. + EFFECTS: Initializes global variables. + CAUTION: MUST BE CALLED BEFORE ANY OTHER CNF-FUNCTION. +***************************************************************/ +{ + /* If strong skolemization is performed, allocate array for variable depth */ + if (flag_GetFlagValue(Flags, flag_CNFSTRSKOLEM)) + cnf_VARIABLEDEPTHARRAY = (int*) memory_Malloc(sizeof(int[symbol__MAXSTANDARDVAR + 1])); + else + cnf_VARIABLEDEPTHARRAY = NULL; + cnf_SEARCHCOPY = prfs_Create(); + cnf_HAVEPROOFPS = prfs_Create(); +} + + +void cnf_Free(FLAGSTORE Flags) +/************************************************************** + INPUT: A flag store. + RETURNS: None. + SUMMARY: Frees the CNF Module. +***************************************************************/ +{ + /* If strong skolemization is performed, free array for variable depth */ + if (flag_GetFlagValue(Flags, flag_CNFSTRSKOLEM)) { + memory_Free(cnf_VARIABLEDEPTHARRAY, sizeof(int) * (symbol__NOOFSTANDARDVAR + 1)); + cnf_VARIABLEDEPTHARRAY = NULL; + } + prfs_Delete(cnf_SEARCHCOPY); + cnf_SEARCHCOPY = NULL; + prfs_Delete(cnf_HAVEPROOFPS); + cnf_HAVEPROOFPS = NULL; +} + + +static int cnf_GetFormulaPolarity(TERM term, TERM subterm) +/********************************************************** + INPUT: Two terms term and subterm where subterm is a + subterm of term. + RETURNS: The polarity of subterm in term. +********************************************************/ +{ + LIST scan; + TERM term1; + int polterm1,bottom; + + bottom = vec_ActMax(); + vec_Push((POINTER) 1); + vec_Push(term); + + do { + term1 = (TERM)vec_PopResult(); + polterm1 = (int)vec_PopResult(); + if (term1 == subterm) { + vec_SetMax(bottom); + return polterm1; + }else + if (symbol_Equal(term_TopSymbol(term1),fol_Not())) { + vec_Push((POINTER) (- polterm1)); + vec_Push(list_Car(term_ArgumentList(term1))); + } + if (symbol_Equal(term_TopSymbol(term1),fol_Exist()) || + symbol_Equal(term_TopSymbol(term1),fol_All())) { + vec_Push((POINTER)polterm1); + vec_Push(list_Second(term_ArgumentList(term1))); + } + else + if (symbol_Equal(term_TopSymbol(term1),fol_Implies())) { + vec_Push((POINTER) (- polterm1)); + vec_Push(list_Car(term_ArgumentList(term1))); + vec_Push((POINTER) polterm1); + vec_Push(list_Second(term_ArgumentList(term1))); + } + else + if (symbol_Equal(term_TopSymbol(term1),fol_Equiv())) { + vec_Push(0); + vec_Push(list_Car(term_ArgumentList(term1))); + vec_Push(0); + vec_Push(list_Second(term_ArgumentList(term1))); + } + else + if (symbol_Equal(term_TopSymbol(term1),fol_And()) || + symbol_Equal(term_TopSymbol(term1),fol_Or())) { + for (scan = term_ArgumentList(term1); + !list_Empty(scan); + scan = list_Cdr(scan)) { + vec_Push((POINTER) polterm1); + vec_Push(list_Car(scan)); + } + } + } while (bottom != vec_ActMax()); + vec_SetMax(bottom); + misc_StartErrorReport(); + misc_ErrorReport("\n In cnf_GetFormulaPolarity: Wrong arguments !\n"); + misc_FinishErrorReport(); + return -2; +} + + +static BOOL cnf_ContainsDefinitionIntern(TERM TopDef, TERM Def, int Polarity, + TERM* FoundPred) +/********************************************************** + INPUT: A term TopDef which is the top level term of the recursion. + A term Def which is searched for a definition. + A pointer to a term into which the predicate of the definition + is stored if it is found. + RETURNS: TRUE if Def contains a definition that can be converted + to standard form. +********************************************************/ +{ + /* AND / OR */ + /* In these cases Def cannot be converted to standard form */ + + if ((symbol_Equal(term_TopSymbol(Def),fol_And()) && (Polarity == 1)) || + (symbol_Equal(term_TopSymbol(Def),fol_Or()) && (Polarity == -1))) + return FALSE; + + if (symbol_Equal(term_TopSymbol(Def), fol_And()) || + symbol_Equal(term_TopSymbol(Def),fol_Or())) { + /* Polarity is ok */ + LIST l; + for (l=term_ArgumentList(Def); !list_Empty(l); l=list_Cdr(l)) + if (cnf_ContainsDefinitionIntern(TopDef, list_Car(l), Polarity, FoundPred)) + return TRUE; + return FALSE; + } + + /* Quantifiers */ + if (fol_IsQuantifier(term_TopSymbol(Def))) + return cnf_ContainsDefinitionIntern(TopDef, term_SecondArgument(Def), Polarity, FoundPred); + + /* Negation */ + if (symbol_Equal(term_TopSymbol(Def),fol_Not())) + return cnf_ContainsDefinitionIntern(TopDef, term_FirstArgument(Def), -Polarity, FoundPred); + + /* Implication */ + if (symbol_Equal(term_TopSymbol(Def),fol_Implies())) { + if (Polarity==1) { + if (cnf_ContainsDefinitionIntern(TopDef, term_FirstArgument(Def), -Polarity, FoundPred)) + return TRUE; + return cnf_ContainsDefinitionIntern(TopDef, term_SecondArgument(Def), Polarity, FoundPred); + } + return FALSE; + } + + /* Equivalence */ + if (symbol_Equal(term_TopSymbol(Def),fol_Equiv()) && (Polarity==1)) { + /* Check if equivalence itself is in correct form */ + TERM defpredicate; + + defpredicate = cnf_IsDefinition(Def); + if (defpredicate != (TERM) NULL) { + LIST predicate_vars, l, defpath; + BOOL allquantifierfound; + TERM super; + int pol; + /* Check if predicate occurs several times in TopDef */ + /* if (cnf_PredicateOccurrences(TopDef, term_TopSymbol(defpredicate)) > 1) {} + puts("\n Predicate occurs more than once."); + return FALSE; */ + + + /* Now make sure that the variables of the predicate are */ + /* all--quantified and not in the scope of an exist quantifier */ + /* predicate_vars = list_Copy(term_ArgumentList(defpredicate)); */ + predicate_vars = term_ListOfVariables(defpredicate); + predicate_vars = term_DeleteDuplicatesFromList(predicate_vars); + + /* So far (going bottom--up) no all-quantifier was found for */ + /* a variable of the predicates' arguments */ + allquantifierfound = FALSE; + + /* Build defpath here by going bottom up */ + /* At first, list of superterms on path is top down */ + defpath = list_Nil(); + super = Def; + while (super != (TERM) NULL) { + defpath = list_Cons(super, defpath); + super = term_Superterm(super); + } + /* No go top down and add polarities */ + pol = 1; + for (l=defpath; !list_Empty(l); l=list_Cdr(l)) { + list_Rplaca(l, list_PairCreate((TERM) list_Car(l), (LIST) pol)); + if (symbol_Equal(term_TopSymbol((TERM) list_Car(l)), fol_Not())) + pol = -pol; + else { + if (symbol_Equal(term_TopSymbol((TERM) list_Car(l)), fol_Implies()) && + (term_FirstArgument((TERM) list_Car(l)) == (TERM) list_Car(list_Cdr(l)))) + pol = -pol; + else + if (symbol_Equal(term_TopSymbol((TERM) list_Car(l)), fol_Equiv())) + pol = 0; + } + } + /* <defpath> is now a list of pairs (term, polarity) */ + for (l=defpath; !list_Empty(l) && !list_Empty(predicate_vars); l=list_Cdr(l)) { + LIST pair; + TERM t; + int p; + /* Pair Term t / Polarity p */ + pair = (LIST) list_Car(l); + t = (TERM) list_PairFirst(pair); + p = (int) list_PairSecond(pair); + + if (fol_IsQuantifier(term_TopSymbol(t))) { + + /* Variables of the predicate that are universally quantified are no problem */ + if ((symbol_Equal(term_TopSymbol(t), fol_All()) && (p==1)) || + (symbol_Equal(term_TopSymbol(t), fol_Exist()) && (p==-1))) { + LIST scan; + allquantifierfound = TRUE; + for (scan=fol_QuantifierVariables(t); !list_Empty(scan); scan=list_Cdr(scan)) + predicate_vars = list_DeleteElement(predicate_vars,(TERM) list_Car(scan), + (BOOL (*)(POINTER,POINTER))term_Equal); + } + else { + /* Check if allquantified variables of the predicate are in scope of an exist--quantifier */ + /* We already found an all quantified variable */ + if (allquantifierfound) { + list_Delete(predicate_vars); + list_DeletePairList(defpath); + return FALSE; + } + else { + LIST scan; + /* Check if a variable of the predicate is exist--quantified */ + for (scan=fol_QuantifierVariables(t); !list_Empty(scan); scan=list_Cdr(scan)) { + if (term_ListContainsTerm(predicate_vars, list_Car(scan))) { + list_Delete(predicate_vars); + list_DeletePairList(defpath); + return FALSE; + } + } + } + } + } + } + +#ifdef CHECK + if (!list_Empty(predicate_vars)) { + list_Delete(predicate_vars); + misc_StartErrorReport(); + misc_ErrorReport("\n In cnf_ContainsDefinitionIntern: Definition has free variables.\n"); + misc_FinishErrorReport(); + } +#endif + list_DeletePairList(defpath); + *FoundPred = defpredicate; + return TRUE; + } + } + + return FALSE; +} + + +BOOL cnf_ContainsDefinition(TERM Def, TERM* FoundPred) +/********************************************************** + INPUT: A term Def which is searched for a definition of a predicate. + A pointer to a term into which the predicate of the definition + is stored if it is found. + RETURNS: TRUE if Def contains a definition that can be converted to + standard form. +***********************************************************/ +{ + BOOL result; +#ifdef CHECK + fol_CheckFatherLinks(Def); +#endif + result = cnf_ContainsDefinitionIntern(Def, Def, 1, FoundPred); +#ifdef CHECK + fol_CheckFatherLinks(Def); +#endif + return result; +} + + +static TERM cnf_IsDefinition(TERM Def) +/********************************************************** + INPUT: A term Def. + RETURNS: The Def term where the arguments of the equivalence are exchanged + iff the first one is not a predicate. +**********************************************************/ +{ + LIST l,freevars, predicatevars; + +#ifdef CHECK + if (Def == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cnf_IsDefinition: Empty formula.\n"); + misc_FinishErrorReport(); + } + if (!symbol_Equal(term_TopSymbol(Def),fol_Equiv())) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cnf_IsDefinition: Formula is no equivalence.\n"); + misc_FinishErrorReport(); + } +#endif + + /* If the predicate is the second argument of the equivalence, exchange them */ + if (!symbol_IsPredicate(term_TopSymbol(term_FirstArgument(Def)))) { + TERM arg1; + arg1 = term_FirstArgument(Def); + term_RplacFirstArgument(Def, term_SecondArgument(Def)); + term_RplacSecondArgument(Def, arg1); + } + + + /* Check if the first argument is a predicate */ + if (!symbol_IsPredicate(term_TopSymbol(term_FirstArgument(Def)))) + return NULL; + + /* Check if first argument is a predicate and not fol_Equality */ + /* if (!symbol_IsPredicate(term_TopSymbol(term_FirstArgument(Def))) + || symbol_Equal(term_TopSymbol(term_FirstArgument(Def)), fol_Equality()))) { + return NULL; + }*/ + + + /* The free variables of the non-predicate term must occur in the predicate term */ + + freevars = fol_FreeVariables(term_SecondArgument(Def)); + freevars = term_DeleteDuplicatesFromList(freevars); + predicatevars = term_ListOfVariables(term_FirstArgument(Def)); + predicatevars = term_DeleteDuplicatesFromList(predicatevars); + + for (l=predicatevars; !list_Empty(l); l=list_Cdr(l)) + freevars = list_DeleteElement(freevars, list_Car(l), + (BOOL (*)(POINTER,POINTER))term_Equal); + + if (!list_Empty(freevars)) { + list_Delete(freevars); + list_Delete(predicatevars); + return NULL; + } + + list_Delete(predicatevars); + return term_FirstArgument(Def); +} + + +static BOOL cnf_ContainsPredicateIntern(TERM Target, SYMBOL Predicate, + int Polarity, TERM* TargetPredicate, + TERM* ToTopLevel, LIST* TargetVars, + LIST* VarsForTopLevel) +/********************************************************** + INPUT: A term (sub--) Target + A symbol Predicate which is searched in the target term. + The polarity of the subterm. + A pointer to the term TargetPredicate into which the found + predicate term is stored. + A pointer to the list TargetVars into which the variables found + in the predicates' arguments are stored. + A pointer to a list VarsForTopLevel into which all variables are + stored that are all--quantified and can be moved to top level. + + RETURNS: TRUE if Formula contains the predicate for which a definition + was found. +********************************************************/ +{ + /* AND / OR */ + /* In these cases the predicate (if it exists) can not be moved to a higher level */ + + if ((symbol_Equal(term_TopSymbol(Target),fol_And()) && Polarity == 1) || + (symbol_Equal(term_TopSymbol(Target),fol_Or()) && Polarity == -1) || + (symbol_Equal(term_TopSymbol(Target),fol_Implies()) && Polarity != 1) || + symbol_Equal(term_TopSymbol(Target), fol_Equiv())) { + TERM s; + LIST l; + /* Try to find Predicate in Target */ + s = term_FindSubterm(Target, Predicate); + if (s == NULL) + return FALSE; + + /* Store variables found in the predicates arguments */ + for (l=term_ArgumentList(s); !list_Empty(l); l = list_Cdr(l)) + *TargetVars = list_Nconc(fol_FreeVariables((TERM) list_Car(l)), *TargetVars); + *TargetVars = term_DeleteDuplicatesFromList(*TargetVars); + /* Keep found predicate */ + *TargetPredicate = s; + *ToTopLevel = Target; + return TRUE; + } + + /* AND / OR continued */ + if (symbol_Equal(term_TopSymbol(Target),fol_And()) || symbol_Equal(term_TopSymbol(Target),fol_Or())) { + /* The polarity is ok here */ + LIST l; + for (l=term_ArgumentList(Target); !list_Empty(l); l = list_Cdr(l)) + if (cnf_ContainsPredicateIntern((TERM) list_Car(l), Predicate, Polarity, + TargetPredicate, ToTopLevel, TargetVars, + VarsForTopLevel)) + return TRUE; + return FALSE; + } + + /* Quantifiers */ + if (fol_IsQuantifier(term_TopSymbol(Target))) { + if (cnf_ContainsPredicateIntern(term_SecondArgument(Target), Predicate, + Polarity, TargetPredicate, ToTopLevel, + TargetVars, VarsForTopLevel)) { + /* Quantifiers for free variables of the predicate should be moved + to top level to make the proof easier */ + if ((symbol_Equal(term_TopSymbol(Target), fol_All()) && Polarity == 1) || + (symbol_Equal(term_TopSymbol(Target), fol_Exist()) && Polarity == -1)) { + LIST l; + /* Check for all variables found in the predicates arguments */ + for (l = *TargetVars; !list_Empty(l); l=list_Cdr(l)) { + if (term_ListContainsTerm(fol_QuantifierVariables(Target),list_Car(l))) + *VarsForTopLevel = list_Cons(list_Car(l), *VarsForTopLevel); + } + } + return TRUE; + } + return FALSE; + } + + /* Negation */ + if (symbol_Equal(term_TopSymbol(Target),fol_Not())) + return cnf_ContainsPredicateIntern(term_FirstArgument(Target), Predicate, + -Polarity, TargetPredicate, ToTopLevel, + TargetVars, VarsForTopLevel); + /* Implication */ + if (symbol_Equal(term_TopSymbol(Target),fol_Implies())) { + /* In this case the predicate (if it exists) can be moved to a higher level */ + if (cnf_ContainsPredicateIntern(term_FirstArgument(Target), Predicate, + -Polarity, TargetPredicate, ToTopLevel, + TargetVars, VarsForTopLevel)) + return TRUE; + return cnf_ContainsPredicateIntern(term_SecondArgument(Target), Predicate, + Polarity, TargetPredicate, ToTopLevel, + TargetVars, VarsForTopLevel); + } + + /* Found the predicate */ + if (symbol_Equal(term_TopSymbol(Target), Predicate)) { + LIST l; + for (l = term_ArgumentList(Target); !list_Empty(l); l = list_Cdr(l)) + *TargetVars = list_Nconc(fol_FreeVariables((TERM) list_Car(l)), *TargetVars); + *TargetVars = term_DeleteDuplicatesFromList(*TargetVars); + + *TargetPredicate = Target; + *ToTopLevel = Target; + return TRUE; + } + + /* In all other cases the predicate was not found */ + return FALSE; +} + + +BOOL cnf_ContainsPredicate(TERM Target, SYMBOL Predicate, + TERM* TargetPredicate, TERM* ToTopLevel, + LIST* TargetVars, LIST* VarsForTopLevel) +/********************************************************** + INPUT: A term Target without implications. + A symbol Predicate which is searched in the target term. + A pointer to the predicate found in TargetTerm is recorded. + A pointer to the term TargetPredicate into which the found + predicate term is stored. + A pointer to the list TargetVars into which the variables + found in the predicates' arguments are stored. + A pointer to a list VarsForTopLevel into which all variables + are stored that are all--quantified and can be moved to top level. + RETURNS: TRUE if Formula contains the predicate for which a definition + was found. +********************************************************/ +{ + BOOL result; +#ifdef CHECK + fol_CheckFatherLinks(Target); +#endif + result = cnf_ContainsPredicateIntern(Target, Predicate, 1, TargetPredicate, + ToTopLevel, TargetVars, VarsForTopLevel); +#ifdef CHECK + fol_CheckFatherLinks(Target); +#endif + return result; +} + + +static int cnf_PredicateOccurrences(TERM Term, SYMBOL P) +/**************************************************** + INPUT: A term and a predicate symbol. + RETURNS: The number of occurrences of the predicate symbol in Term +**************************************************/ +{ + /* Quantifiers */ + if (fol_IsQuantifier(term_TopSymbol(Term))) + return cnf_PredicateOccurrences(term_SecondArgument(Term), P); + + /* Junctors and NOT */ + if (fol_IsJunctor(term_TopSymbol(Term)) || + symbol_Equal(term_TopSymbol(Term),fol_Not())) { + LIST scan; + int count; + count = 0; + for (scan=term_ArgumentList(Term); !list_Empty(scan); scan=list_Cdr(scan)) { + count += cnf_PredicateOccurrences(list_Car(scan), P); + /* Only the cases count==1 and count>1 are important */ + if (count > 1) + return count; + } + return count; + } + + if (symbol_Equal(term_TopSymbol(Term), P)) + return 1; + return 0; +} + + +static TERM cnf_NegationNormalFormulaPath(TERM Term, TERM PredicateTerm) +/********************************************************** + INPUT: A term and a predicate term which is a subterm of term + RETURNS: The negation normal form of the term along the path. + CAUTION: The term is destructively changed. + This works only if the superterm member of Term and its subterms + are set. +********************************************************/ +{ + TERM subterm, termL, term1; + LIST scan; + SYMBOL symbol; + BOOL set; + + term1 = Term; + while (term1 != NULL) { + set = FALSE; + if (symbol_Equal(term_TopSymbol(term1),fol_Not())) { + subterm = term_FirstArgument(term1); + if (symbol_Equal(term_TopSymbol(subterm),fol_Not())) { + LIST l; + term_RplacTop(term1,term_TopSymbol(term_FirstArgument(subterm))); + list_Delete(term_ArgumentList(term1)); + term_RplacArgumentList(term1,term_ArgumentList(term_FirstArgument(subterm))); + term_Free(term_FirstArgument(subterm)); + list_Delete(term_ArgumentList(subterm)); + term_Free(subterm); + /* Set superterm member to new superterm */ + for (l=term_ArgumentList(term1); !list_Empty(l); l=list_Cdr(l)) + term_RplacSuperterm(list_Car(l), term1); + /* term1 weiter betrachten */ + set = TRUE; + } + else { + if (fol_IsQuantifier(term_TopSymbol(subterm))) { + LIST l; + symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); + termL = term_CreateAddFather(fol_Not(), + list_List(term_SecondArgument(subterm))); + list_RplacSecond(term_ArgumentList(subterm), termL); + term_RplacSuperterm(termL, subterm); + term_RplacTop(term1,symbol); + list_Delete(term_ArgumentList(term1)); + term_RplacArgumentList(term1, term_ArgumentList(subterm)); + for (l=term_ArgumentList(term1); !list_Empty(l); l = list_Cdr(l)) + term_RplacSuperterm(list_Car(l), term1); + term_RplacArgumentList(subterm, list_Nil()); + term_Delete(subterm); + term1 = termL; + /* Next term to check is not(subterm) */ + set = TRUE; + } + else { + if (symbol_Equal(term_TopSymbol(subterm),fol_Or()) || + (symbol_Equal(term_TopSymbol(subterm),fol_And()))) { + LIST l; + symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); + for (scan = term_ArgumentList(subterm); !list_Empty(scan); + scan = list_Cdr(scan)) { + TERM new; + termL = list_Car(scan); + new = term_CreateAddFather(fol_Not(),list_List(termL)); + list_Rplaca(scan, new); + term_RplacSuperterm(new, subterm); + } + term_RplacTop(term1,symbol); + list_Delete(term_ArgumentList(term1)); + term_RplacArgumentList(term1,term_ArgumentList(subterm)); + for (l = term_ArgumentList(term1); !list_Empty(l); l=list_Cdr(l)) + term_RplacSuperterm(list_Car(l), term1); + term_RplacArgumentList(subterm, list_Nil()); + term_Delete(subterm); + } + } + } + } + if (!set) { + if (!list_Empty(term_ArgumentList(term1))) + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) + if (term_HasProperSuperterm(PredicateTerm, list_Car(scan))) { + term1 = list_Car(scan); + set = TRUE; + break; + } + if (!set) + term1 = NULL; + } + } + return Term; +} + + +TERM cnf_ApplyDefinitionOnce(TERM Predicate, TERM Formula, TERM TargetTerm, + TERM TargetPredicate, FLAGSTORE Flags) +/********************************************************* + INPUT: A term Predicate which is a predicate found in a definition. + A term Formula which is a term equivalent to the predicate. + A term TargetTerm in which one occurrence of the predicate may be + replaced by the Formula. + A term TargetPredicate which is the subterm of the TargetTerm + to be replaced. + A flag store. + RETURNS: The changed TargetTerm. +*************************************************************/ +{ + SYMBOL maxvar, maxvar_temp; + LIST bound, scan; + BOOL success; + + /* Init varcounter */ + maxvar = term_MaxVar(TargetTerm); + maxvar_temp = term_MaxVar(Formula); + if (maxvar_temp > maxvar) + maxvar = maxvar_temp; + symbol_SetStandardVarCounter(maxvar); + + /* Find bound variables in formula for renaming them */ + bound = fol_BoundVariables(Formula); + for (scan=bound; !list_Empty(scan); scan=list_Cdr(scan)) { + /* Bound variable in definition is already used in term */ + if (term_ContainsSymbol(TargetTerm, term_TopSymbol(list_Car(scan)))) + term_ExchangeVariable(Formula, term_TopSymbol(list_Car(scan)), + symbol_CreateStandardVariable()); + } + list_Delete(bound); + TargetTerm = cnf_ApplyDefinitionInternOnce(Predicate, Formula, TargetTerm, + TargetPredicate,&success); + if (flag_GetFlagValue(Flags, flag_PAPPLYDEFS)) { + if (success) { + fputs("\nTarget after applying def:\n", stdout); + fol_PrettyPrint(TargetTerm); + puts("\n"); + } + } + + return TargetTerm; +} + + +static TERM cnf_ApplyDefinitionInternOnce(TERM Predicate, TERM Formula, + TERM TargetTerm, TERM TargetPredicate, + BOOL* Success) +/********************************************************** + INPUT: A term Predicate which is equivalence to + Formula and Term + RETURNS: The term in which all occurrences of P(..) are + replaced by Formula modulo the proper bindings + CAUTION: Term is destructively changed! +***********************************************************/ +{ + /* Quantifiers */ + if (fol_IsQuantifier(term_TopSymbol(TargetTerm))) { + term_RplacSecondArgument(TargetTerm, + cnf_ApplyDefinitionInternOnce(Predicate, Formula, + term_SecondArgument(TargetTerm), + TargetPredicate, Success)); + term_RplacSuperterm(term_SecondArgument(TargetTerm), TargetTerm); + return TargetTerm; + } + + /* Junctors and NOT */ + if (fol_IsJunctor(term_TopSymbol(TargetTerm)) || + symbol_Equal(term_TopSymbol(TargetTerm),fol_Not())) { + LIST scan; + for (scan=term_ArgumentList(TargetTerm); !list_Empty(scan); scan=list_Cdr(scan)) { + list_Rplaca(scan, cnf_ApplyDefinitionInternOnce(Predicate, Formula, + list_Car(scan), + TargetPredicate, Success)); + term_RplacSuperterm((TERM) list_Car(scan), TargetTerm); + } + return TargetTerm; + } + + if (symbol_Equal(term_TopSymbol(TargetTerm), term_TopSymbol(Predicate))) { + if (TargetTerm == TargetPredicate) { + TERM result; + result = Formula; + cnf_RplacVar(result, term_ArgumentList(Predicate), + term_ArgumentList(TargetTerm)); + term_AddFatherLinks(result); + term_Delete(TargetTerm); + *Success = TRUE; + return result; + } + } + + return TargetTerm; +} + + +static TERM cnf_RemoveEquivImplFromFormula(TERM term) +/********************************************************** + INPUT: A term. + RETURNS: The term with replaced implications and equivalences. + CAUTION: The term is destructively changed. +********************************************************/ +{ + TERM term1,termL,termR,termLneg,termRneg; + LIST scan; + int bottom,pol; + + bottom = vec_ActMax(); + vec_Push(term); + + while (bottom != vec_ActMax()) { + term1 = (TERM)vec_PopResult(); + if (symbol_Equal(term_TopSymbol(term1),fol_Implies())) { + term_RplacTop(term1, fol_Or()); + list_Rplaca(term_ArgumentList(term1), + term_Create(fol_Not(), list_List(list_Car(term_ArgumentList(term1))))); + }else + if (symbol_Equal(term_TopSymbol(term1),fol_Equiv())) { + pol = cnf_GetFormulaPolarity(term,term1); + termL = (TERM)list_Car(term_ArgumentList(term1)); + termR = (TERM)list_Second(term_ArgumentList(term1)); + termLneg = term_Create(fol_Not(),list_List(term_Copy(termL))); + termRneg = term_Create(fol_Not(),list_List(term_Copy(termR))); + if (pol == 1 || pol == 0) { + term_RplacTop(term1, fol_And()); + list_Rplaca(term_ArgumentList(term1), term_Create(fol_Or(),list_Cons(termLneg,list_List(termR)))); + list_RplacSecond(term_ArgumentList(term1),term_Create(fol_Or(),list_Cons(termRneg,list_List(termL)))); + }else + if (pol == -1) { + term_RplacTop(term1, fol_Or()); + list_Rplaca(term_ArgumentList(term1), term_Create(fol_And(),list_Cons(termLneg,list_List(termRneg)))); + list_RplacSecond(term_ArgumentList(term1), term_Create(fol_And(),list_Cons(termL,list_List(termR)))); + } + } + if (!list_Empty(term_ArgumentList(term1))) + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) + vec_Push(list_Car(scan)); + } + vec_SetMax(bottom); + return term; +} + + +static TERM cnf_MovePredicateVariablesUp(TERM Term, TERM TargetPredicateTerm, + LIST VarsForTopLevel) +/********************************************************** + INPUT: A term and a predicate term which is a subterm of term + an equivalence. + RETURNS: The term where the free variables of the equivalence, which + must be allquantified and not in the scope of an + exist quantifier, are moved to toplevel. + CAUTION: The term is destructively changed. +********************************************************/ +{ + TERM term1; + LIST scan; + int bottom; + + bottom = vec_ActMax(); + vec_Push(Term); + + while (bottom != vec_ActMax()) { + term1 = (TERM)vec_PopResult(); + if (!list_Empty(term_ArgumentList(term1))) + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) { + TERM arg; + arg = (TERM) list_Car(scan); + if (term_HasProperSuperterm(TargetPredicateTerm, arg)) { + if (symbol_Equal(term_TopSymbol(arg), fol_All())) { + LIST predicatevarscan, quantifiervars; + quantifiervars = fol_QuantifierVariables(arg); + for (predicatevarscan=VarsForTopLevel; !list_Empty(predicatevarscan); + predicatevarscan = list_Cdr(predicatevarscan)) + quantifiervars = list_DeleteElementFree(quantifiervars, + (TERM) list_Car(predicatevarscan), + (BOOL (*)(POINTER,POINTER))term_Equal, + (void (*)(POINTER))term_Delete); + if (!list_Empty(quantifiervars)) + term_RplacArgumentList(term_FirstArgument(arg), quantifiervars); + else { + TERM subterm; + subterm = term_SecondArgument(arg); + term_Free(term_FirstArgument(arg)); + list_Delete(term_ArgumentList(arg)); + term_Free(arg); + list_Rplaca(scan, subterm); + term_RplacSuperterm(subterm, term1); + } + } + vec_Push((TERM) list_Car(scan)); + } + } + } + + for (scan=VarsForTopLevel; !list_Empty(scan); scan = list_Cdr(scan)) + list_Rplaca(scan, term_Copy((TERM) list_Car(scan))); + if (symbol_Equal(term_TopSymbol(Term), fol_All())) { + LIST vars; + vars = fol_QuantifierVariables(Term); + vars = list_Nconc(vars, list_Copy(VarsForTopLevel)); + vars = term_DestroyDuplicatesInList(vars); + term_RplacArgumentList(term_FirstArgument(Term), vars); + } + else { + TERM newtop; + newtop = fol_CreateQuantifier(fol_All(), list_Copy(VarsForTopLevel), list_List(Term)); + term_RplacSuperterm(Term, newtop); + Term = newtop; + } + vec_SetMax(bottom); + return Term; +} + + +static TERM cnf_RemoveImplFromFormulaPath(TERM Term, TERM PredicateTerm) +/********************************************************** + INPUT: A term and a predicate term which is a subterm of term + RETURNS: The term where implications along the path to PredicateTerm + are replaced. + CAUTION: The term is destructively changed. + This works only if the superterm member of Term and its + subterms are set. +********************************************************/ +{ + TERM term1; + LIST scan; + int bottom; + + bottom = vec_ActMax(); + vec_Push(Term); + + while (bottom != vec_ActMax()) { + term1 = (TERM)vec_PopResult(); + if (term_HasProperSuperterm(PredicateTerm, term1)) { + if (symbol_Equal(term_TopSymbol(term1),fol_Implies())) { + TERM newterm; + term_RplacTop(term1, fol_Or()); + newterm = term_CreateAddFather(fol_Not(), list_List(list_Car(term_ArgumentList(term1)))); + list_Rplaca(term_ArgumentList(term1), newterm); + term_RplacSuperterm(newterm, term1); + } + + if (!list_Empty(term_ArgumentList(term1))) + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) + vec_Push(list_Car(scan)); + } + } + vec_SetMax(bottom); + return Term; +} + + +static SYMBOL cnf_GetDualSymbol(SYMBOL symbol) +/******************************************************** + INPUT: A predefined symbol. + RETURNS: The dual symbol. +********************************************************/ +{ + SYMBOL dual; + + dual = symbol; + if (symbol_Equal(symbol,fol_All())) + dual = fol_Exist(); + else + if (symbol_Equal(symbol,fol_Exist())) + dual = fol_All(); + else + if (symbol_Equal(symbol,fol_Or())) + dual = fol_And(); + else + if (symbol_Equal(symbol,fol_And())) + dual = fol_Or(); + return dual; +} + + +TERM cnf_NegationNormalFormula(TERM term) +/******************************************************** + INPUT: A term. + RETURNS: The negation normal form of the term. + CAUTION: The term is destructively changed. +********************************************************/ +{ + TERM term1,subterm,termL; + LIST scan; + SYMBOL symbol; + int bottom; + + bottom = vec_ActMax(); + vec_Push(term); + + while (bottom != vec_ActMax()) { + term1 = (TERM)vec_PopResult(); + if (symbol_Equal(term_TopSymbol(term1),fol_Not())) { + subterm = (TERM)list_Car(term_ArgumentList(term1)); + if (symbol_Equal(term_TopSymbol(subterm),fol_Not())) { + term_RplacTop(term1,term_TopSymbol(term_FirstArgument(subterm))); + list_Delete(term_ArgumentList(term1)); + term_RplacArgumentList(term1,term_ArgumentList(term_FirstArgument(subterm))); + term_Free(term_FirstArgument(subterm)); + list_Delete(term_ArgumentList(subterm)); + term_Free(subterm); + vec_Push(term1); + }else + if (fol_IsQuantifier(term_TopSymbol(subterm))) { + symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); + termL = term_Create(fol_Not(), + list_List(term_SecondArgument(subterm))); + list_RplacSecond(term_ArgumentList(subterm), termL); + term_RplacTop(term1,symbol); + list_Delete(term_ArgumentList(term1)); + term_RplacArgumentList(term1,term_CopyTermList(term_ArgumentList(subterm))); + term_Delete(subterm); + } else + if (symbol_Equal(term_TopSymbol(subterm),fol_Or()) || + symbol_Equal(term_TopSymbol(subterm),fol_And())) { + symbol = (SYMBOL)cnf_GetDualSymbol(term_TopSymbol(subterm)); + for (scan = term_ArgumentList(subterm); + !list_Empty(scan); + scan = list_Cdr(scan)) { + termL = (TERM)list_Car(scan); + list_Rplaca(scan, term_Create(fol_Not(),list_List(termL))); + } + term_RplacTop(term1,symbol); + list_Delete(term_ArgumentList(term1)); + term_RplacArgumentList(term1,term_CopyTermList(term_ArgumentList(subterm))); + term_Delete(subterm); + } + } + if (!list_Empty(term_ArgumentList(term1))) + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) + vec_Push(list_Car(scan)); + } + vec_SetMax(bottom); + return term; +} + + +static TERM cnf_QuantMakeOneVar(TERM term) +/************************************************************** + INPUT: A term. + RETURNS: The term where all quantifiers quantify over only one variable. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + TERM term1,termL; + SYMBOL quantor; + LIST scan,varlist; + int bottom; + + bottom = vec_ActMax(); + vec_Push(term); + + while (bottom != vec_ActMax()) { + term1 = (TERM)vec_PopResult(); + if (fol_IsQuantifier(term_TopSymbol(term1))) { + quantor = term_TopSymbol(term1); + if (list_Length(term_ArgumentList(term_FirstArgument(term1))) > 1) { + varlist = + list_Copy(list_Cdr(term_ArgumentList(term_FirstArgument(term1)))); + for (scan=varlist;!list_Empty(scan);scan=list_Cdr(scan)) { + termL = term_SecondArgument(term1); + term_RplacSecondArgument(term1, fol_CreateQuantifier(quantor,list_List(list_Car(scan)),list_List(termL))); + } + for (scan=varlist;!list_Empty(scan);scan=list_Cdr(scan)) { + term_RplacArgumentList(term_FirstArgument(term1), + list_PointerDeleteElement(term_ArgumentList(term_FirstArgument(term1)),list_Car(scan))); + } + list_Delete(varlist); + } + } + if (!list_Empty(term_ArgumentList(term1))) + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) + vec_Push(list_Car(scan)); + } + vec_SetMax(bottom); + return term; +} + + +static LIST cnf_GetSymbolList(LIST varlist) +/************************************************************** + INPUT: A list of variables + RETURNS: The list of the symbols of the variables. +***************************************************************/ +{ + LIST scan,result; + + result = list_Nil(); + for (scan=varlist;!list_Empty(scan);scan=list_Cdr(scan)) + result = list_Cons((POINTER)term_TopSymbol((TERM)list_Car(scan)),result); + + return result; +} + + +static BOOL cnf_TopIsAnd(LIST termlist) +/************************************************************** + INPUT: A list of terms. + RETURNS: True if one term in termlist is a conjunction. +***************************************************************/ +{ + LIST scan; + + for (scan=termlist;!list_Empty(scan);scan=list_Cdr(scan)) + if (term_TopSymbol(list_Car(scan)) == fol_And()) + return TRUE; + return FALSE; +} + + +static TERM cnf_MakeOneOr(TERM term) +/************************************************************** + INPUT: A term. + RETURNS: Takes all arguments of an or together. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + + LIST scan; + + if (symbol_Equal(term_TopSymbol(term),fol_Or())) { + TERM argterm; + scan=term_ArgumentList(term); + while (!list_Empty(scan)) { + argterm = (TERM)list_Car(scan); + cnf_MakeOneOr(argterm); + if (symbol_Equal(term_TopSymbol(argterm),fol_Or())) { + scan = list_Cdr(scan); + term_RplacArgumentList(term, + list_Nconc(term_ArgumentList(argterm),list_PointerDeleteElement(term_ArgumentList(term),argterm))); + term_Free(argterm); + } + else + scan = list_Cdr(scan); + } + } else if (!symbol_IsPredicate(term_TopSymbol(term))) + for (scan=term_ArgumentList(term);!list_Empty(scan);scan=list_Cdr(scan)) + cnf_MakeOneOr(list_Car(scan)); + + return term; +} + + +static TERM cnf_MakeOneOrPredicate(TERM term) +/************************************************************** + INPUT: A term. + RETURNS: Takes all predicates and negated predicates as arguments + of an or together. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + + LIST scan,scan1,predlist; + + if (cnf_TopIsAnd(term_ArgumentList(term))) { + + for (scan1=term_ArgumentList(term); + !(list_Empty(scan1) || symbol_Equal(term_TopSymbol(list_Car(scan1)),fol_And())); + scan1=list_Cdr(scan1)); + + if (!list_Empty(scan1)) { + predlist = list_Nil(); + for (scan=scan1; !list_Empty(scan); scan=list_Cdr(scan)) { + if (symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || + fol_IsNegativeLiteral(list_Car(scan))) { + predlist = list_Cons(list_Car(scan),predlist); + } + } + for (scan=predlist;!list_Empty(scan);scan=list_Cdr(scan)) + term_RplacArgumentList(term, + list_PointerDeleteElement(term_ArgumentList(term),list_Car(scan))); + + if (!list_Empty(predlist)) + term_RplacArgumentList(term, list_Nconc(predlist,term_ArgumentList(term))); + } + } + return term; +} + + +static TERM cnf_MakeOneOrTerm(TERM term) +/************************************************************** + INPUT: A term. + RETURNS: Takes all predicates as arguments of an or together. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + return cnf_MakeOneOrPredicate(cnf_MakeOneOr(term)); +} + + +static TERM cnf_MakeOneAnd(TERM term) +/************************************************************** + INPUT: A term. + RETURNS: Takes all arguments of an and together. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + LIST scan; + + if (symbol_Equal(term_TopSymbol(term),fol_And())) { + TERM argterm; + scan=term_ArgumentList(term); + while (!list_Empty(scan)) { + argterm = (TERM)list_Car(scan); + cnf_MakeOneAnd(argterm); + if (symbol_Equal(term_TopSymbol(argterm),fol_And())) { + scan = list_Cdr(scan); + term_RplacArgumentList(term, + list_Nconc(term_ArgumentList(argterm),list_PointerDeleteElement(term_ArgumentList(term),argterm))); + term_Free(argterm); + } + else + scan = list_Cdr(scan); + } + } else if (!symbol_IsPredicate(term_TopSymbol(term))) + for (scan=term_ArgumentList(term);!list_Empty(scan);scan=list_Cdr(scan)) + cnf_MakeOneAnd(list_Car(scan)); + + return term; +} + + +static TERM cnf_MakeOneAndPredicate(TERM term) +/************************************************************** + INPUT: A term. + RETURNS: Takes all predicates as arguments of one or together. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + LIST scan,scan1,predlist; + + for (scan1=term_ArgumentList(term); + !(list_Empty(scan1) || symbol_Equal(term_TopSymbol(list_Car(scan1)),fol_Or())); + scan1=list_Cdr(scan1)); + + if (!list_Empty(scan1)) { + /* The car of scan1 points to a term with topsymbol 'or' */ + predlist = list_Nil(); + for (scan=scan1; !list_Empty(scan); scan=list_Cdr(scan)) { + if (symbol_IsPredicate(term_TopSymbol(list_Car(scan))) && + fol_IsNegativeLiteral(list_Car(scan))) { + predlist = list_Cons(list_Car(scan),predlist); + } + } + for (scan=predlist; !list_Empty(scan); scan=list_Cdr(scan)) + term_RplacArgumentList(term, list_PointerDeleteElement(term_ArgumentList(term),list_Car(scan))); + + if (!list_Empty(predlist)) + term_RplacArgumentList(term, list_Nconc(predlist,term_ArgumentList(term))); + } + return term; +} + + +static TERM cnf_MakeOneAndTerm(TERM term) +/************************************************************** + INPUT: A term. + RETURNS: Takes all predicates as arguments of an or together. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + return cnf_MakeOneAndPredicate(cnf_MakeOneAnd(term)); +} + + +LIST cnf_ComputeLiteralLists(TERM Term) +/********************************************************** + INPUT: A term in negation normal form without quantifiers. + RETURNS: The list of all literal lists corresponding to the + CNF of Term. +***********************************************************/ +{ + LIST Scan, Scan1, Scan2, Help, Result, List1, List2, NewResult; + SYMBOL Symbol; + + Symbol = term_TopSymbol(Term); + Result = list_Nil(); + + if (symbol_Equal(Symbol,fol_Or())) { + Result = cnf_ComputeLiteralLists(list_Car(term_ArgumentList(Term))); + for (Scan=list_Cdr(term_ArgumentList(Term));!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Help = cnf_ComputeLiteralLists(list_Car(Scan)); + NewResult = list_Nil(); + for (Scan1=Help;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) + for (Scan2=Result;!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) { + List1 = list_Car(Scan1); + List2 = list_Car(Scan2); + if (!list_Empty(list_Cdr(Scan2))) + List1 = term_CopyTermList(List1); + if (!list_Empty(list_Cdr(Scan1))) + List2 = term_CopyTermList(List2); + NewResult = list_Cons(term_DestroyDuplicatesInList(list_Nconc(List1,List2)), + NewResult); + } + list_Delete(Help); + list_Delete(Result); + Result = NewResult; + } + return Result; + } + + if (symbol_Equal(Symbol,fol_And())) { + Result = cnf_ComputeLiteralLists(list_Car(term_ArgumentList(Term))); + for (Scan=list_Cdr(term_ArgumentList(Term));!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Result = list_Nconc(cnf_ComputeLiteralLists(list_Car(Scan)), Result); + } + return Result; + } + + if (symbol_Equal(Symbol,fol_Not()) || symbol_IsPredicate(Symbol)) + return list_List(list_List(term_Copy(Term))); + + + misc_StartErrorReport(); + misc_ErrorReport("\n In cnf_ComputeLiteralLists: Unexpected junctor in input Formula!\n"); + misc_FinishErrorReport(); + + return Result; +} + + +static TERM cnf_DistributiveFormula(TERM Formula) +/************************************************************** + INPUT: A Formula in NNF which consists only of disjunctions and + conjunctions. + RETURNS: The Formula where the distributivity rule is exhaustively applied + and all disjunctions and the top level conjunction are grouped. + CAUTION: The Formula is destructively changed. +***************************************************************/ +{ + TERM Result; + LIST Scan, Lists; + + Lists = cnf_ComputeLiteralLists(Formula); + + for (Scan= Lists; !list_Empty(Scan); Scan=list_Cdr(Scan)) + list_Rplaca(Scan,term_Create(fol_Or(), list_Car(Scan))); + + Result = term_Create(fol_And(), Lists); + term_Delete(Formula); + + return Result; +} + + + +void cnf_FPrintClause(TERM term, FILE* file) +/************************************************************** + INPUT: A term and a file pointer. + RETURNS: Nothing. + EFFECT: Print the term which contains only disjunctions to file. + The disjunctions represent a clause. +***************************************************************/ +{ + + TERM term1; + LIST scan; + int bottom; + + bottom = vec_ActMax(); + vec_Push(term); + + while (bottom != vec_ActMax()) { + term1 = (TERM)vec_PopResult(); + if (symbol_Equal(term_TopSymbol(term1),fol_Or())) { + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) + vec_Push(list_Car(scan)); + }else + term_FPrint(file,term1); + } + fputs(".\n", file); + vec_SetMax(bottom); +} + + +void cnf_FPrint(TERM term, FILE* file) +/************************************************************** + INPUT: A term and a file pointer. + RETURNS: Nothing. + EFFECT: Print the term (in negation normal form) + which contains only conjunctions of + disjunctions to file. The conjunctions are interpreted + to represent different clauses. +***************************************************************/ +{ + TERM term1; + LIST scan; + int bottom; + + bottom = vec_ActMax(); + vec_Push(term); + + while (bottom != vec_ActMax()) { + term1 = (TERM)vec_PopResult(); + if (symbol_Equal(term_TopSymbol(term1),fol_And())) { + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) + vec_Push(list_Car(scan)); + }else + if (symbol_Equal(term_TopSymbol(term1),fol_Or()) || + symbol_IsPredicate(term_TopSymbol(term1)) || + symbol_Equal(term_TopSymbol(term1),fol_Not())) + cnf_FPrintClause(term1,file); + } + vec_SetMax(bottom); +} + + +void cnf_StdoutPrint(TERM term) +/************************************************************** + INPUT: A term. + RETURNS: Nothing. + EFFECT: Print the term (in negation normal form) + which contains only conjunctions of + disjunctions to standard out. The conjunctions are interpreted + to represent different clauses. +***************************************************************/ +{ + LIST termlist,scan,scan1; + + for (scan=term_ArgumentList(term); !list_Empty(scan); scan=list_Cdr(scan)) { + termlist = list_Nil(); + if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || + fol_IsNegativeLiteral(list_Car(scan)))) + termlist = term_ArgumentList(list_Car(scan)); + + if (!list_Empty(termlist)) { + for (scan1=termlist;!list_Empty(scan1);scan1=list_Cdr(scan1)) + term_Print(list_Car(scan1)); + puts("."); + }else{ + term_Print(list_Car(scan)); + puts("."); + } + } +} + + +void cnf_FilePrint(TERM term, FILE* file) +/************************************************************** + INPUT: A term and a file. + RETURNS: Nothing. + EFFECT: Print the term (in negation normal form) + which contains only conjunctions of + disjunctions to file. The conjunctions are interpreted + to represent different clauses. +***************************************************************/ +{ + LIST termlist,scan,scan1; + + for (scan=term_ArgumentList(term); !list_Empty(scan); scan=list_Cdr(scan)) { + termlist = list_Nil(); + if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || + fol_IsNegativeLiteral(list_Car(scan)))) + termlist = term_ArgumentList(list_Car(scan)); + + if (!list_Empty(termlist)) { + for (scan1=termlist;!list_Empty(scan1);scan1=list_Cdr(scan1)) + term_FPrint(file,list_Car(scan1)); + fputs(".\n", file); + }else{ + term_FPrint(file,list_Car(scan)); + fputs(".\n", file); + } + } + +} + + +void cnf_FilePrintPrefix(TERM term, FILE* file) +/************************************************************** + INPUT: A term and a file pointer. + RETURNS: Nothing. + EFFECT: Prefix Print the term (in negation normal form) + which contains only conjunctions of + disjunctions to file. The conjunctions are interpreted + to represent different clauses. +***************************************************************/ +{ + LIST termlist,scan,scan1; + + for (scan=term_ArgumentList(term);!list_Empty(scan);scan=list_Cdr(scan)) { + termlist = list_Nil(); + if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || + fol_IsNegativeLiteral(list_Car(scan)))) + termlist = term_ArgumentList(list_Car(scan)); + + if (!list_Empty(termlist)) { + for (scan1=termlist;!list_Empty(scan1);scan1=list_Cdr(scan1)) { + term_FPrintPrefix(file,list_Car(scan1)); + if (!list_Empty(list_Cdr(scan1))) + fputs(" | ", file); + } + fputs(".\n", file); + } else { + term_FPrintPrefix(file,list_Car(scan)); + fputs(".\n", file); + } + } +} + + +static LIST cnf_SubsumeClauseList(LIST clauselist) +/********************************************************** + INPUT: A list of clauses. + RETURNS: The list of clauses without subsumed clauses. + CAUTION: The list is destructively changed. +***********************************************************/ +{ + LIST scan,result; + st_INDEX stindex; + CLAUSE actclause; + + stindex = st_IndexCreate(); + result = list_Nil(); + + for (scan = clauselist; !list_Empty(scan); scan=list_Cdr(scan)) + res_InsertClauseIndex(list_Car(scan),stindex); + + for (scan=clauselist; !list_Empty(scan); scan=list_Cdr(scan)) { + actclause = list_Car(scan); + res_DeleteClauseIndex(actclause,stindex); + if (!res_BackSubWithLength(actclause,stindex)) { + res_InsertClauseIndex(actclause,stindex); + result = list_Cons(actclause,result); + } + } + if (list_Length(result) != list_Length(clauselist)) { + for (scan = result; !list_Empty(scan); scan=list_Cdr(scan)) + clauselist = list_PointerDeleteElement(clauselist,list_Car(scan)); + if (!list_Empty(result)) + clause_DeleteClauseList(clauselist); + }else + list_Delete(clauselist); + st_IndexDelete(stindex); + return result; +} + + +static LIST cnf_MakeClauseList(TERM term, BOOL Sorts, BOOL Conclause, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A term in cnf and two boolean values indicating + whether sorts should be generated and whether the + generated clauses are Conclauses, a flag store and + a precedence. + RETURNS: A list of clauses with respect to term. The terms + in the new clauses are the copied subterms from term. + EFFECT: The flag store and the precedence are not changed, + but they're needed for creating clauses. +***************************************************************/ +{ + LIST termlist,scan,clauselist,newclauselist,delclauselist,condlist; + CLAUSE clause; + int j; + + termlist = list_Nil(); + clauselist = list_Nil(); + + if (fol_IsTrue(term)) + return clauselist; + + if (fol_IsNegativeLiteral(term) || symbol_IsPredicate(term_TopSymbol(term))) { + termlist = list_List(term_Copy(term)); + clause = clause_CreateFromLiterals(termlist, Sorts, Conclause,TRUE, + Flags, Precedence); + clauselist = list_Nconc(clauselist,list_List(clause)); + term_StartMinRenaming(); + term_Rename(clause_GetLiteralTerm(clause,0)); + list_Delete(termlist); + return clauselist; + } + + delclauselist = list_Nil(); + term = cnf_MakeOneAndTerm(term); + if (symbol_Equal(term_TopSymbol(term), fol_And())) { + for (scan=term_ArgumentList(term); !list_Empty(scan); scan=list_Cdr(scan)) { + list_Rplaca(scan, cnf_MakeOneOrTerm(list_Car(scan))); + termlist = list_Nil(); + if (!(symbol_IsPredicate(term_TopSymbol(list_Car(scan))) || + fol_IsNegativeLiteral(list_Car(scan)))) { + termlist = term_CopyTermList(term_ArgumentList(list_Car(scan))); + termlist = term_DestroyDuplicatesInList(termlist); + } else + termlist = list_List(term_Copy(list_Car(scan))); + + if (!list_Empty(termlist)) { + clause = clause_CreateFromLiterals(termlist, Sorts, Conclause, TRUE, + Flags, Precedence); + term_StartMinRenaming(); + for (j = 0; j < clause_Length(clause); j++) + term_Rename(clause_GetLiteralTerm(clause,j)); + clauselist = list_Cons(clause,clauselist); + list_Delete(termlist); + } + } + } else { + /* Here the term is a disjunction, i.e. there is only one clause */ + term = cnf_MakeOneOrTerm(term); + if (!(symbol_IsPredicate(term_TopSymbol(term)) || + fol_IsNegativeLiteral(term))) { + termlist = term_CopyTermList(term_ArgumentList(term)); + termlist = term_DestroyDuplicatesInList(termlist); + } else + termlist = list_List(term_Copy(term)); + + if (!list_Empty(termlist)) { + clause = clause_CreateFromLiterals(termlist, Sorts, Conclause, TRUE, + Flags, Precedence); + term_StartMinRenaming(); + for (j = 0; j < clause_Length(clause); j++) + term_Rename(clause_GetLiteralTerm(clause,j)); + clauselist = list_Cons(clause,clauselist); + list_Delete(termlist); + } + } + + for (scan=clauselist; !list_Empty(scan); scan=list_Cdr(scan)) { + condlist = cond_CondFast(list_Car(scan)); + if (!list_Empty(condlist)) + clause_DeleteLiterals(list_Car(scan), condlist, Flags, Precedence); + list_Delete(condlist); + } + clauselist = cnf_SubsumeClauseList(clauselist); + newclauselist = list_Nil(); + while (!list_Empty(clauselist)) { + clause = res_SelectLightestClause(clauselist); + newclauselist = list_Nconc(newclauselist,list_List(clause)); + clauselist = list_PointerDeleteElement(clauselist,clause); + } + list_Delete(clauselist); + for (scan=newclauselist; !list_Empty(scan); scan=list_Cdr(scan)) { + if (res_HasTautology(list_Car(scan))) + delclauselist = list_Cons(list_Car(scan),delclauselist); + } + for (scan=delclauselist; !list_Empty(scan); scan=list_Cdr(scan)) + newclauselist = list_PointerDeleteElement(newclauselist,list_Car(scan)); + clause_DeleteClauseList(delclauselist); + + return newclauselist; +} + + +TERM cnf_Flatten(TERM Term, SYMBOL Symbol) +/************************************************************** + INPUT: A <Term> and <Symbol> that is assumed to be associative. + RETURNS: If the top symbol of <Term> is <Symbol> the <Term> is flattened + as long as it contains further direct subterms starting with <Symbol> + CAUTION: The term is destructively changed. +***************************************************************/ +{ + LIST Scan1,Scan2; + + if (symbol_Equal(term_TopSymbol(Term), Symbol)) { + TERM Argterm; + Scan1 =term_ArgumentList(Term); + while (!list_Empty(Scan1)) { + Argterm = (TERM)list_Car(Scan1); + Scan2 = list_Cdr(Scan1); + if (symbol_Equal(term_TopSymbol(Argterm),Symbol)) { + cnf_Flatten(Argterm,Symbol); + list_NInsert(Scan1,list_Cdr(term_ArgumentList(Argterm))); /* Be efficient ... */ + list_Rplaca(Scan1,list_Car(term_ArgumentList(Argterm))); + list_Free(term_ArgumentList(Argterm)); + term_Free(Argterm); + } + Scan1 = Scan2; + } + } + return Term; +} + + +static TERM cnf_FlattenPath(TERM Term, TERM PredicateTerm) +/************************************************************** + INPUT: A <Term> and <Symbol> that is assumed to be associative, + and a predicate term which is a subterm of term + RETURNS: If the top symbol of <Term> is <Symbol> the <Term> is flattened + as long as it contains further direct subterms starting with <Symbol> + CAUTION: The term is destructively changed. +***************************************************************/ +{ + TERM subterm; + + subterm = Term; + while (symbol_Equal(term_TopSymbol(subterm), fol_All())) + subterm = term_SecondArgument(subterm); + + if (symbol_Equal(term_TopSymbol(subterm), fol_Or())) { + TERM Argterm; + LIST scan1; + scan1 = term_ArgumentList(subterm); + while (!list_Empty(scan1)) { + LIST scan2; + Argterm = (TERM)list_Car(scan1); + scan2 = list_Cdr(scan1); + if (term_HasProperSuperterm(PredicateTerm, Argterm)) { + if (symbol_Equal(term_TopSymbol(Argterm),fol_Or())) { + LIST l; + cnf_Flatten(Argterm,fol_Or()); + for (l=term_ArgumentList(Argterm); !list_Empty(l); l=list_Cdr(l)) + term_RplacSuperterm((TERM) list_Car(l), subterm); + list_NInsert(scan1,list_Cdr(term_ArgumentList(Argterm))); /* Be efficient ... */ + list_Rplaca(scan1,list_Car(term_ArgumentList(Argterm))); + list_Free(term_ArgumentList(Argterm)); + term_Free(Argterm); + } + } + scan1 = scan2; + } + } + return Term; +} + + +static void cnf_DistrQuantorNoVarSub(TERM Term) +/************************************************************** + INPUT: A formula in negation normal form starting with a universal + (existential) quantifier and a disjunction (conjunction) as argument. + EFFECT: The Quantor is distributed if possible. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + LIST Variables,Subformulas,Scan1,Scan2,Rest; + TERM Subterm,Var,NewForm; + SYMBOL Subtop,Top; + + Top = term_TopSymbol(Term); + Variables = list_Copy(fol_QuantifierVariables(Term)); + Subterm = term_SecondArgument(Term); + Subtop = term_TopSymbol(Subterm); + Subterm = cnf_Flatten(Subterm,Subtop); + + for (Scan1=Variables;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { + Subformulas = list_Nil(); + Var = (TERM)list_Car(Scan1); + for (Scan2=term_ArgumentList(Subterm);!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) + if (!fol_VarOccursFreely(Var,list_Car(Scan2))) + Subformulas = list_Cons(list_Car(Scan2),Subformulas); + if (!list_Empty(Subformulas)) { + Rest = list_NPointerDifference(term_ArgumentList(Subterm),Subformulas); + if (list_Empty(list_Cdr(Rest))) { /* One subformula */ + if (symbol_Equal(Top,term_TopSymbol(list_Car(Rest)))) { /* Optimization: quantifier still exist */ + NewForm = (TERM)list_Car(Rest); + term_RplacArgumentList(term_FirstArgument(NewForm), + list_Cons((POINTER)Var,fol_QuantifierVariables(NewForm))); + list_Delete(Rest); + } + else + NewForm = fol_CreateQuantifier(Top,list_List((POINTER)Var),Rest); + } + else + NewForm = fol_CreateQuantifier(Top,list_List((POINTER)Var),list_List(term_Create(Subtop,Rest))); + term_RplacArgumentList(Subterm,list_Cons(NewForm,Subformulas)); + term_RplacArgumentList(term_FirstArgument(Term), + list_PointerDeleteElement(fol_QuantifierVariables(Term),(POINTER)Var)); + } + } + + if (list_Empty(fol_QuantifierVariables(Term))) { /* All variables moved inside */ + term_Free(term_FirstArgument(Term)); + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,Subtop); + term_RplacArgumentList(Term,term_ArgumentList(Subterm)); + term_Free(Subterm); + } + list_Delete(Variables); +} + + +static TERM cnf_AntiPrenex(TERM Term) +/************************************************************** + INPUT: A formula in negation normal form. + RETURNS: The term after application of anti-prenexing. Quantifiers + are moved inside as long as possible. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + LIST Scan; + SYMBOL Top; + + Top = term_TopSymbol(Term); + + if (fol_IsQuantifier(Top)) { + TERM Subterm,Actterm; + SYMBOL DistrSymb,Subtop; /* The junctor the respective quantifier distributes over */ + + Subterm = term_SecondArgument(Term); + Subtop = term_TopSymbol(Subterm); + + if (!symbol_IsPredicate(Subtop) && + !symbol_Equal(Subtop,fol_Not())) { /* Formula in NNF: No Literals or Atoms */ + if (symbol_Equal(Top,fol_All())) + DistrSymb = fol_And(); + else + DistrSymb = fol_Or(); + if (fol_IsQuantifier(Subtop)) { + cnf_AntiPrenex(Subterm); + Subtop = term_TopSymbol(Subterm); + } + if (symbol_Equal(Subtop,DistrSymb)) { + LIST Variables; + LIST NewVars; + Variables = fol_QuantifierVariables(Term); + Subterm = cnf_Flatten(Subterm,DistrSymb); + for (Scan=term_ArgumentList(Subterm);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Actterm = (TERM)list_Car(Scan); + NewVars = list_NIntersect(fol_FreeVariables(Actterm),Variables, + (BOOL (*)(POINTER,POINTER))term_Equal); + if (!list_Empty(NewVars)) { + if (symbol_Equal(Top,term_TopSymbol(Actterm))) { /* Quantor already there */ + term_CopyTermsInList(NewVars); + term_RplacArgumentList(term_FirstArgument(Actterm), + list_Nconc(fol_QuantifierVariables(Actterm), + NewVars)); + } + else { + term_CopyTermsInList(NewVars); + list_Rplaca(Scan,fol_CreateQuantifier(Top, NewVars, list_List(Actterm))); + } + } + } + term_Delete(term_FirstArgument(Term)); /* Delete old variable list */ + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,DistrSymb); + term_RplacArgumentList(Term,term_ArgumentList(Subterm)); + term_Free(Subterm); + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + list_Rplaca(Scan,cnf_AntiPrenex(list_Car(Scan))); + } + else + if (!fol_IsQuantifier(Subtop)) { + cnf_DistrQuantorNoVarSub(Term); + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + cnf_AntiPrenex(list_Car(Scan)); + } + } + } + else + if (!symbol_Equal(Top,fol_Not()) && !symbol_IsPredicate(Top)) + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + cnf_AntiPrenex(list_Car(Scan)); + + return Term; +} + + +static void cnf_DistrQuantorNoVarSubPath(TERM Term, TERM PredicateTerm) +/************************************************************** + INPUT: A formula in negation normal form starting with a universal + (existential) quantifier and a disjunction (conjunction) as argument + and a predicate term which is a subterm of term. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + LIST Variables,Subformulas,Scan1,Scan2,Rest; + TERM Subterm,Var,NewForm; + SYMBOL Subtop,Top; + + /*fputs("\nAN0:\t",stdout);term_Print(Term);*/ + + Top = term_TopSymbol(Term); + Variables = list_Copy(fol_QuantifierVariables(Term)); + Subterm = term_SecondArgument(Term); + Subtop = term_TopSymbol(Subterm); + Subterm = cnf_Flatten(Subterm,Subtop); + + /*fputs("\nAN1:\t",stdout);term_Print(Subterm);*/ + + for (Scan1=Variables;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { + Subformulas = list_Nil(); + Var = (TERM)list_Car(Scan1); + /* Find subterms in which the variable does not occur freely */ + for (Scan2=term_ArgumentList(Subterm);!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) + if (!fol_VarOccursFreely(Var,list_Car(Scan2))) + Subformulas = list_Cons(list_Car(Scan2),Subformulas); + if (!list_Empty(Subformulas)) { + /* Rest is the list of those subterms where the variable does occur freely */ + Rest = list_NPointerDifference(term_ArgumentList(Subterm),Subformulas); + if (list_Empty(list_Cdr(Rest))) { /* One subformula */ + if (symbol_Equal(Top,term_TopSymbol(list_Car(Rest)))) { /* Optimization: quantifier still exist */ + NewForm = (TERM)list_Car(Rest); + /* Move one variable down */ + term_RplacArgumentList(term_FirstArgument(NewForm), + list_Cons((POINTER)Var,fol_QuantifierVariables(NewForm))); + list_Delete(Rest); + } + else { + NewForm = fol_CreateQuantifierAddFather(Top,list_List((POINTER)Var), + Rest); + } + } + else { + TERM t; + t = term_CreateAddFather(Subtop,Rest); + NewForm = fol_CreateQuantifierAddFather(Top,list_List((POINTER)Var),list_List(t)); + } + if (term_HasProperSuperterm(PredicateTerm, NewForm)) + NewForm = cnf_AntiPrenexPath(NewForm, PredicateTerm); + term_RplacArgumentList(Subterm,list_Cons(NewForm,Subformulas)); + term_RplacSuperterm(NewForm, Subterm); + term_RplacArgumentList(term_FirstArgument(Term), + list_PointerDeleteElement(fol_QuantifierVariables(Term),(POINTER)Var)); + } + } + + if (list_Empty(fol_QuantifierVariables(Term))) { /* All variables moved inside */ + LIST l; + term_Free(term_FirstArgument(Term)); + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,Subtop); + term_RplacArgumentList(Term,term_ArgumentList(Subterm)); + term_Free(Subterm); + for (l=term_ArgumentList(Term); !list_Empty(l); l=list_Cdr(l)) + term_RplacSuperterm((TERM) list_Car(l), Term); + } + list_Delete(Variables); +} + + +static TERM cnf_AntiPrenexPath(TERM Term, TERM PredicateTerm) +/************************************************************** + INPUT: A formula in negation normal form and a predicate term + which is a subterm of term. + RETURNS: The term after application of anti-prenexing. Quantifiers + are moved inside along the path as long as possible. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + LIST Scan; + SYMBOL Top; + + Top = term_TopSymbol(Term); + + if (fol_IsQuantifier(Top)) { + TERM Subterm,Actterm; + SYMBOL DistrSymb,Subtop; /* The junctor the respective quantifier distributes over */ + + Subterm = term_SecondArgument(Term); + Subtop = term_TopSymbol(Subterm); + + if (!symbol_Equal(Subtop,fol_Not()) && !symbol_IsPredicate(Subtop)) { /* No Literals or Atoms */ + if (symbol_Equal(Top,fol_All())) + DistrSymb = fol_And(); + else + DistrSymb = fol_Or(); + if (fol_IsQuantifier(Subtop)) { + cnf_AntiPrenexPath(Subterm, PredicateTerm); + Subtop = term_TopSymbol(Subterm); + } + if (symbol_Equal(Subtop,DistrSymb)) { + LIST Variables; + LIST NewVars; + Variables = fol_QuantifierVariables(Term); + Subterm = cnf_Flatten(Subterm,DistrSymb); + term_AddFatherLinks(Subterm); + /* + for (l=term_ArgumentList(Subterm); !list_Empty(l); l=list_Cdr(l)) + term_RplacSuperterm((TERM) list_Car(l), Subterm); + */ + for (Scan=term_ArgumentList(Subterm);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Actterm = (TERM)list_Car(Scan); + NewVars = list_NIntersect(fol_FreeVariables(Actterm),Variables, + (BOOL (*)(POINTER,POINTER))term_Equal); + if (!list_Empty(NewVars)) { + if (symbol_Equal(Top,term_TopSymbol(Actterm))) { /* Quantor already there */ + term_CopyTermsInList(NewVars); + term_RplacArgumentList(term_FirstArgument(Actterm), + list_Nconc(fol_QuantifierVariables(Actterm), NewVars)); + } + else { + term_CopyTermsInList(NewVars); + list_Rplaca(Scan,fol_CreateQuantifierAddFather(Top, NewVars, list_List(Actterm))); + } + } + } + term_Delete(term_FirstArgument(Term)); /* Delete old variable list */ + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,DistrSymb); + term_RplacArgumentList(Term,term_ArgumentList(Subterm)); + term_Free(Subterm); + term_AddFatherLinks(Term); + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + term_RplacSuperterm((TERM) list_Car(Scan), Term); + if (term_HasPointerSubterm((TERM) list_Car(Scan), PredicateTerm)) { + puts("\ncheck1"); + list_Rplaca(Scan,cnf_AntiPrenexPath(list_Car(Scan), PredicateTerm)); + term_RplacSuperterm((TERM) list_Car(Scan), Term); + } + } + } + else + if (!fol_IsQuantifier(Subtop)) { + cnf_DistrQuantorNoVarSubPath(Term, PredicateTerm); + for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (term_HasPointerSubterm(list_Car(Scan), PredicateTerm)) + cnf_AntiPrenexPath(list_Car(Scan), PredicateTerm); + } + } + } + } + else + if (!symbol_Equal(Top,fol_Not()) && !symbol_IsPredicate(Top)) + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (term_HasProperSuperterm(PredicateTerm, (TERM) list_Car(Scan))) + cnf_AntiPrenexPath(list_Car(Scan), PredicateTerm); + + term_AddFatherLinks(Term); + return Term; +} + + +static TERM cnf_RemoveTrivialOperators(TERM Term) +/************************************************************** + INPUT: A formula. + RETURNS: The formula after + removal of "or" and "and" with only one argument + CAUTION: The term is destructively changed. +***************************************************************/ +{ + SYMBOL Top; + LIST Scan; + + Top = term_TopSymbol(Term); + + if (symbol_IsPredicate(Top)) + return Term; + + if ((symbol_Equal(Top,fol_And()) || symbol_Equal(Top,fol_Or())) && + list_Empty(list_Cdr(term_ArgumentList(Term)))) { + TERM Result; + Result = term_FirstArgument(Term); + term_RplacSuperterm(Result, term_Superterm(Term)); + list_Delete(term_ArgumentList(Term)); + term_Free(Term); + return cnf_RemoveTrivialOperators(Result); + } + + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + list_Rplaca(Scan,cnf_RemoveTrivialOperators(list_Car(Scan))); + term_RplacSuperterm((TERM) list_Car(Scan), Term); + } + + return Term; +} + + +static TERM cnf_SimplifyQuantors(TERM Term) + /************************************************************** + INPUT: A formula. + RETURNS: The formula after + removal of bindings of variables that don't occur in the + respective subformula and possible mergings of quantors + CAUTION: The term is destructively changed. +***************************************************************/ +{ + SYMBOL Top; + LIST Scan; + + Top = term_TopSymbol(Term); + + if (symbol_IsPredicate(Top) || symbol_Equal(Top,fol_Varlist())) + return Term; + + if (fol_IsQuantifier(Top)) { + LIST Vars; + TERM Var,Subterm,Aux; + Vars = list_Nil(); + Subterm = term_SecondArgument(Term); + + while (symbol_Equal(term_TopSymbol(Subterm),Top)) { + term_RplacArgumentList(term_FirstArgument(Term), + list_Nconc(fol_QuantifierVariables(Term),fol_QuantifierVariables(Subterm))); + term_Free(term_FirstArgument(Subterm)); + Aux = term_SecondArgument(Subterm); + list_Delete(term_ArgumentList(Subterm)); + term_Free(Subterm); + list_Rplaca(list_Cdr(term_ArgumentList(Term)),Aux); + Subterm = Aux; + } + + for (Scan=fol_QuantifierVariables(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Var = (TERM)list_Car(Scan); + if (!fol_VarOccursFreely(Var,Subterm)) + Vars = list_Cons(Var,Vars); + } + if (!list_Empty(Vars)) { + Subterm = term_FirstArgument(Term); + term_RplacArgumentList(Subterm,list_NPointerDifference(term_ArgumentList(Subterm),Vars)); + term_DeleteTermList(Vars); + if (list_Empty(term_ArgumentList(Subterm))) { + Subterm = term_SecondArgument(Term); + term_Delete(term_FirstArgument(Term)); + list_Delete(term_ArgumentList(Term)); + term_Free(Term); + return cnf_SimplifyQuantors(Subterm); + } + } + } + + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + list_Rplaca(Scan,cnf_SimplifyQuantors(list_Car(Scan))); + + return Term; +} + + +TERM cnf_RemoveTrivialAtoms(TERM Term) +/************************************************************** + INPUT: A formula. + RETURNS: The formula where occurrences of the atoms "true" + and "false" are propagated and eventually removed. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + SYMBOL Top,Subtop; + LIST Scan; + TERM Result; + BOOL Update; + + + if (!term_IsComplex(Term)) + return Term; + + Top = term_TopSymbol(Term); + Update = FALSE; + + if (symbol_Equal(Top,fol_And())) { + Scan = term_ArgumentList(Term); + while (!list_Empty(Scan)) { + Result = cnf_RemoveTrivialAtoms(list_Car(Scan)); + Subtop = term_TopSymbol(Result); + if (symbol_Equal(Subtop,fol_True())) + Update = TRUE; + else + if (symbol_Equal(Subtop,fol_False())) { + term_RplacTop(Term,fol_False()); + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term,list_Nil()); + return Term; + } + Scan = list_Cdr(Scan); + } + if (Update) { + term_RplacArgumentList(Term,fol_DeleteTrueTermFromList(term_ArgumentList(Term))); + if (list_Empty(term_ArgumentList(Term))) { + term_RplacTop(Term,fol_True()); + return Term; + } + } + } + else if (symbol_Equal(Top,fol_Or())) { + Scan = term_ArgumentList(Term); + while (!list_Empty(Scan)) { + Result = cnf_RemoveTrivialAtoms(list_Car(Scan)); + Subtop = term_TopSymbol(Result); + if (symbol_Equal(Subtop,fol_False())) + Update = TRUE; + else + if (symbol_Equal(Subtop,fol_True())) { + term_RplacTop(Term,fol_True()); + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term,list_Nil()); + return Term; + } + Scan = list_Cdr(Scan); + } + if (Update) { + term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); + if (list_Empty(term_ArgumentList(Term))) { + term_RplacTop(Term,fol_False()); + return Term; + } + } + } + else if (fol_IsQuantifier(Top) || symbol_Equal(Top,fol_Not())) { + if (fol_IsQuantifier(Top)) + Result = cnf_RemoveTrivialAtoms(term_SecondArgument(Term)); + else + Result = cnf_RemoveTrivialAtoms(term_FirstArgument(Term)); + Subtop = term_TopSymbol(Result); + if ((symbol_Equal(Subtop,fol_False()) && symbol_Equal(Top,fol_Not())) || + (symbol_Equal(Subtop,fol_True()) && fol_IsQuantifier(Top))) { + term_RplacTop(Term,fol_True()); + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term,list_Nil()); + return Term; + } + else + if ((symbol_Equal(Subtop,fol_True()) && symbol_Equal(Top,fol_Not())) || + (symbol_Equal(Subtop,fol_False()) && fol_IsQuantifier(Top))) { + term_RplacTop(Term,fol_False()); + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term,list_Nil()); + return Term; + } + } + else if (symbol_Equal(Top,fol_Implies())) { + Result = cnf_RemoveTrivialAtoms(term_FirstArgument(Term)); + Subtop = term_TopSymbol(Result); + if (symbol_Equal(Subtop,fol_False())) { + term_RplacTop(Term,fol_True()); + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term,list_Nil()); + return Term; + } + else if (symbol_Equal(Subtop,fol_True())) { + term_Delete(Result); + Result = term_SecondArgument(Term); + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,term_TopSymbol(Result)); + term_RplacArgumentList(Term,term_ArgumentList(Result)); + term_Free(Result); + return cnf_RemoveTrivialAtoms(Term); + } + Result = cnf_RemoveTrivialAtoms(term_SecondArgument(Term)); + Subtop = term_TopSymbol(Result); + if (symbol_Equal(Subtop,fol_True())) { + term_RplacTop(Term,fol_True()); + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term,list_Nil()); + return Term; + } + else if (symbol_Equal(Subtop,fol_False())) { + term_RplacTop(Term,fol_Not()); + term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); + } + } + else if (symbol_Equal(Top,fol_Equiv())) { + Result = cnf_RemoveTrivialAtoms(term_FirstArgument(Term)); + Subtop = term_TopSymbol(Result); + if (symbol_Equal(Subtop,fol_False())) { + term_RplacTop(Term,fol_Not()); + term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); + if (list_Empty(term_ArgumentList(Term))) { + term_RplacTop(Term, fol_True()); + return Term; + } + return cnf_RemoveTrivialAtoms(Term); + } + else if (symbol_Equal(Subtop,fol_True())) { + term_Delete(Result); + Result = term_SecondArgument(Term); + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,term_TopSymbol(Result)); + term_RplacArgumentList(Term,term_ArgumentList(Result)); + term_Free(Result); + return cnf_RemoveTrivialAtoms(Term); + } + Result = cnf_RemoveTrivialAtoms(term_SecondArgument(Term)); + Subtop = term_TopSymbol(Result); + if (symbol_Equal(Subtop,fol_False())) { + term_RplacTop(Term,fol_Not()); + term_RplacArgumentList(Term,fol_DeleteFalseTermFromList(term_ArgumentList(Term))); + } + else if (symbol_Equal(Subtop,fol_True())) { + term_Delete(Result); + Result = term_FirstArgument(Term); + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,term_TopSymbol(Result)); + term_RplacArgumentList(Term,term_ArgumentList(Result)); + term_Free(Result); + } + } + + return Term; +} + + +TERM cnf_ObviousSimplifications(TERM Term) +/************************************************************** + INPUT: A formula. + RETURNS: The formula after performing the following simplifications: + - remove "or" and "and" with only one argument + - remove bindings of variables that don't occur in the + respective subformula + - merge quantors + CAUTION: The term is destructively changed. +***************************************************************/ +{ + Term = cnf_RemoveTrivialAtoms(Term); + Term = cnf_RemoveTrivialOperators(Term); + Term = cnf_SimplifyQuantors(Term); + + return Term; +} + + +/* EK: warum wird Term zurueckgegeben, wenn er destruktiv geaendert wird??? */ +static TERM cnf_SkolemFormula(TERM Term, PRECEDENCE Precedence, LIST* Symblist) +/************************************************************** + INPUT: A formula in negation normal form, a precedence and pointer + to a list used as return value. + RETURNS: The skolemized term and the list of introduced Skolem functions. + CAUTION: The term is destructively changed. + The precedence of the new Skolem functions is set in <Precedence>. +***************************************************************/ +{ + SYMBOL Top,SkolemSymbol; + TERM Subterm,SkolemTerm; + LIST Varlist,Scan; + NAT Arity; + + Top = term_TopSymbol(Term); + + if (fol_IsQuantifier(term_TopSymbol(Term))) { + if (symbol_Equal(Top,fol_All())) { + term_Delete(term_FirstArgument(Term)); + Subterm = term_SecondArgument(Term); + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,term_TopSymbol(Subterm)); + term_RplacArgumentList(Term,term_ArgumentList(Subterm)); + term_Free(Subterm); + return cnf_SkolemFormula(Term, Precedence, Symblist); + } + else { /* exist quantifier */ + Varlist = fol_FreeVariables(Term); + Arity = list_Length(Varlist); + for (Scan=fol_QuantifierVariables(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + SkolemSymbol = symbol_CreateSkolemFunction(Arity, Precedence); + *Symblist = list_Cons((POINTER)SkolemSymbol, *Symblist); + SkolemTerm = term_Create(SkolemSymbol,Varlist); /* Caution: Sharing of Varlist ! */ + fol_ReplaceVariable(term_SecondArgument(Term),term_TopSymbol(list_Car(Scan)),SkolemTerm); + term_Free(SkolemTerm); + } + list_Delete(Varlist); + term_Delete(term_FirstArgument(Term)); + Subterm = term_SecondArgument(Term); + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,term_TopSymbol(Subterm)); + term_RplacArgumentList(Term,term_ArgumentList(Subterm)); + term_Free(Subterm); + return cnf_SkolemFormula(Term, Precedence, Symblist); + } + } + else + if (symbol_Equal(Top,fol_And()) || symbol_Equal(Top,fol_Or())) + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + cnf_SkolemFormula(list_Car(Scan), Precedence, Symblist); + return Term; +} + + +static TERM cnf_Cnf(TERM Term, PRECEDENCE Precedence, LIST* Symblist) +/************************************************************** + INPUT: A formula, a precedence and a pointer to a list of symbols + used as return value. + RETURNS: The term is transformed to conjunctive normal form. + EFFECT: The term is destructively changed and not normalized. + The precedence of new Skolem symbols is set in <Precedence>. +***************************************************************/ +{ + /* Necessary because ren_Rename crashes if a e.g. and() has only one argument */ + Term = cnf_ObviousSimplifications(Term); + term_AddFatherLinks(Term); + Term = ren_Rename(Term, Precedence, Symblist, FALSE, FALSE); + Term = cnf_RemoveEquivImplFromFormula(Term); + Term = cnf_NegationNormalFormula(Term); + Term = cnf_SkolemFormula(cnf_AntiPrenex(Term), Precedence, Symblist); + Term = cnf_DistributiveFormula(Term); + + return Term; +} + + +static LIST cnf_GetUsedTerms(CLAUSE C, PROOFSEARCH Search, + HASH InputClauseToTermLabellist) +/************************************************************** + INPUT: + RETURNS: +***************************************************************/ +{ + LIST UsedTerms, Used2, Scan; + UsedTerms = list_Copy(hsh_Get(InputClauseToTermLabellist, C)); + UsedTerms = cnf_DeleteDuplicateLabelsFromList(UsedTerms); + if (!list_Empty(UsedTerms)) + return UsedTerms; + + for (Scan = clause_ParentClauses(C); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + CLAUSE P; + int ClauseNumber; + ClauseNumber = (int) list_Car(Scan); + P = clause_GetNumberedCl(ClauseNumber, prfs_WorkedOffClauses(Search)); + if (P == NULL) { + P = clause_GetNumberedCl(ClauseNumber, prfs_UsableClauses(Search)); + if (P == NULL) + P = clause_GetNumberedCl(ClauseNumber, prfs_DocProofClauses(Search)); + } + Used2 = cnf_GetUsedTerms(P, Search, InputClauseToTermLabellist); + UsedTerms = list_Nconc(UsedTerms, Used2); + } + return UsedTerms; +} + + +static BOOL cnf_HaveProofOptSkolem(PROOFSEARCH Search, TERM topterm, + char* toplabel, TERM term2, + LIST* UsedTerms, LIST* Symblist, + HASH InputClauseToTermLabellist) +/************************************************************** + INPUT: + RETURNS: ??? EK +***************************************************************/ +{ + LIST ConClauses, EmptyClauses; + LIST scan; + BOOL found; + LIST Usables; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + ConClauses = list_Nil(); + found = FALSE; + /* List of clauses from term2 */ + term_AddFatherLinks(term2); + term2 = cnf_Cnf(term2, Precedence, Symblist); + Usables = cnf_MakeClauseList(term2, FALSE, FALSE, Flags, Precedence); + term_Delete(term2); + + for (scan=Usables; !list_Empty(scan); scan = list_Cdr(scan)) { + clause_SetFlag(list_Car(scan), CONCLAUSE); + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) { +#ifdef CHECK + hsh_Check(InputClauseToTermLabellist); +#endif + hsh_Put(InputClauseToTermLabellist, list_Car(scan), toplabel); +#ifdef CHECK_CNF + fputs("\nUsable : ", stdout); + clause_Print(list_Car(scan)); + printf(" Label %s", toplabel); +#endif + } + } + EmptyClauses = cnf_SatUnit(Search, Usables); + if (!list_Empty(EmptyClauses)) { + found = TRUE; +#ifdef CHECK_CNF + fputs("\nHaveProof : Empty Clause : ", stdout); + clause_Print((CLAUSE) list_Car(EmptyClauses)); + putchar('\n'); +#endif + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) + *UsedTerms = list_Nconc(*UsedTerms, cnf_GetUsedTerms((CLAUSE) list_Car(EmptyClauses), Search, InputClauseToTermLabellist)); + EmptyClauses = list_PointerDeleteDuplicates(EmptyClauses); + clause_DeleteClauseList(EmptyClauses); + } + + /* Removing ConClauses from UsablesIndex */ + ConClauses = list_Copy(prfs_UsableClauses(Search)); + for (scan = ConClauses; !list_Empty(scan); scan = list_Cdr(scan)) + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) + prfs_MoveUsableDocProof(Search, (CLAUSE) list_Car(scan)); + else + prfs_DeleteUsable(Search, (CLAUSE) list_Car(scan)); + list_Delete(ConClauses); + + return found; +} + + +BOOL cnf_HaveProof(LIST TermList, TERM ToProve, FLAGSTORE InputFlags, + PRECEDENCE InputPrecedence) +/************************************************************** + INPUT: A list of terms, a term to prove, a flag store and a precedence. + The arguments are not changed. + RETURNS: True if the termlist implies ToProve + CAUTION: All terms are copied. +***************************************************************/ +{ + PROOFSEARCH search; + LIST scan, usables, symblist, emptyclauses; + BOOL found; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + /* Use global PROOFSEARCH object to avoid stamp overflow */ + search = cnf_HAVEPROOFPS; + usables = symblist = list_Nil(); + + /* Initialize search object's flag store */ + Flags = prfs_Store(search); + flag_CleanStore(Flags); + flag_InitFlotterSubproofFlags(InputFlags, Flags); + /* Initialize search object's precedence */ + Precedence = prfs_Precedence(search); + symbol_TransferPrecedence(InputPrecedence, Precedence); + + /* Build list of clauses from the termlist */ + for (scan=TermList; !list_Empty(scan); scan=list_Cdr(scan)) { + TERM t; + t = term_Copy(list_Car(scan)); + t = cnf_Cnf(t, Precedence, &symblist); + + usables = list_Nconc(cnf_MakeClauseList(t,FALSE,FALSE,Flags,Precedence), + usables); + term_Delete(t); + } + + /* Build clauses from negated term to prove */ + ToProve = term_Create(fol_Not(), list_List(term_Copy(ToProve))); + term_AddFatherLinks(ToProve); + ToProve = cnf_Cnf(ToProve, Precedence, &symblist); + usables = list_Nconc(cnf_MakeClauseList(ToProve,FALSE,FALSE,Flags,Precedence), + usables); + term_Delete(ToProve); + + /* SatUnit requires the CONCLAUSE flag */ + for (scan=usables;!list_Empty(scan); scan = list_Cdr(scan)) + clause_SetFlag(list_Car(scan), CONCLAUSE); + + emptyclauses = cnf_SatUnit(search, usables); + + if (!list_Empty(emptyclauses)) { + found = TRUE; + emptyclauses = list_PointerDeleteDuplicates(emptyclauses); + clause_DeleteClauseList(emptyclauses); + } + else + found = FALSE; + prfs_Clean(search); + symbol_DeleteSymbolList(symblist); + + return found; +} + + +static void cnf_RplacVarsymbFunction(TERM term, SYMBOL varsymb, TERM function) +/********************************************************** + INPUT: A term, a variable symbol and a function. + EFFECT: The variable with the symbol varsymb in the term + is replaced by the function function. + CAUTION: The term is destructively changed. +***********************************************************/ +{ + int bottom; + TERM term1; + LIST scan; + + bottom = vec_ActMax(); + vec_Push(term); + + while (bottom != vec_ActMax()) { + term1 = (TERM)vec_PopResult(); + if (symbol_Equal(term_TopSymbol(term1),varsymb)) { + term_RplacTop(term1,term_TopSymbol(function)); + term_RplacArgumentList(term1,term_CopyTermList(term_ArgumentList(function))); + }else + if (!list_Empty(term_ArgumentList(term1))) + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) + vec_Push(list_Car(scan)); + } + vec_SetMax(bottom); +} + + +static void cnf_RplacVar(TERM Term, LIST Varlist, LIST Termlist) +/********************************************************** + INPUT: A term,a variable symbol and a function. + RETURNS: The variable with the symbol varsymb in the term + is replaced by the function function. + CAUTION: The term is destructively changed. +***********************************************************/ +{ + int bottom; + TERM term1; + LIST scan,scan2; + + bottom = vec_ActMax(); + vec_Push(Term); + + while (bottom != vec_ActMax()) { + term1 = vec_PopResult(); + if (symbol_IsVariable(term_TopSymbol(term1))) { + BOOL done; + done = FALSE; + for (scan=Varlist, scan2=Termlist; !list_Empty(scan) && !done; + scan = list_Cdr(scan), scan2 = list_Cdr(scan2)) { + if (symbol_Equal(term_TopSymbol(term1),term_TopSymbol(list_Car(scan)))) { + term_RplacTop(term1,term_TopSymbol((TERM) list_Car(scan2))); + term_RplacArgumentList(term1, + term_CopyTermList(term_ArgumentList(list_Car(scan2)))); + done = TRUE; + } + } + } + else + if (!list_Empty(term_ArgumentList(term1))) + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) + vec_Push(list_Car(scan)); + } + vec_SetMax(bottom); +} + + +static TERM cnf_MakeSkolemFunction(LIST varlist, PRECEDENCE Precedence) +/************************************************************** + INPUT: A list of variables and a precedence. + RETURNS: The new term oskf... (oskc...) which is a function + with varlist as arguments. + EFFECT: The precedence of the new Skolem function is set in <Precedence>. +***************************************************************/ +{ + TERM term; + SYMBOL skolem; + + skolem = symbol_CreateSkolemFunction(list_Length(varlist), Precedence); + term = term_Create(skolem, term_CopyTermList(varlist)); + return term; +} + + +static void cnf_PopAllQuantifier(TERM term) +/******************************************************** + INPUT: A term whose top symbol is fol_all. + RETURNS: Nothing. + EFFECT: Removes the quantifier +********************************************************/ +{ + TERM SubTerm; + LIST VarList; + +#ifdef CHECK + if (!symbol_Equal(term_TopSymbol(term), fol_All())) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cnf_PopAllQuantifier: Top symbol is not fol_All !\n"); + misc_FinishErrorReport(); + } +#endif + + VarList = term_ArgumentList(term_FirstArgument(term)); + term_DeleteTermList(VarList); + term_Free(term_FirstArgument(term)); + SubTerm = term_SecondArgument(term); + list_Delete(term_ArgumentList(term)); + term_RplacTop(term,term_TopSymbol(SubTerm)); + term_RplacArgumentList(term,term_ArgumentList(SubTerm)); + term_Free(SubTerm); +} + + +static TERM cnf_QuantifyAndNegate(TERM term, LIST VarList, LIST FreeList) +/**************************************************************** + INPUT: A term, a list of variables to be exist-quantified, + a list of variables to be all-quantified + RETURNS: not(forall[FreeList](exists[VarList](term))) + MEMORY: The term, the lists and their arguments are copied. +***************************************************************/ +{ + TERM Result; + TERM TermCopy; + LIST VarListCopy; + LIST FreeListCopy; + + TermCopy = term_Copy(term); + VarListCopy = term_CopyTermList(VarList); + Result = fol_CreateQuantifier(fol_Exist(),VarListCopy,list_List(TermCopy)); + FreeListCopy = list_Nil(); + + FreeList = fol_FreeVariables(Result); + if (!list_Empty(FreeList)) { + FreeListCopy = term_CopyTermList(FreeList); + list_Delete(FreeList); + Result = fol_CreateQuantifier(fol_All(), FreeListCopy, list_List(Result)); + } + Result = term_Create(fol_Not(), list_List(Result)); + return Result; +} + + +static TERM cnf_MoveProvedTermToTopLevel(TERM Term, TERM Term1, TERM Proved, + LIST VarList, LIST FreeList, + PRECEDENCE Precedence) +/******************************************************************** + INPUT: A top-level term, which must be a conjunction, + a subterm <Term1> of <Term>, a subterm <Proved> of <Term1>, + a list of existence quantified variables <VarList>, + a list of free variables <FreeList> and a precedence. + <Term1> is of the form + exists[...](t1 and t2 and ... and Proved and ..) + RETURNS: A new term, where <Proved> is removed from the arguments + of <Term1>. + EFFECT: The precedence of new Skolem functions is set in <Precedence> +*******************************************************************/ +{ + TERM termR; + TERM skolemfunction; + SYMBOL varsymb; + LIST scan; + + termR = term_SecondArgument(Term1); /* t1 and t2 and ... and Proved ... */ + term_RplacArgumentList(termR, + list_PointerDeleteElement(term_ArgumentList(termR), + Proved)); + if (list_Length(term_ArgumentList(termR)) < 2) { + TERM termRL = term_FirstArgument(termR); /* t1 */ + list_Delete(term_ArgumentList(termR)); + term_RplacTop(termR, term_TopSymbol(termRL)); + term_RplacArgumentList(termR,term_ArgumentList(termRL)); + term_Free(termRL); + } + + for (scan = VarList; scan != list_Nil(); scan = list_Cdr(scan)) { + varsymb = term_TopSymbol(list_Car(scan)); + skolemfunction = cnf_MakeSkolemFunction(FreeList, Precedence); + cnf_RplacVarsymbFunction(termR,varsymb,skolemfunction); + cnf_RplacVarsymbFunction(Proved,varsymb,skolemfunction); + term_Delete(skolemfunction); + } + + if (!list_Empty(FreeList)) { + Proved = + fol_CreateQuantifier(fol_All(), term_CopyTermList(FreeList), + list_List(Proved)); + if (list_Length(FreeList) > 1) + Proved = cnf_QuantMakeOneVar(Proved); + } + + term_Delete(term_FirstArgument(Term1)); /* Variables of "exists" */ + list_Delete(term_ArgumentList(Term1)); + term_RplacTop(Term1,term_TopSymbol(termR)); + term_RplacArgumentList(Term1,term_ArgumentList(termR)); + term_Free(termR); + + term_RplacArgumentList(Term, list_Cons(Proved, term_ArgumentList(Term))); + return Proved; +} + + +static void cnf_Skolemize(TERM Term, LIST FreeList, PRECEDENCE Precedence) +/******************************************************** + INPUT: A existence quantified term, the list of free variables + and a precedence. + RETURNS: Nothing. + EFFECT: The term is destructively changed, i.e. the + existence quantifier is removed by skolemization. + The precedence of new Skolem functions is set in <Precedence>. +*********************************************************/ +{ + LIST exlist; + TERM subterm; + LIST symblist; + + symblist = list_Nil(); + exlist = cnf_GetSymbolList(term_ArgumentList(term_FirstArgument(Term))); + term_Delete(term_FirstArgument(Term)); + subterm = term_SecondArgument(Term); + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,term_TopSymbol(subterm)); + term_RplacArgumentList(Term,term_ArgumentList(subterm)); + term_Free(subterm); + symblist = cnf_SkolemFunctionFormula(Term, FreeList, exlist, Precedence); + list_Delete(exlist); + list_Delete(symblist); +} + + +static LIST cnf_FreeVariablesBut(TERM Term, LIST Symbols) +/******************************************************** + INPUT: A term and a list of symbols + RETURNS: A list of all free variable terms in Term whose symbols are + not in Symbols +*********************************************************/ +{ + LIST follist, Scan; + follist = fol_FreeVariables(Term); + for (Scan = follist; !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (list_Member(Symbols, (POINTER)term_TopSymbol(list_Car(Scan)), + (BOOL (*)(POINTER,POINTER))symbol_Equal)) + list_Rplaca(Scan,NULL); + follist = list_PointerDeleteElement(follist,NULL); + + return follist; +} + + +static void cnf_SkolemFunctionFormulaMapped(TERM term, LIST allist, LIST map) +/************************************************************** + INPUT: A term term and a list allist of variables and a list map + of pairs (variable symbols, function symbol) + RETURNS: None. + CAUTION: The term is destructively changed. All variable symbols + in map which appear in term are replaced by the skolem functions + with respect to allist which contains the universally quantified + variables. +***************************************************************/ +{ + TERM term1; + LIST scan,scan1; + SYMBOL skolem, symbol; + int bottom; + + bottom = vec_ActMax(); + + for (scan1=map; !list_Empty(scan1); scan1=list_Cdr(scan1)) { + vec_Push(term); + symbol = (SYMBOL) list_PairFirst((LIST) list_Car(scan1)); + skolem = (SYMBOL) list_PairSecond((LIST) list_Car(scan1)); + +#ifdef CHECK_STRSKOLEM + if (flag_GetFlagValue(flag_PSTRSKOLEM)) { + fputs("\nVariable : ", stdout); + symbol_Print(symbol); + fputs("\nFunction : ", stdout); + symbol_Print(skolem); + } +#endif + while (bottom != vec_ActMax()) { + term1 = (TERM)vec_PopResult(); + + if (symbol_Equal(term_TopSymbol(term1),symbol)) { + term_RplacTop(term1,skolem); + list_Delete(term_ArgumentList(term1)); + term_RplacArgumentList(term1,term_CopyTermList(allist)); + } + if (!list_Empty(term_ArgumentList(term1))) + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) { + vec_Push(list_Car(scan)); + } + } + } + vec_SetMax(bottom); +} + + +static BOOL cnf_HasDeeperVariable(LIST List1, LIST List2) +/****************************************************************** + INPUT: Two lists of variable terms + RETURNS: TRUE if a variable in the first list is deeper than all variables + in the second list, FALSE otherwise. + NOTE: If cnf_VARIABLEDEPTHARRAY is not allocated this will crash + If new variables are introduced by strong skolemization, their + depth is -1. +*******************************************************************/ +{ + LIST scan; + int maxdepth1; + + /* Determine maximum depth of variables in List1 */ + maxdepth1 = 0; + for (scan=List1; !list_Empty(scan); scan=list_Cdr(scan)) { + int i; + i = cnf_VARIABLEDEPTHARRAY[term_TopSymbol((TERM) list_Car(scan))]; +#ifdef CHECK_STRSKOLEM + if (flag_GetFlagValue(flag_PSTRSKOLEM)) { + fputs("\nFor variable ", stdout); + symbol_Print(term_TopSymbol((TERM) list_Car(scan))); + printf(" depth is %d.", i); + } +#endif + if (i > maxdepth1) + maxdepth1 = i; + } + + /* Compare with depth of variables in List2 */ + for (scan=List2; !list_Empty(scan); scan=list_Cdr(scan)) { + int i; + i = cnf_VARIABLEDEPTHARRAY[term_TopSymbol((TERM) list_Car(scan))]; +#ifdef CHECK_STRSKOLEM + if (flag_GetFlagValue(flag_PSTRSKOLEM)) { + fputs("\nFor variable ", stdout); + symbol_Print(term_TopSymbol((TERM) list_Car(scan))); + printf(" depth is %d.", i); + } +#endif + if (i >= maxdepth1) + return FALSE; + } + return TRUE; +} + + +static void cnf_StrongSkolemization(PROOFSEARCH Search, TERM Topterm, + char* Toplabel, BOOL TopAnd, TERM Term, + LIST* UsedTerms, LIST* Symblist, + BOOL Result1, + HASH InputClauseToTermLabellist, int Depth) +/****************************************************************** + INPUT: An existence quantified formula. ??? EK + RETURNS: Nothing. + EFFECT: The existence quantifier is removed by strong skolemization. + The precedence of new Skolem symbols is set in the precedence + of the search object. +*******************************************************************/ +{ + LIST exlist; /* Variable symbols bound by exists[]() */ + LIST pairlist; /* List of pairs (Subterm of AND, free variable symbols + not in exlist) */ + LIST allfreevariables; + LIST newvariables; /* w2..wn*/ + LIST mapping; /* List of pairs */ + int numberofallfreevariables, acc_length, i; + LIST pair, pairscan, pairscan_pred, scan, accumulatedvariables; + TERM subterm, w; + BOOL strskolemsuccess; /* Indicates whether strong skolemization was + possible */ + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + /* Necessary so that new variables really are new ! */ + if (flag_GetFlagValue(Flags, flag_CNFSTRSKOLEM)) + symbol_SetStandardVarCounter(term_MaxVar(Topterm)); + + /* Get list of quantified variable symbols x_k */ + exlist = cnf_GetSymbolList(term_ArgumentList(term_FirstArgument(Term))); + /* Pop quantifier */ + term_Delete(term_FirstArgument(Term)); + subterm = term_SecondArgument(Term); + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,term_TopSymbol(subterm)); + term_RplacArgumentList(Term,term_ArgumentList(subterm)); + term_Free(subterm); + + /* Now for every argument get the list of free variables whose symbols + are not in exlist */ + pairlist = list_Nil(); + for (scan=term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) { + pair = list_PairCreate((TERM) list_Car(scan), + cnf_FreeVariablesBut((TERM) list_Car(scan), exlist)); + if (list_Empty(pairlist)) + pairlist = list_List(pair); + else { + /* First sort subterms by number of free variables */ + int pairlength, currentlength; + pairlength = list_Length((LIST) list_PairSecond(pair)); + pairscan = pairlist; + pairscan_pred = list_Nil(); + currentlength = 0; + while (!list_Empty(pairscan)) { + currentlength = list_Length((LIST) list_PairSecond((LIST) list_Car(pairscan))); + if (currentlength < pairlength) { + pairscan_pred = pairscan; + pairscan = list_Cdr(pairscan); + } + else if (currentlength == pairlength) { + /* If both subterms have the same number of free variables compare depth of variables */ + if (cnf_HasDeeperVariable((LIST) list_PairSecond((LIST) list_Car(pairscan)), /* in list */ + (LIST) list_PairSecond(pair))) { /* new pair */ +#ifdef CHECK_STRSKOLEM + if (flag_GetFlagValue(flag_PSTRSKOLEM)) { + fputs("\nTerm ", stdout); + term_Print((TERM) list_PairFirst((LIST) list_Car(pairscan))); + fputs("\n has deeper variable than ", stdout); + term_Print((TERM) list_PairFirst(pair)); + } +#endif + pairscan_pred = pairscan; + pairscan = list_Cdr(pairscan); + } + else + break; + } + else + break; + } + + /* New pair has more variables than all others in list */ + if (list_Empty(pairscan)) + list_Rplacd(pairscan_pred, list_List(pair)); + /* New pair is inserted between pairscan_pred and pairscan */ + else if (currentlength >= pairlength) { + /* Head of list */ + if (list_Empty(pairscan_pred)) + pairlist = list_Cons(pair, pairlist); + else + list_InsertNext(pairscan_pred, pair); + } + /* The case for the same number of variables is not yet implemented */ + } + } + +#ifdef CHECK_STRSKOLEM + if (flag_GetFlagValue(flag_PSTRSKOLEM)) { + for (pairscan=pairlist; !list_Empty(pairscan); pairscan = list_Cdr(pairscan)) { + LIST l; + fputs("\nSubterm ", stdout); + term_Print((TERM) list_PairFirst((LIST) list_Car(pairscan))); + fputs("\n has free variables ", stdout); + for (l=(LIST) list_PairSecond((LIST) list_Car(pairscan)); !list_Empty(l); l = list_Cdr(l)) { + term_Print((TERM) list_Car(l)); + fputs(" ", stdout); + } + } + } +#endif + + /* Determine number of all free variablein and()--term whose symbols are not in exlist */ + /* Create map from ex_variables tp skolem symbols */ + allfreevariables = cnf_FreeVariablesBut(Term, exlist); + numberofallfreevariables = list_Length(allfreevariables); + + mapping = list_Nil(); + + for (scan = exlist; !list_Empty(scan); scan = list_Cdr(scan)) { + SYMBOL skolem; + skolem = symbol_CreateSkolemFunction(numberofallfreevariables, Precedence); + *Symblist = list_Cons((POINTER)skolem,*Symblist); + mapping = list_Cons(list_PairCreate(list_Car(scan), (POINTER)skolem), + mapping); + } + list_Delete(allfreevariables); + + /* Create new variables */ + newvariables = list_Nil(); + + for (i=0; i < numberofallfreevariables; i++) { + w = term_CreateStandardVariable(); + newvariables = list_Cons(w, newvariables); + } + +#ifdef CHECK_STRSKOLEM + if (flag_GetFlagValue(flag_PSTRSKOLEM)) { + LIST l; + fputs("\nNew variables : ", stdout); + for (l=newvariables; !list_Empty(l); l = list_Cdr(l)) { + term_Print((TERM) list_Car(l)); + fputs(" ", stdout); + } + } +#endif + + /* Now do the replacing */ + accumulatedvariables = list_Nil(); + acc_length = 0; + strskolemsuccess = FALSE; + for (pairscan=pairlist; !list_Empty(pairscan); pairscan=list_Cdr(pairscan)) { + LIST allist; + + /* Add bound variables for this subterm */ + accumulatedvariables = list_Nconc(accumulatedvariables, + (LIST) list_PairSecond((LIST) list_Car(pairscan))); + accumulatedvariables = term_DeleteDuplicatesFromList(accumulatedvariables); + + /* Remove new variables not (no longer) needed */ + for (i=0; i < list_Length(accumulatedvariables) - acc_length; i++) { + term_Delete((TERM) list_Top(newvariables)); + newvariables = list_Pop(newvariables); + } + acc_length = list_Length(accumulatedvariables); + +#ifdef CHECK_STRSKOLEM + if (flag_GetFlagValue(flag_PSTRSKOLEM)) { + LIST l; + fputs("\n\nSubterm is ", stdout); + term_Print((TERM) list_PairFirst((LIST) list_Car(pairscan))); + fputs("\nFree variables : ", stdout); + for (l=accumulatedvariables; !list_Empty(l); l = list_Cdr(l)) { + term_Print((TERM) list_Car(l)); + fputs(" ", stdout); + } + } +#endif + if (!list_Empty(newvariables)) + strskolemsuccess = TRUE; + allist = list_Nconc(list_Copy(accumulatedvariables), list_Copy(newvariables)); + + cnf_SkolemFunctionFormulaMapped((TERM) list_PairFirst((LIST) list_Car(pairscan)), allist, + mapping); +#ifdef CHECK_STRSKOLEM + if (flag_GetFlagValue(flag_PSTRSKOLEM)) { + fputs("\nSubterm after skolemization : ", stdout); + term_Print(list_PairFirst((LIST) list_Car(pairscan))); + } +#endif + + list_Delete(allist); + cnf_OptimizedSkolemFormula(Search, Topterm, Toplabel, TopAnd, + (TERM) list_PairFirst((LIST) list_Car(pairscan)), + UsedTerms, Symblist, Result1, + InputClauseToTermLabellist, Depth); + } + while (!list_Empty(newvariables)) { + term_Delete((TERM) list_Top(newvariables)); + newvariables = list_Pop(newvariables); + } + list_Delete(accumulatedvariables); /* Only pairs and pairlist left */ + list_DeletePairList(pairlist); + list_Delete(exlist); + list_DeletePairList(mapping); + if (flag_GetFlagValue(Flags, flag_PSTRSKOLEM) && strskolemsuccess) { + fputs("\nStrong skolemization applied", stdout); + } +} + + +static void cnf_OptimizedSkolemFormula(PROOFSEARCH Search, TERM topterm, + char* toplabel, BOOL TopAnd, TERM term, + LIST* UsedTerms, LIST* Symblist, + BOOL Result1, + HASH InputClauseToTermLabellist, + int Depth) +/************************************************************** + INPUT: Two terms in negation normal form. ??? EK + RETURNS: The skolemized term with the optimized skolemization + due to Ohlbach and Weidenbach of <term> and further improvements. + <rest> is used as additional, conjunctively added information. + EFFECT: The symbol precedence of the search object is changed + because new Skolem symbols are defined. + CAUTION: The term is destructively changed. +***************************************************************/ +{ + TERM termL2, provedterm; + LIST freevariables, scan, varlist; + SYMBOL top; + BOOL result2; + BOOL optimized; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + result2 = FALSE; + freevariables = list_Nil(); + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + top = term_TopSymbol(term); + if (fol_IsQuantifier(top)) { + if (symbol_Equal(top,fol_All())) { + /* For quantified variables store depth if strong skolemization is performed */ + if (flag_GetFlagValue(Flags, flag_CNFSTRSKOLEM)) { + LIST variables; + variables = term_ArgumentList(term_FirstArgument(term)); + for (scan=variables; !list_Empty(scan); scan=list_Cdr(scan)) { +#ifdef CHECK_STRSKOLEM + if (flag_GetFlagValue(Flags, flag_PSTRSKOLEM)) { + if (cnf_VARIABLEDEPTHARRAY[term_TopSymbol(list_Car(scan))] != -1) { + fputs("\nFor variable ", stderr); + term_Print((TERM) list_Car(scan)); + printf(" depth is already set to %d, now setting it to %d", + cnf_VARIABLEDEPTHARRAY[term_TopSymbol(list_Car(scan))],Depth); + } + } +#endif +#ifdef CHECK_STRSKOLEM + if (flag_GetFlagValue(Flags, flag_PSTRSKOLEM)) { + fputs("\nVariable ", stdout); + term_Print((TERM) list_Car(scan)); + printf(" has depth %d in term\n ", Depth); + term_Print(term); + } +#endif + cnf_VARIABLEDEPTHARRAY[term_TopSymbol(list_Car(scan))] = Depth; + } + Depth++; + } + cnf_PopAllQuantifier(term); + cnf_OptimizedSkolemFormula(Search,topterm, toplabel, TopAnd, term, + UsedTerms, Symblist, Result1, + InputClauseToTermLabellist, Depth); + return; + } + freevariables = fol_FreeVariables(term); + optimized = FALSE; + if (symbol_Equal(term_TopSymbol(term_SecondArgument(term)), fol_And())) { + if (flag_GetFlagValue(Flags, flag_CNFOPTSKOLEM)) { + scan = term_ArgumentList(term_SecondArgument(term)); + varlist = term_ArgumentList(term_FirstArgument(term)); + while (!list_Empty(scan) && !optimized) { + if (!Result1) { + if (TopAnd) { + if (flag_GetFlagValue(Flags, flag_POPTSKOLEM)) { + fputs("\nHaveProof not necessary", stdout); + } + result2 = TRUE; + } + else { + termL2 = cnf_QuantifyAndNegate((TERM) list_Car(scan), + varlist, freevariables); + result2 = cnf_HaveProofOptSkolem(Search, topterm, toplabel, termL2, + UsedTerms, Symblist, + InputClauseToTermLabellist); +#ifdef CHECK_OPTSKOLEM + if (flag_GetFlagValue(Flags, flag_POPTSKOLEM)) { + fputs("\nHaveProof result : ", stdout); + if (result2) + fputs("TRUE", stdout); + else + fputs("FALSE", stdout); + } +#endif + } + } + + if (Result1 || result2) { + optimized = TRUE; + if (flag_GetFlagValue(Flags, flag_POPTSKOLEM)) { + fputs("\nIn term ", stdout); + term_Print(topterm); + fputs("\n subterm ", stdout); + term_Print((TERM) list_Car(scan)); + puts(" is moved to toplevel."); + } + provedterm = + cnf_MoveProvedTermToTopLevel(topterm, term, list_Car(scan), + varlist, freevariables, Precedence); + if (flag_GetFlagValue(Flags, flag_POPTSKOLEM)) { + fputs("Result : ", stdout); + term_Print(topterm); + putchar('\n'); + } + /* provedterm is argument of top AND term */ + cnf_OptimizedSkolemFormula(Search, topterm, toplabel, TRUE, + provedterm,UsedTerms, Symblist, Result1, + InputClauseToTermLabellist, Depth); + } + else + scan = list_Cdr(scan); + } + } + if (!optimized) { + /* Optimized skolemization not enabled or not possible */ + if (flag_GetFlagValue(Flags, flag_CNFSTRSKOLEM)) { + optimized = TRUE; /* Strong Skolemization is always possible after exists[..](and(..)) */ + cnf_StrongSkolemization(Search, topterm, toplabel, TopAnd, term, + UsedTerms, Symblist, Result1, + InputClauseToTermLabellist, Depth); + } + } + } + else + TopAnd = FALSE; + if (!optimized) { + /* Optimized skolemization not enabled or not possible */ + /* Strong skolemization not enabled or not possible */ + cnf_Skolemize(term, freevariables, Precedence); + } + list_Delete(freevariables); + cnf_OptimizedSkolemFormula(Search, topterm, toplabel, TopAnd, term,UsedTerms, + Symblist,Result1,InputClauseToTermLabellist,Depth); + return; + } + else { + if (symbol_Equal(top,fol_And()) || symbol_Equal(top,fol_Or())) { + if (symbol_Equal(top,fol_Or())) + TopAnd = FALSE; + for (scan=term_ArgumentList(term);!list_Empty(scan); + scan=list_Cdr(scan)) + cnf_OptimizedSkolemFormula(Search, topterm, toplabel, TopAnd, + (TERM) list_Car(scan), + UsedTerms, Symblist, + Result1, InputClauseToTermLabellist, Depth); + } + } + return; +} + + +static LIST cnf_SkolemFunctionFormula(TERM term, LIST allist, LIST exlist, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A term <term>, a list <allist> of variables, a list <exlist> + of variable symbols and a precedence. + RETURNS: The list of new Skolem functions. + EFFECT: The term is destructively changed. All variable symbols + in <exlist> which appear in <term> are replaced by skolem functions + with respect to <allist> which contains the universally quantified + variables. + New Skolem functions are created and their precedence is set + in <Precedence>. +***************************************************************/ +{ + TERM term1; + LIST scan, scan1, Result; + SYMBOL skolem; + int bottom,n; + + Result = list_Nil(); + bottom = vec_ActMax(); + n = list_Length(allist); + + for (scan1=exlist; !list_Empty(scan1); scan1=list_Cdr(scan1)) { + vec_Push(term); + skolem = symbol_CreateSkolemFunction(n, Precedence); + Result = list_Cons((POINTER)skolem, Result); + + while (bottom != vec_ActMax()) { + term1 = (TERM)vec_PopResult(); + if (symbol_Equal(term_TopSymbol(term1),(SYMBOL)list_Car(scan1))) { + term_RplacTop(term1,skolem); + list_Delete(term_ArgumentList(term1)); + term_RplacArgumentList(term1,term_CopyTermList(allist)); + } + if (!list_Empty(term_ArgumentList(term1))) + for (scan=term_ArgumentList(term1);!list_Empty(scan);scan=list_Cdr(scan)) + vec_Push(list_Car(scan)); + } + } + vec_SetMax(bottom); + return Result; +} + + +static LIST cnf_OptimizedSkolemization(PROOFSEARCH Search, TERM Term, + char* Label, LIST* UsedTerms, + LIST* Symblist, BOOL result, + BOOL Conjecture, + HASH InputClauseToTermLabellist) +/************************************************************** + INPUT: A term, a shared index and a list of non-ConClauses. ??? EK + RETURNS: The list of clauses derived from Term. + EFFECT: The term is skolemized using optimized skolemization wrt ShIndex. +**************************************************************/ +{ + LIST Clauses; + TERM FirstArg; + int i; + FLAGSTORE Flags; + PRECEDENCE Precedence; + +#ifdef CHECK + if (Term == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cnf_OptimizedSkolemization: Input term is NULL.\n"); + misc_FinishErrorReport(); + } +#endif + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + FirstArg = Term; + + if (flag_GetFlagValue(Flags, flag_CNFSTRSKOLEM)) { + /* Initializing array */ + for (i = 1; i <= symbol__MAXSTANDARDVAR; i++) + cnf_VARIABLEDEPTHARRAY[i] = -1; + } + + if (flag_GetFlagValue(Flags, flag_POPTSKOLEM) || + flag_GetFlagValue(Flags, flag_PSTRSKOLEM)) { + fputs("\nTerm before skolemization : \n ", stdout); + fol_PrettyPrintDFG(Term); + } + + if (!fol_IsLiteral(Term)) { + if (flag_GetFlagValue(Flags, flag_CNFOPTSKOLEM) || + flag_GetFlagValue(Flags, flag_CNFSTRSKOLEM)) { + if (flag_GetFlagValue(Flags, flag_CNFOPTSKOLEM)) + Term = term_Create(fol_And(), list_List(Term)); /* CW hack: definitions are added on top level*/ + cnf_OptimizedSkolemFormula(Search, Term, Label, TRUE, FirstArg, UsedTerms, + Symblist, result, InputClauseToTermLabellist, 0); + } + else { + LIST Symbols; + Symbols = list_Nil(); + Term = cnf_SkolemFormula(Term, Precedence, &Symbols); + list_Delete(Symbols); + } + } + if (flag_GetFlagValue(Flags, flag_POPTSKOLEM) || + flag_GetFlagValue(Flags, flag_PSTRSKOLEM)) { + fputs("\nTerm after skolemization : ", stdout); + term_Print(Term); + } + Term = cnf_DistributiveFormula(Term); + Clauses = cnf_MakeClauseList(Term, FALSE, Conjecture, Flags, Precedence); + term_Delete(Term); + + return Clauses; +} + + +LIST cnf_GetSkolemFunctions(TERM Term, LIST ArgList, LIST* SkolToExVar) +/************************************************************** + INPUT: A term, the argumentlist of a skolem function, a mapping from + a skolem function to a variable + RETURNS: The longest argumentlist of all skolem functions found so far. + EFFECT: Computes information for renaming variables and replacing + skolem functions during de-skolemization. +**************************************************************/ +{ + LIST Scan; + SYMBOL Top; + + Top = term_TopSymbol(Term); + + if (fol_IsQuantifier(Top)) + return cnf_GetSkolemFunctions(term_SecondArgument(Term), ArgList, + SkolToExVar); + + if (symbol_IsFunction(Top) && symbol_HasProperty(Top, SKOLEM)) { + BOOL found; + SYMBOL Var = 0; + int Arity; + found = FALSE; + + /* Keep longest argument list of all skolem functions in the clause for renaming */ + /* Delete all other argument lists */ + Arity = list_Length(term_ArgumentList(Term)); + if (Arity > list_Length(ArgList)) { + term_DeleteTermList(ArgList); + ArgList = term_ArgumentList(Term); + } + else + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term, NULL); + + /* Replace skolem function by variable */ + if (list_Length(*SkolToExVar) > Arity) { + NAT i; + LIST SkolScan = *SkolToExVar; + for (i = 0; i < Arity; i++) + SkolScan = list_Cdr(SkolScan); + for (SkolScan = (LIST) list_Car(SkolScan); + (SkolScan != list_Nil()) && !found; SkolScan = list_Cdr(SkolScan)) { + SYMBOL Skol; + Skol = (SYMBOL) list_PairFirst((LIST) list_Car(SkolScan)); + if (Skol == term_TopSymbol(Term)) { + Var = (SYMBOL) list_PairSecond((LIST) list_Car(SkolScan)); + found = TRUE; + } + } + } + if (!found) { + LIST Pair; + NAT i; + LIST SkolScan; + + SkolScan = *SkolToExVar; + for (i = 0; i < Arity; i++) { + if (list_Cdr(SkolScan) == list_Nil()) + list_Rplacd(SkolScan, list_List(NULL)); + SkolScan = list_Cdr(SkolScan); + } + + Var = symbol_CreateStandardVariable(); + Pair = list_PairCreate((POINTER) term_TopSymbol(Term), + (POINTER) Var); + if (list_Car(SkolScan) == list_Nil()) + list_Rplaca(SkolScan, list_List(Pair)); + else + list_Rplaca(SkolScan, list_Nconc((LIST) list_Car(SkolScan), + list_List(Pair))); + } + term_RplacTop(Term, Var); + } + else { + for (Scan = term_ArgumentList(Term); Scan != list_Nil(); + Scan = list_Cdr(Scan)) + ArgList = cnf_GetSkolemFunctions((TERM) list_Car(Scan), ArgList, + SkolToExVar); + } + return ArgList; +} + + +void cnf_ReplaceVariable(TERM Term, SYMBOL Old, SYMBOL New) +/************************************************************** + INPUT: A term, two symbols that are variables + EFFECT: In term every occurrence of Old is replaced by New +**************************************************************/ +{ + LIST Scan; + +#ifdef CHECK + if (!symbol_IsVariable(Old)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cnf_ReplaceVariable: Illegal input symbol.\n"); + misc_FinishErrorReport(); + } +#endif + + if (symbol_Equal(term_TopSymbol(Term), Old)) + term_RplacTop(Term, New); + else + for (Scan = term_ArgumentList(Term); !list_Empty(Scan); + Scan = list_Cdr(Scan)) + cnf_ReplaceVariable(list_Car(Scan), Old, New); +} + + +LIST cnf_RemoveSkolemFunctions(CLAUSE Clause, LIST* SkolToExVar, LIST Vars) +/************************************************************** + INPUT: A clause, a list which is a mapping from skolem functions to + variables and a list of variables for forall-quantification. + RETURNS: A list of terms derived from the clause using deskolemization + EFFECT: Arguments of skolem functions are renamed consistently. + Skolemfunctions are replaced by variables. +**************************************************************/ +{ + LIST Scan; + LIST TermScan, TermList, ArgList; + TERM Term; + int i; + + TermList = list_Nil(); + + ArgList = list_Nil(); + for (i = 0; i < clause_Length(Clause); i++) { + Term = term_Copy(clause_GetLiteralTerm(Clause, i)); + ArgList = cnf_GetSkolemFunctions(Term, ArgList, SkolToExVar); + TermList = list_Cons(Term, TermList); + } + + if (list_Empty(ArgList)) + return TermList; + + /* Rename variables */ + for (Scan = ArgList; Scan != list_Nil(); Scan = list_Cdr(Scan)) { + for (TermScan = TermList; TermScan != list_Nil(); + TermScan = list_Cdr(TermScan)) { + Term = (TERM) list_Car(TermScan); + cnf_ReplaceVariable(Term, + term_TopSymbol((TERM) list_Car(Scan)), + (SYMBOL) list_Car(Vars)); + } + if (list_Cdr(Vars) == list_Nil()) { + SYMBOL New = symbol_CreateStandardVariable(); + Vars = list_Nconc(Vars, list_List((POINTER) New)); + } + Vars = list_Cdr(Vars); + } + term_DeleteTermList(ArgList); + return TermList; +} + + +TERM cnf_DeSkolemFormula(LIST Clauses) +/************************************************************** + INPUT: A list of clauses. + RETURNS: A formula built from the clauses. + EFFECT: All skolem functions are removed from the clauses. +**************************************************************/ +{ + LIST Scan, SkolToExVar, Vars, FreeVars, FreeVarsCopy, VarScan, TermList; + TERM VarListTerm, TopTerm, Term; + BOOL First; + + SkolToExVar = list_List(NULL); + Vars = list_List((POINTER) symbol_CreateStandardVariable()); + + TopTerm = term_Create(fol_And(), NULL); + + for (Scan = Clauses; Scan != list_Nil(); Scan = list_Cdr(Scan)) { + TermList = cnf_RemoveSkolemFunctions((CLAUSE) list_Car(Scan), + &SkolToExVar, Vars); + Term = term_Create(fol_Or(), TermList); + FreeVars = fol_FreeVariables(Term); + if (!list_Empty(FreeVars)) { + FreeVarsCopy = term_CopyTermList(FreeVars); + list_Delete(FreeVars); + Term = fol_CreateQuantifier(fol_All(), FreeVarsCopy, list_List(Term)); + } + term_RplacArgumentList(TopTerm, list_Cons(Term, term_ArgumentList(TopTerm))); + } + + VarScan = Vars; + First = TRUE; + + for (Scan = SkolToExVar; Scan != list_Nil(); Scan = list_Cdr(Scan)) { + if (list_Empty(list_Car(Scan))) { + if (term_TopSymbol(TopTerm) == fol_All()) + term_RplacArgumentList(TopTerm, list_Cons(term_Create((SYMBOL) list_Car(VarScan), NULL), + term_ArgumentList(TopTerm))); + if (!First) + TopTerm = fol_CreateQuantifier(fol_All(), + list_List(term_Create((SYMBOL) list_Car(VarScan), NULL)), + list_List(TopTerm)); + } + else { + LIST ExVarScan; + LIST ExVars = list_Nil(); + for (ExVarScan = list_Car(Scan); ExVarScan != list_Nil(); + ExVarScan = list_Cdr(ExVarScan)) { + if (ExVars == list_Nil()) + ExVars = list_List(term_Create((SYMBOL) list_PairSecond((LIST) list_Car(ExVarScan)), NULL)); + else + ExVars = list_Cons(term_Create((SYMBOL) list_PairSecond((LIST) list_Car(ExVarScan)), NULL), ExVars); + list_PairFree((LIST) list_Car(ExVarScan)); + } + list_Delete((LIST) list_Car(Scan)); + list_Rplaca(Scan, NULL); + + if (term_TopSymbol(TopTerm) == fol_Exist()) { + VarListTerm = (TERM) list_Car(term_ArgumentList(TopTerm)); + term_RplacArgumentList(VarListTerm, + list_Nconc(term_ArgumentList(VarListTerm), + ExVars)); + } + else + TopTerm = fol_CreateQuantifier(fol_Exist(), ExVars, list_List(TopTerm)); + ExVars = list_Nil(); + + if (!First) + TopTerm = fol_CreateQuantifier(fol_All(), + list_List(term_Create((SYMBOL) list_Car(VarScan), NULL)), + list_List(TopTerm)); + } + if (!First) + VarScan = list_Cdr(VarScan); + else + First = FALSE; + + } + list_Delete(SkolToExVar); + list_Delete(Vars); + + return TopTerm; +} + + +#ifdef OPTCHECK +/* Currently unused */ +/*static */ +LIST cnf_CheckOptimizedSkolemization(LIST* AxClauses, LIST* ConClauses, + TERM AxTerm, TERM ConTerm, + LIST NonConClauses, LIST* SkolemPredicates, + SHARED_INDEX ShIndex, BOOL result) +/********************************************************** + EFFECT: Used to check the correctness of optimized skolemization +***********************************************************/ +{ + TERM DeSkolemizedAxOpt, DeSkolemizedConOpt, DeSkolemizedAx, DeSkolemizedCon; + TERM TopOpt, Top, ToProve; + LIST SkolemFunctions2; + + if (*AxClauses != list_Nil()) { + DeSkolemizedAxOpt = cnf_DeSkolemFormula(*AxClauses); + if (*ConClauses != list_Nil()) { + DeSkolemizedConOpt = cnf_DeSkolemFormula(*ConClauses); + TopOpt = term_Create(fol_And(), + list_Cons(DeSkolemizedAxOpt, + list_List(DeSkolemizedConOpt))); + } + else + TopOpt = DeSkolemizedAxOpt; + } + else { + DeSkolemizedConOpt = cnf_DeSkolemFormula(*ConClauses); + TopOpt = DeSkolemizedConOpt; + } + + clause_DeleteClauseList(*AxClauses); + clause_DeleteClauseList(*ConClauses); + *AxClauses = list_Nil(); + *ConClauses = list_Nil(); + + flag_SetFlagValue(flag_CNFOPTSKOLEM, flag_CNFOPTSKOLEMOFF); + if (AxTerm) { + *AxClauses = cnf_OptimizedSkolemization(term_Copy(AxTerm), ShIndex, NonConClauses, result,FALSE, ClauseToTermLabellist); + } + if (ConTerm) { + *ConClauses = cnf_OptimizedSkolemization(term_Copy(ConTerm), ShIndex, NonConClauses, result,TRUE, ClauseToTermLabellist); + } + + if (*AxClauses != list_Nil()) { + DeSkolemizedAx = cnf_DeSkolemFormula(*AxClauses); + if (*ConClauses != list_Nil()) { + DeSkolemizedCon = cnf_DeSkolemFormula(*ConClauses); + Top = term_Create(fol_And(), + list_Cons(DeSkolemizedAx, + list_List(DeSkolemizedCon))); + } + else + Top = DeSkolemizedAx; + } + else { + DeSkolemizedCon = cnf_DeSkolemFormula(*ConClauses); + Top = DeSkolemizedCon; + } + + clause_DeleteClauseList(*AxClauses); + clause_DeleteClausList(*ConClauses); + *AxClauses = list_Nil(); + *ConClauses = list_Nil(); + + ToProve = term_Create(fol_Equiv(), list_Cons(TopOpt, list_List(Top))); + ToProve = term_Create(fol_Not(), list_List(ToProve)); + fol_NormalizeVars(ToProve); + ToProve = cnf_ObviousSimplifications(ToProve); + term_AddFatherLinks(ToProve); + ToProve = ren_Rename(ToProve,SkolemPredicates,FALSE); + ToProve = cnf_RemoveEquivImplFromFormula(ToProve); + ToProve = cnf_NegationNormalFormula(ToProve); + ToProve = cnf_AntiPrenex(ToProve); + + SkolemFunctions2 = list_Nil(); + ToProve = cnf_SkolemFormula(ToProve, &SkolemFunctions2); + ToProve = cnf_DistributiveFormula(ToProve); + *ConClauses = cnf_MakeClauseList(ToProve); + if (ToProve) + term_Delete(ToProve); + *AxClauses = list_Nil(); + return SkolemFunctions2; +} +#endif + + +PROOFSEARCH cnf_Flotter(LIST AxiomList, LIST ConjectureList, LIST* AxClauses, + LIST* AllLabels, HASH TermLabelToClauselist, + HASH ClauseToTermLabellist, FLAGSTORE InputFlags, + PRECEDENCE InputPrecedence, LIST* Symblist) +/************************************************************** + INPUT: A list of axiom formulae, + a list of conjecture formulae, + a pointer to a list in which clauses derived from axiom formulae + are stored, + a pointer to a list in which clauses derived from + conjecture formulae are stored, ??? + a pointer to a list of all termlabels, + a hasharray in which for every term label the list of clauses + derived from the term is stored (if DocProof is set), + a hasharray in which for every clause the list of labels + of the terms used for deriving the clause is stored (if DocProof + is set), + a flag store, + a precedence + a pointer to a list of symbols which have to be deleted later if + the ProofSearch object is kept. + RETURNS: If KeepProofSearch ??? is TRUE, then the ProofSearch object is not + freed but returned. + Else, NULL is returned. + EFFECT: ??? EK + The precedence of new skolem symbols is set in <InputPrecedence>. +***************************************************************/ +{ + LIST Scan, Scan2, FormulaClauses,SkolemFunctions; + LIST SkolemPredicates, EmptyClauses, AllFormulae; + LIST UsedTerms; + TERM AxTerm,Formula; + BOOL Result; + PROOFSEARCH Search; + PRECEDENCE Precedence; + FLAGSTORE Flags; + NAT Count; + HASH InputClauseToTermLabellist; + + Search = prfs_Create(); + + /* Initialize the flagstore for the CNF transformation */ + Flags = prfs_Store(Search); + flag_CleanStore(Flags); + flag_InitFlotterFlags(InputFlags, Flags); + /* Initialize the precedence */ + Precedence = prfs_Precedence(Search); + symbol_TransferPrecedence(InputPrecedence, Precedence); + + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) + prfs_AddDocProofSharingIndex(Search); + + AxTerm = (TERM)NULL; + SkolemPredicates = list_Nil(); + Result = FALSE; + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) + InputClauseToTermLabellist = hsh_Create(); + else + InputClauseToTermLabellist = NULL; + + symbol_ReinitGenericNameCounters(); + + for (Scan = AxiomList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + LIST Pair; + Pair = list_Car(Scan); + AxTerm = (TERM) list_PairSecond(Pair); + fol_RemoveImplied(AxTerm); + term_AddFatherLinks(AxTerm); + fol_NormalizeVars(AxTerm); + if (flag_GetFlagValue(Flags, flag_CNFFEQREDUCTIONS)) + cnf_PropagateSubstEquations(AxTerm); + AxTerm = cnf_ObviousSimplifications(AxTerm); + if (flag_GetFlagValue(Flags, flag_CNFRENAMING)) { + term_AddFatherLinks(AxTerm); + AxTerm = ren_Rename(AxTerm, Precedence, &SkolemPredicates, + flag_GetFlagValue(Flags, flag_CNFPRENAMING), TRUE); + } + AxTerm = cnf_RemoveEquivImplFromFormula(AxTerm); + AxTerm = cnf_NegationNormalFormula(AxTerm); + AxTerm = cnf_AntiPrenex(AxTerm); + list_Rplacd(Pair, (LIST) AxTerm); + } + AllFormulae = AxiomList; + + /* At this point the list contains max. 1 element, which is a pair + of the label NULL and the negated + conjunction of all conjecture formulae. */ + + Count = 0; + for (Scan = ConjectureList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + TERM ConTerm; + char* Label; + char buf[100]; + /* Add label */ + if (list_PairFirst(list_Car(Scan)) == NULL) { + sprintf(buf, "conjecture%d", Count); + Label = string_StringCopy(buf); + list_Rplaca((LIST) list_Car(Scan), Label); + if (flag_GetFlagValue(Flags, flag_DOCPROOF) && + flag_GetFlagValue(Flags, flag_PLABELS)) { + printf("\nAdded label %s for conjecture", Label); + fol_PrettyPrintDFG((TERM) list_PairSecond(list_Car(Scan))); + } + } + + ConTerm = (TERM) list_PairSecond((LIST) list_Car(Scan)); + fol_RemoveImplied(ConTerm); + term_AddFatherLinks(ConTerm); + fol_NormalizeVars(ConTerm); + if (flag_GetFlagValue(Flags, flag_CNFFEQREDUCTIONS)) + cnf_PropagateSubstEquations(ConTerm); + ConTerm = cnf_ObviousSimplifications(ConTerm); + + if (flag_GetFlagValue(Flags, flag_CNFRENAMING)) { + term_AddFatherLinks(ConTerm); + ConTerm = ren_Rename(ConTerm, Precedence, &SkolemPredicates, + flag_GetFlagValue(Flags, flag_CNFPRENAMING),TRUE); + } + /* fputs("\nRen:\t",stdout);term_Print(ConTerm);putchar('\n'); */ + ConTerm = cnf_RemoveEquivImplFromFormula(ConTerm); + ConTerm = cnf_NegationNormalFormula(ConTerm); + /* fputs("\nAn:\t",stdout);term_Print(ConTerm);putchar('\n'); */ + ConTerm = cnf_AntiPrenex(ConTerm); + /* fputs("\nPr:\t",stdout);term_Print(ConTerm);putchar('\n'); */ + /* Insert changed term into pair */ + list_Rplacd((LIST) list_Car(Scan), (LIST) ConTerm); + + Count++; + } + + AllFormulae = list_Append(ConjectureList, AllFormulae); + for (Scan = ConjectureList;!list_Empty(Scan); Scan = list_Cdr(Scan)) + list_Rplaca(Scan,list_PairSecond(list_Car(Scan))); + + FormulaClauses = list_Nil(); + SkolemFunctions = list_Nil(); + Count = 0; + for (Scan = AllFormulae; !list_Empty(Scan); Scan = list_Cdr(Scan), Count++) { + LIST FormulaClausesTemp; + Formula = term_Copy((TERM) list_PairSecond(list_Car(Scan))); +#ifdef CHECK_CNF + fputs("\nInputFormula : ",stdout); term_Print(Formula); + printf("\nLabel : %s", (char*) list_PairFirst(list_Car(Scan))); +#endif + Formula = cnf_SkolemFormula(Formula,Precedence,&SkolemFunctions); + Formula = cnf_DistributiveFormula(Formula); + FormulaClausesTemp = cnf_MakeClauseList(Formula,FALSE,FALSE,Flags,Precedence); + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) { + for (Scan2 = FormulaClausesTemp; !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) { + hsh_Put(InputClauseToTermLabellist, list_Car(Scan2), list_PairFirst(list_Car(Scan))); + } + } + FormulaClauses = list_Nconc(FormulaClauses, FormulaClausesTemp); + term_Delete(Formula); + } + + /* Trage nun Formula Clauses modulo Reduktion in einen Index ein */ + + /* red_SatUnit works only on conclauses */ + for (Scan = FormulaClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) + clause_SetFlag((CLAUSE) list_Car(Scan), CONCLAUSE); + /* For FormulaClauses a full saturation */ + /* List is deleted in red_SatUnit ! */ + EmptyClauses = red_SatUnit(Search, FormulaClauses); + if (!list_Empty(EmptyClauses)) { + Result = TRUE; + /*puts("\nPROOF in FormulaClauses");*/ + clause_DeleteClauseList(EmptyClauses); + } + + /* Move all usables to workedoff */ + FormulaClauses = list_Copy(prfs_UsableClauses(Search)); + for (Scan = FormulaClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) + prfs_MoveUsableWorkedOff(Search, (CLAUSE) list_Car(Scan)); + list_Delete(FormulaClauses); + FormulaClauses = list_Nil(); + +#ifdef CHECK + /*cnf_CheckClauseListsConsistency(ShIndex); */ +#endif + + + *Symblist = list_Nil(); + for (Scan = AllFormulae; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + LIST Ax, Pair; + UsedTerms = list_Nil(); + Pair = list_Car(Scan); +#ifdef CHECK_CNF + fputs("\nFormula : ", stdout); + term_Print((TERM) list_PairSecond(Pair)); + printf("\nLabel : %s", (char*) list_PairFirst(Pair)); +#endif + Ax = cnf_OptimizedSkolemization(Search, term_Copy((TERM)list_PairSecond(Pair)), + (char*) list_PairFirst(Pair), &UsedTerms, + Symblist,Result,FALSE,InputClauseToTermLabellist); + /* Set CONCLAUSE flag for clauses derived from conjectures */ + if (list_PointerMember(ConjectureList,list_PairSecond(Pair))) { + LIST l; + for (l = Ax; !list_Empty(l); l = list_Cdr(l)) + clause_SetFlag((CLAUSE) list_Car(l), CONCLAUSE); + } + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) { + hsh_PutListWithCompareFunc(TermLabelToClauselist, list_PairFirst(Pair), + list_Copy(Ax), + (BOOL (*)(POINTER,POINTER))cnf_LabelEqual, + (unsigned long (*)(POINTER))hsh_StringHashKey); + UsedTerms = list_Cons(list_PairFirst(Pair), UsedTerms); + UsedTerms = cnf_DeleteDuplicateLabelsFromList(UsedTerms); + for (Scan2 = Ax; !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) { + hsh_PutList(ClauseToTermLabellist, list_Car(Scan2), list_Copy(UsedTerms)); + hsh_PutList(InputClauseToTermLabellist, list_Car(Scan2), list_Copy(UsedTerms)); + } + } + *AxClauses = list_Nconc(*AxClauses, Ax); + list_Delete(UsedTerms); + } + + /* Transfer precedence of new skolem symbols into <InputPrecedence> */ + symbol_TransferPrecedence(Precedence, InputPrecedence); + + list_Delete(ConjectureList); + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) + hsh_Delete(InputClauseToTermLabellist); + if (!flag_GetFlagValue(Flags, flag_INTERACTIVE)) { + list_Delete(*Symblist); + } + + *AllLabels = list_Nil(); + for (Scan = AllFormulae; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + LIST Pair; + Pair = list_Car(Scan); + term_Delete((TERM) list_PairSecond(Pair)); + *AllLabels = list_Cons(list_PairFirst(Pair), *AllLabels); + list_PairFree(Pair); + } + + list_Delete(AllFormulae); + list_Delete(SkolemFunctions); + list_Delete(SkolemPredicates); + + if (!flag_GetFlagValue(Flags, flag_INTERACTIVE)) { + symbol_ResetSkolemIndex(); + prfs_Delete(Search); + return NULL; + } + else { + /* Delete DocProof clauses */ + prfs_DeleteDocProof(Search); + return Search; + } +} + +LIST cnf_QueryFlotter(PROOFSEARCH Search, TERM Term, LIST* Symblist) +/************************************************************** + INPUT: A term to derive clauses from, using optimized skolemization, + and a ProofSearch object. + RETURNS: A list of derived clauses. + EFFECT: ??? EK + The precedence of new skolem symbols is set in <Search>. +***************************************************************/ +{ + LIST SkolemPredicates, SkolemFunctions, IndexedClauses, Scan; + LIST ResultClauses, Dummy, EmptyClauses; + TERM TermCopy; + int Formulae2Clause; + BOOL Result; + FLAGSTORE Flags, SubProofFlags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + /* Initialize the flagstore of the cnf_SEARCHCOPY object with default values */ + /* and copy the value of flag_DOCPROOF from the global Proofserach object. */ + SubProofFlags = prfs_Store(cnf_SEARCHCOPY); + flag_InitStoreByDefaults(SubProofFlags); + flag_TransferFlag(Flags, SubProofFlags, flag_DOCPROOF); + /* Transfer the precedence into the local search object */ + symbol_TransferPrecedence(Precedence, prfs_Precedence(cnf_SEARCHCOPY)); + + SkolemPredicates = SkolemFunctions = list_Nil(); + Result = FALSE; + + prfs_CopyIndices(Search, cnf_SEARCHCOPY); + + Term = term_Create(fol_Not(), list_List(Term)); + fol_NormalizeVars(Term); + Term = cnf_ObviousSimplifications(Term); + if (flag_GetFlagValue(Flags, flag_CNFRENAMING)) { + term_AddFatherLinks(Term); + Term = ren_Rename(Term, Precedence, &SkolemPredicates, + flag_GetFlagValue(Flags,flag_CNFPRENAMING), TRUE); + } + Term = cnf_RemoveEquivImplFromFormula(Term); + Term = cnf_NegationNormalFormula(Term); + Term = cnf_AntiPrenex(Term); + + TermCopy = term_Copy(Term); + TermCopy = cnf_SkolemFormula(TermCopy, Precedence, &SkolemFunctions); + TermCopy = cnf_DistributiveFormula(TermCopy); + + IndexedClauses = cnf_MakeClauseList(TermCopy,FALSE,FALSE,Flags,Precedence); + term_Delete(TermCopy); + + /* red_SatUnit works only on conclauses */ + for (Scan = IndexedClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) + clause_SetFlag((CLAUSE) list_Car(Scan), CONCLAUSE); + + EmptyClauses = red_SatUnit(cnf_SEARCHCOPY, IndexedClauses); + + if (!list_Empty(EmptyClauses)) { + Result = TRUE; + clause_DeleteClauseList(EmptyClauses); + } + + while (!list_Empty(prfs_UsableClauses(cnf_SEARCHCOPY))) { + prfs_MoveUsableWorkedOff(cnf_SEARCHCOPY, (CLAUSE) list_Car(prfs_UsableClauses(cnf_SEARCHCOPY))); + } + /* Works only if DOCPROOF is false. Otherwise we need labels */ + Dummy = list_Nil(); + if (flag_GetFlagValue(SubProofFlags, flag_DOCPROOF)) + Formulae2Clause = TRUE; + else + Formulae2Clause = FALSE; + flag_SetFlagValue(SubProofFlags, flag_DOCPROOF, flag_DOCPROOFOFF); + ResultClauses = cnf_OptimizedSkolemization(cnf_SEARCHCOPY, term_Copy(Term), + NULL, &Dummy, Symblist, Result, + FALSE, NULL); + + if (Formulae2Clause) + flag_SetFlagValue(SubProofFlags, flag_DOCPROOF, flag_DOCPROOFON); + + term_Delete(Term); + list_Delete(SkolemPredicates); + list_Delete(SkolemFunctions); + prfs_Clean(cnf_SEARCHCOPY); + + /* All result clauses of queries are conjecture clauses */ + for (Scan=ResultClauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) + clause_SetFlag((CLAUSE) list_Car(Scan), CONCLAUSE); + + return ResultClauses; +} + + +#ifdef CHECK +/* Currently unused */ +/*static*/ void cnf_CheckClauseListsConsistency(SHARED_INDEX ShIndex) +/************************************************************** + INPUT: A shared index and a list of non-ConClauses. + EFFECT: When this function is called all clauses in the index must be + non-ConClauses, which must also be members of the list. +**************************************************************/ +{ + LIST AllClauses, scan; + + AllClauses = clause_AllIndexedClauses(ShIndex); + for (scan = AllClauses; scan != list_Nil(); scan = list_Cdr(scan)) { + if (clause_GetFlag((CLAUSE) list_Car(scan), CONCLAUSE)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cnf_CheckClauseListsConsistency: Clause is a CONCLAUSE.\n"); + misc_FinishErrorReport(); + } + if (clause_GetFlag((CLAUSE) list_Car(scan), BLOCKED)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cnf_CheckClauseListsConsistency: Clause is BLOCKED.\n"); + misc_FinishErrorReport(); + } + } + list_Delete(AllClauses); +} +#endif + + +static LIST cnf_SatUnit(PROOFSEARCH Search, LIST ClauseList) +/********************************************************* + INPUT: A list of unshared clauses, proof search object + RETURNS: A possibly empty list of empty clauses. +**********************************************************/ +{ + CLAUSE Given; + LIST Scan, Derivables, EmptyClauses, BackReduced; + NAT n, Derived; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + Derived = flag_GetFlagValue(Flags, flag_CNFPROOFSTEPS); + EmptyClauses = list_Nil(); + ClauseList = clause_ListSortWeighed(ClauseList); + + while (!list_Empty(ClauseList) && list_Empty(EmptyClauses)) { + Given = (CLAUSE)list_NCar(&ClauseList); + Given = red_CompleteReductionOnDerivedClause(Search, Given, red_ALL); + if (Given) { + if (clause_IsEmptyClause(Given)) + EmptyClauses = list_List(Given); + else { + /*fputs("\n\nGiven: ",stdout);clause_Print(Given);*/ + BackReduced = red_BackReduction(Search, Given, red_USABLE); + + if (Derived != 0) { + Derivables = + inf_BoundedDepthUnitResolution(Given, prfs_UsableSharingIndex(Search), + FALSE, Flags, Precedence); + Derivables = + list_Nconc(Derivables, + inf_BoundedDepthUnitResolution(Given,prfs_WorkedOffSharingIndex(Search), + FALSE, Flags, Precedence)); + n = list_Length(Derivables); + if (n > Derived) + Derived = 0; + else + Derived -= n; + } + else + Derivables = list_Nil(); + + Derivables = list_Nconc(BackReduced,Derivables); + Derivables = split_ExtractEmptyClauses(Derivables, &EmptyClauses); + + prfs_InsertUsableClause(Search, Given); + + for (Scan = Derivables; !list_Empty(Scan); Scan = list_Cdr(Scan)) + ClauseList = clause_InsertWeighed(list_Car(Scan), ClauseList, Flags, + Precedence); + list_Delete(Derivables); + } + } + } + clause_DeleteClauseList(ClauseList); + return EmptyClauses; +} + + +TERM cnf_DefTargetConvert(TERM Target, TERM ToTopLevel, TERM ToProveDef, + LIST DefPredArgs, LIST TargetPredArgs, + LIST TargetPredVars, LIST VarsForTopLevel, + FLAGSTORE Flags, PRECEDENCE Precedence, + BOOL* LocallyTrue) +/********************************************************** + INPUT: A term Target which contains a predicate that might be replaced + by its definition. + A term ToTopLevel which is the highest level subterm in Target + that contains the predicate and can be moved to top level or(). + A term ToProveDef which must hold if the definition is to be applied. + (IS DESTROYED AND FREED) + A list DefPredArgs of the arguments of the predicate in the + Definition. + A list TargetPredArgs of the arguments of the predicate in Target. + A list TargetPredVars of the variables occurring in the arguments + of the predicate in Target. + A list VarsForTopLevel containing the variables that should be + all-quantified at top level to make the proof easier. + A flag store. + A pointer to a boolean LocallyTrue which is set to TRUE iff + the definition can be applied. + RETURNS: The Target term which is brought into standard form. +**********************************************************/ + +{ + TERM orterm, targettoprove; + SYMBOL maxvar; /* For normalizing terms */ + LIST l1, l2; + LIST freevars, vars; /* Free variables in targettoprove */ + + if (flag_GetFlagValue(Flags, flag_PAPPLYDEFS)) { + puts("\nTarget :"); + fol_PrettyPrint(Target); + } +#ifdef CHECK + fol_CheckFatherLinks(Target); +#endif + /* No proof found yet */ + *LocallyTrue = FALSE; + + /* Remove implications from path */ + Target = cnf_RemoveImplFromFormulaPath(Target, ToTopLevel); + + /* Move negations as far down as possible */ + Target = cnf_NegationNormalFormulaPath(Target, ToTopLevel); + + /* Move quantifiers as far down as possible */ + Target = cnf_AntiPrenexPath(Target, ToTopLevel); + + /* Move all-quantified variables from the predicates' arguments to top level */ + Target = cnf_MovePredicateVariablesUp(Target, ToTopLevel, VarsForTopLevel); + + /* Flatten top or() */ + Target = cnf_FlattenPath(Target, ToTopLevel); + + /* Now make sure that all variables in the top forall quantifier are in TargetPredVars */ + /* Not necessary, according to CW */ + if (symbol_Equal(term_TopSymbol(Target), fol_All())) { + targettoprove = term_Copy(term_SecondArgument(Target)); + orterm = term_SecondArgument(Target); + } + else { + targettoprove = term_Copy(Target); + orterm = Target; + } + + /* Find argument of targettoprove that contains the predicate and remove it */ + if (symbol_Equal(term_TopSymbol(targettoprove), fol_Or())) { + /* Find subterm that contains the predicate */ + LIST arglist; + arglist = term_ArgumentList(targettoprove); + for (l1=arglist, l2=term_ArgumentList(orterm); !list_Empty(l1); + l1 = list_Cdr(l1), l2 = list_Cdr(l2)) { + if (term_HasProperSuperterm(ToTopLevel, (TERM) list_Car(l2)) || + (ToTopLevel == (TERM) list_Car(l2))) { + arglist = list_PointerDeleteElementFree(arglist, list_Car(l1), + (void (*)(POINTER))term_Delete); + break; + } + } + term_RplacArgumentList(targettoprove, arglist); + /* Nothing left for the proof ? */ + if (list_Empty(term_ArgumentList(targettoprove))) { + term_Delete(targettoprove); + term_Delete(ToProveDef); +#ifdef CHECK + fol_CheckFatherLinks(Target); +#endif + return Target; + } + } + else { + /* Nothing left for the proof */ + term_Delete(targettoprove); + term_Delete(ToProveDef); +#ifdef CHECK + fol_CheckFatherLinks(Target); +#endif + return Target; + } + + /* Normalize variables in ToProveDef with respect to targettoprove */ + maxvar = term_MaxVar(targettoprove); + symbol_SetStandardVarCounter(maxvar); + vars = fol_BoundVariables(ToProveDef); + vars = term_DeleteDuplicatesFromList(vars); + for (l1=vars; !list_Empty(l1); l1=list_Cdr(l1)) + term_ExchangeVariable(ToProveDef, term_TopSymbol(list_Car(l1)), symbol_CreateStandardVariable()); + list_Delete(vars); + + /* Replace arguments of predicate in condition of definition by matching arguments + of predicate in target term */ + for (l1=DefPredArgs, l2=TargetPredArgs; !list_Empty(l1); l1=list_Cdr(l1), l2=list_Cdr(l2)) + term_ReplaceVariable(ToProveDef, term_TopSymbol((TERM) list_Car(l1)), (TERM) list_Car(l2)); + + targettoprove = term_Create(fol_Not(), list_List(targettoprove)); + targettoprove = cnf_NegationNormalFormula(targettoprove); + targettoprove = term_Create(fol_Implies(), + list_Cons(targettoprove, list_List(ToProveDef))); + + /* At this point ToProveDef must not be accessed again ! */ + + /* Add all--quantifier to targettoprove */ + freevars = fol_FreeVariables(targettoprove); + term_CopyTermsInList(freevars); + targettoprove = fol_CreateQuantifier(fol_All(), freevars, list_List(targettoprove)); + + if (flag_GetFlagValue(Flags, flag_PAPPLYDEFS)) { + puts("\nConverted to :"); + fol_PrettyPrint(Target); + } + + targettoprove = cnf_NegationNormalFormula(targettoprove); + + if (flag_GetFlagValue(Flags, flag_PAPPLYDEFS)) { + puts("\nToProve for this target :"); + fol_PrettyPrint(targettoprove); + } + + *LocallyTrue = cnf_HaveProof(list_Nil(), targettoprove, Flags, Precedence); + + term_Delete(targettoprove); + +#ifdef CHECK + fol_CheckFatherLinks(Target); +#endif + + return Target; +} + + +static TERM cnf_RemoveQuantFromPathAndFlatten(TERM TopTerm, TERM SubTerm) +/********************************************************** + INPUT: Two terms, <SubTerm> must be a subterm of <TopTerm>. + Superterm of <SubTerm> must be an equivalence. + Along the path to SubTerm there are only quantifiers or disjunctions. + All free variables in the equivalence are free variables + in <SubTerm>. + All free variables in <SubTerm> are bound by a universal quantifier + (with polarity 1). + RETURN: The destructively changed <TopTerm>. + EFFECT: Removes all quantifiers not binding a variable in <SubTerm> + from <subTerm>'s path. + Moves all universal quantifiers binding free variable + in <SubTerm> up. + <TopTerm> is transformed into the form + forall([X1,...,Xn],or (equiv(<SubTerm>,psi),phi)). +**********************************************************/ +{ + TERM Term1, Term2, Flat, Variable; + LIST Scan1, Scan2, FreeVars; + + +#ifdef CHECK + if (!fol_CheckFormula(TopTerm) || !term_HasPointerSubterm(TopTerm, SubTerm)) { + misc_StartErrorReport(); + misc_ErrorReport("\nIn cnf_RemoveQuantFromPathAndFlatten: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + TopTerm = cnf_SimplifyQuantors(TopTerm); + term_AddFatherLinks(TopTerm); + Term1 = term_Superterm(SubTerm); + + while (Term1 != TopTerm) { + + while (symbol_Equal(fol_Or(), term_TopSymbol(Term1)) && (TopTerm != Term1)) { + Term1 = term_Superterm(Term1); + } + if (fol_IsQuantifier(term_TopSymbol(Term1))) { + Flat = term_SecondArgument(Term1); + Flat = cnf_Flatten(Flat, fol_Or()); + Scan1 = fol_QuantifierVariables(Term1); + while (!list_Empty(Scan1)) { + Variable = (TERM)list_Car(Scan1); + if (fol_VarOccursFreely(Variable, SubTerm)) { + Scan2 = list_Cdr(Scan1); + fol_DeleteQuantifierVariable(Term1, term_TopSymbol(list_Car(Scan1))); + Scan1 = Scan2; + } + else { + Scan1 = list_Cdr(Scan1); + } + } + if (fol_IsQuantifier(term_TopSymbol(Term1))) { + /* still variables, but not binding a variable in the equivalence term */ + LIST ArgList; + + term_RplacArgumentList(Flat, list_PointerDeleteOneElement(term_ArgumentList(Flat), SubTerm)); + ArgList = term_ArgumentList(Term1); + term_RplacArgumentList(Term1, list_Nil()); + Term2 = term_Create(term_TopSymbol(Term1), ArgList); + term_RplacArgumentList(Term1, list_Cons(SubTerm, list_List(Term2))); + term_RplacTop(Term1, fol_Or()); + Scan1 = term_ArgumentList(Term1); + while (!list_Empty(Scan1)) { + term_RplacSuperterm((TERM)list_Car(Scan1), Term1); + Scan1 = list_Cdr(Scan1); + } + } + } + else { + +#ifdef CHECK + if (!symbol_Equal(term_TopSymbol(Term1), fol_Or())) { + misc_StartErrorReport(); + misc_ErrorReport("\nIn cnf_RemoveQuantFromPathAndFlatten: Illegal term Term1"); + misc_FinishErrorReport(); + } +#endif + + Term1 = cnf_Flatten(Term1, fol_Or()); + } + } + FreeVars = fol_FreeVariables(Term1); + if (!list_Empty(FreeVars)) { + term_CopyTermsInList(FreeVars); + TopTerm = fol_CreateQuantifier(fol_All(), FreeVars, list_List(Term1)); + } + return TopTerm; +} + + +TERM cnf_DefConvert(TERM Def, TERM FoundPredicate, TERM* ToProve) +/********************************************************* + INPUT: A term Def which is an equivalence (P(x1,..,xn) <=> Formula) + that can be converted to standard form. + The subterm that holds the defined predicate. + A pointer to a term ToProve into which a term is stored + that has to be proved before applying the definition. + RETURNS: The converted definition : forall([..], or(equiv(..,..), ..)) +************************************************************/ +{ + TERM orterm; + +#ifdef CHECK + fol_CheckFatherLinks(Def); +#endif + + Def = cnf_RemoveImplFromFormulaPath(Def, FoundPredicate); /* Remove implications along the path */ + Def = cnf_NegationNormalFormulaPath(Def, FoundPredicate); /* Move not's as far down as possible */ + +#ifdef CHECK + if (!fol_CheckFormula(Def)) { + misc_StartErrorReport(); + misc_ErrorReport("\nIn cnf_DefConvert: Illegal input Formula.\n"); + misc_FinishErrorReport(); + } + if (!term_HasPointerSubterm(Def, FoundPredicate)) { + misc_StartErrorReport(); + misc_ErrorReport("\nIn cnf_DefConvert: Illegal input SubTerm.\n"); + misc_FinishErrorReport(); + } +#endif + + Def = cnf_RemoveQuantFromPathAndFlatten(Def, term_Superterm(FoundPredicate)); + term_AddFatherLinks(Def); + +#ifdef CHECK + if (!fol_CheckFormula(Def)) { + misc_StartErrorReport(); + misc_ErrorReport("\nIn cnf_DefConvert: Illegal term Def."); + misc_FinishErrorReport(); + } + if (!term_HasPointerSubterm(Def, FoundPredicate)) { + misc_StartErrorReport(); + misc_ErrorReport("\nIn cnf_DefConvert: Illegal term FoundPredicate."); + misc_FinishErrorReport(); + } +#endif + + /* Find top level or() */ + if (symbol_Equal(term_TopSymbol(Def), fol_All())) { + /* Make sure there are several arguments */ + if (symbol_Equal(term_TopSymbol(term_SecondArgument(Def)), fol_Or()) && + (list_Length(term_ArgumentList(term_SecondArgument(Def))) == 1)) { + TERM t; + t = term_SecondArgument(Def); + term_RplacSecondArgument(Def, term_FirstArgument(term_SecondArgument(Def))); + term_Free(t); + orterm = NULL; + term_RplacSuperterm(term_SecondArgument(Def), Def); + } + else + orterm = term_SecondArgument(Def); + } + else { + /* Make sure there are several arguments */ + if (symbol_Equal(term_TopSymbol(Def), fol_Or()) && + (list_Length(term_ArgumentList(Def)) == 1)) { + TERM t; + t = Def; + Def = term_FirstArgument(Def); + term_Free(t); + orterm = NULL; + term_RplacSuperterm(term_SecondArgument(Def), Def); + } + else + orterm = Def; + } + + /* If there is something to prove */ + if (orterm != (TERM) NULL) { + TERM equiv; + LIST args; + + equiv = (TERM) NULL; + + /* In pell 10 there are no conditions for the equivalence */ + if (symbol_Equal(term_TopSymbol(orterm), fol_Equiv())) { + equiv = orterm; + *ToProve = NULL; + } + else { + TERM t; + /* First find equivalence term among arguments */ + args = term_ArgumentList(orterm); + equiv = term_Superterm(FoundPredicate); + + /* Delete equivalence from list */ + args = list_PointerDeleteElement(args, equiv); + term_RplacArgumentList(orterm, args); + + /* ToProve consists of all the definitions arguments except the equivalence */ + *ToProve = term_Copy(orterm); + + /* Now not(*ToProve) implies the equivalence */ + /* Negate *ToProve */ + *ToProve = term_Create(fol_Not(), list_List(*ToProve)); + *ToProve = cnf_NegationNormalFormula(*ToProve); + term_AddFatherLinks(*ToProve); + + /* Now convert definition to implication form */ + term_RplacTop(orterm, fol_Implies()); + t = term_Create(fol_Not(), + list_List(term_Create(fol_Or(), + term_ArgumentList(orterm)))); + term_RplacArgumentList(orterm, list_Cons(t, list_List(equiv))); + + Def = cnf_NegationNormalFormula(Def); + term_AddFatherLinks(Def); + } + } + +#ifdef CHECK + fol_CheckFatherLinks(Def); +#endif + return Def; +} + + +LIST cnf_HandleDefinition(PROOFSEARCH Search, LIST Pair, LIST Axioms, + LIST Sorts, LIST Conjectures) +/******************************************************************* + INPUT: A PROOFSEARCH object, a pair (label, term) and 3 lists of pairs. + If the term in pair is a definition, the defined predicate + is expanded in all the lists + and added to the proofsearch object. + RETURNS: The pair with the converted definition: + forall([..], or(equiv(..,..), .......)) +********************************************************************/ +{ + TERM definition, defpredicate, equivterm; + + BOOL alwaysapplicable; /* Is set to TRUE iff the definition can always be applied */ + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + /* The axiomlist consists of (label, formula) pairs */ + definition = list_PairSecond(Pair); + + /* Test if Definition contains a definition */ + defpredicate = (TERM) NULL; + if (cnf_ContainsDefinition(definition, &defpredicate)) { + TERM toprove; + LIST allformulae, scan; + + /* Create list of all formula pairs */ + /* Check if definition may be applied to each formula */ + allformulae = list_Copy(Axioms); + allformulae = list_Nconc(allformulae, list_Copy(Sorts)); + allformulae = list_Nconc(allformulae, list_Copy(Conjectures)); +#ifdef CHECK + for (scan=allformulae; !list_Empty(scan); scan=list_Cdr(scan)) { + if (!list_Empty((LIST) list_Car(scan))) { + if (!term_IsTerm((TERM) list_PairSecond((LIST) list_Car(scan)))) + fol_CheckFatherLinks((TERM) list_PairSecond((LIST) list_Car(scan))); + } + } +#endif + + /* Convert definition to standard form */ + if (flag_GetFlagValue(Flags, flag_PAPPLYDEFS)) { + fputs("\nPredicate : ", stdout); + symbol_Print(term_TopSymbol(defpredicate)); + } + + definition = cnf_DefConvert(definition, defpredicate, &toprove); + if (toprove == NULL) + alwaysapplicable = TRUE; + else + alwaysapplicable = FALSE; + + prfs_SetDefinitions(Search, list_Cons(term_Copy(definition), + prfs_Definitions(Search))); + + if (flag_GetFlagValue(Flags, flag_PAPPLYDEFS)) { + if (alwaysapplicable) { + fputs("\nAlways Applicable : ", stdout); + fol_PrettyPrint(definition); + } + } + + /* Definition is converted to a form where the equivalence is + the first argument of the disjunction */ + equivterm = term_SecondArgument(term_Superterm(defpredicate)); + + + scan = allformulae; + while (!list_Empty(scan)) { + BOOL localfound; + LIST pair, targettermvars; + + /* Pair label / term */ + pair = list_Car(scan); + + /* Pair may be NULL if it is a definition that could be deleted */ + if ((pair != NULL) && (definition != (TERM) list_PairSecond(pair))) { + TERM target, targetpredicate, totoplevel; + LIST varsfortoplevel; + target = (TERM) list_PairSecond(pair); + targettermvars = varsfortoplevel = list_Nil(); + + /* If definition is not always applicable, check if it is applicable + for this formula */ + localfound = FALSE; + if (!alwaysapplicable) { + if (cnf_ContainsPredicate(target, term_TopSymbol(defpredicate), + &targetpredicate, &totoplevel, + &targettermvars, &varsfortoplevel)) { + TERM toprovecopy; + toprovecopy = term_Copy(toprove); + target = cnf_DefTargetConvert(target, totoplevel, toprovecopy, + term_ArgumentList(defpredicate), + term_ArgumentList(targetpredicate), + targettermvars, varsfortoplevel, + Flags, Precedence, &localfound); + list_Delete(targettermvars); + list_Delete(varsfortoplevel); + targettermvars = varsfortoplevel = list_Nil(); + + list_Rplacd(pair, (LIST) target); + if (localfound) + list_Rplacd(pair, + (LIST) cnf_ApplyDefinitionOnce(defpredicate, + equivterm, + list_PairSecond(pair), + targetpredicate, + Flags)); + } + } + else { + if (cnf_ContainsPredicate(target, term_TopSymbol(defpredicate), + &targetpredicate, &totoplevel, + &targettermvars, &varsfortoplevel)) + list_Rplacd(pair, (LIST) cnf_ApplyDefinitionOnce(defpredicate, + equivterm, + list_PairSecond(pair), + targetpredicate, + Flags)); + else + scan = list_Cdr(scan); + list_Delete(targettermvars); + list_Delete(varsfortoplevel); + targettermvars = varsfortoplevel = list_Nil(); + } + } + else + scan = list_Cdr(scan); + } + list_Delete(allformulae); + /* toprove can be NULL if the definition can always be applied */ + if (toprove != (TERM) NULL) + term_Delete(toprove); + list_Rplacd(Pair, (LIST) definition); + } + + return Pair; +} + + +LIST cnf_ApplyDefinitionToClause(CLAUSE Clause, TERM Predicate, TERM Expansion, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, two terms and a flag store and a precedence. + RETURNS: The list of clauses where each occurrence of Predicate is + replaced by Expansion. +***************************************************************/ +{ + NAT i; + BOOL changed; + LIST args, scan, symblist; + TERM clauseterm, argument; + + changed = FALSE; + + /* Build term from clause */ + args = list_Nil(); + for (i = 0; i < clause_Length(Clause); i++) { + argument = clause_GetLiteralTerm(Clause, i); /* with sign */ + args = list_Cons(term_Copy(argument), args); + } + clauseterm = term_Create(fol_Or(), args); + + for (scan=term_ArgumentList(clauseterm); !list_Empty(scan); scan=list_Cdr(scan)) { + BOOL isneg; + + argument = (TERM) list_Car(scan); + if (symbol_Equal(term_TopSymbol(argument), fol_Not())) { + argument = term_FirstArgument(argument); + isneg = TRUE; + } + else + isneg = FALSE; + + /* Try to match with predicate */ + cont_StartBinding(); + if (unify_Match(cont_LeftContext(), Predicate, argument)) { + SUBST subst; + TERM newargument; + subst = subst_ExtractMatcher(); + newargument = subst_Apply(subst, term_Copy(Expansion)); + subst_Free(subst); + if (isneg) + newargument = term_Create(fol_Not(), list_List(newargument)); + term_Delete((TERM) list_Car(scan)); + list_Rplaca(scan, newargument); + changed = TRUE; + } + cont_BackTrack(); + } + + if (changed) { + /* Build term and derive list of clauses */ + LIST result; + if (flag_GetFlagValue(Flags, flag_PAPPLYDEFS)) { + puts("\nClause before applying def :"); + clause_Print(Clause); + puts("\nPredicate :"); + fol_PrettyPrint(Predicate); + puts("\nExpansion :"); + fol_PrettyPrint(Expansion); + } + symblist = list_Nil(); + clauseterm = cnf_Cnf(clauseterm, Precedence, &symblist); + result = cnf_MakeClauseList(clauseterm,FALSE,FALSE,Flags,Precedence); + list_Delete(symblist); + term_Delete(clauseterm); + if (flag_GetFlagValue(Flags, flag_PAPPLYDEFS)) { + LIST l; + puts("\nClauses derived by expanding definition :"); + for (l = result; !list_Empty(l); l=list_Cdr(l)) { + clause_Print((CLAUSE) list_Car(l)); + fputs("\n", stdout); + } + } + return result; + } + else { + term_Delete(clauseterm); + return list_Nil(); + } +} + + +BOOL cnf_PropagateSubstEquations(TERM StartTerm) +/************************************************************* + INPUT: A term where we assume that father links are established and + that no variable is bound by more than one quantifier. + RETURNS: TRUE, if any substitutions were made, FALSE otherwise. + EFFECT: Function looks for equations of the form x=t where x does not + occur in t. If x=t occurs negatively and disjunctively below + a universal quantifier binding x or if x=t occurs positively and + conjunctively below an existential quantifier binding x, + all occurrences of x are replaced by t in <StartTerm>. +**************************************************************/ +{ + LIST Subequ; + TERM QuantorTerm, Equation, EquationTerm; + SYMBOL Variable; + BOOL Hit, Substituted; + +#ifdef CHECK + if (fol_VarBoundTwice(StartTerm)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cnf_PropagateSubstEquations: Variables of"); + misc_ErrorReport("\n input term are not normalized."); + misc_FinishErrorReport(); + } +#endif + + Substituted = FALSE; + + Subequ = fol_GetSubstEquations(StartTerm); + for ( ; !list_Empty(Subequ); Subequ = list_Pop(Subequ)) { + Hit = FALSE; + Equation = list_Car(Subequ); + Variable = symbol_Null(); + QuantorTerm = term_Null(); + EquationTerm = term_Null(); + + if (term_IsVariable(term_FirstArgument(Equation)) && + !term_ContainsVariable(term_SecondArgument(Equation), + term_TopSymbol(term_FirstArgument(Equation)))) { + + Variable = term_TopSymbol(term_FirstArgument(Equation)); + QuantorTerm = fol_GetBindingQuantifier(Equation, Variable); + EquationTerm = term_SecondArgument(Equation); + Hit = fol_PolarCheck(Equation, QuantorTerm); + } + if (!Hit && term_IsVariable(term_SecondArgument(Equation)) && + !term_ContainsVariable(term_FirstArgument(Equation), + term_TopSymbol(term_SecondArgument(Equation)))) { + + Variable = term_TopSymbol(term_SecondArgument(Equation)); + QuantorTerm = fol_GetBindingQuantifier(Equation, Variable); + EquationTerm = term_FirstArgument(Equation); + Hit = fol_PolarCheck(Equation, QuantorTerm); + } + if (Hit) { + fol_DeleteQuantifierVariable(QuantorTerm,Variable); + term_ReplaceVariable(StartTerm, Variable, EquationTerm); /* We replace everythere ! */ + term_AddFatherLinks(StartTerm); + if (symbol_Equal(term_TopSymbol(QuantorTerm),fol_Equality())) /* Trivial Formula */ + fol_SetTrue(QuantorTerm); + else + fol_SetTrue(Equation); + Substituted = TRUE; + } + } + + /* <Subequ> was freed in the loop. */ + + return Substituted; +} diff --git a/test/spass/cnf.h b/test/spass/cnf.h new file mode 100644 index 0000000000000000000000000000000000000000..be04c5f67e0fb22ea5537ad6bcf199ef7d10341e --- /dev/null +++ b/test/spass/cnf.h @@ -0,0 +1,120 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * NAIVE CNF TRANSLATOR * */ +/* * * */ +/* * $Module: CNF * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#ifndef _CNF_ +#define _CNF_ + +#include "hasharray.h" +#include "renaming.h" +#include "resolution.h" +#include "search.h" +#include "flags.h" + +#include <string.h> + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +static __inline__ BOOL cnf_LabelEqual(const char* l1, const char* l2) +/******************************************************** + INPUT: Two labels. + RETURNS: TRUE, if the labels are equal, FALSE otherwise. +*********************************************************/ +{ + return string_Equal(l1, l2); +} + + +static __inline__ LIST cnf_DeleteDuplicateLabelsFromList(LIST Labels) +/******************************************************** + INPUT: A list of labels. + RETURNS: The list where duplicate labels are removed. + EFFECTS: The duplicate labels are not freed. +*********************************************************/ +{ + return list_DeleteDuplicates(Labels, (BOOL (*)(POINTER,POINTER))cnf_LabelEqual); +} + + +TERM cnf_ApplyDefinitionOnce(TERM, TERM, TERM, TERM, FLAGSTORE); +LIST cnf_ApplyDefinitionToClause(CLAUSE, TERM, TERM,FLAGSTORE,PRECEDENCE); + +BOOL cnf_ContainsDefinition(TERM, TERM*); +BOOL cnf_ContainsPredicate(TERM, SYMBOL, TERM*, TERM*, LIST*, LIST*); + +TERM cnf_DeSkolemFormula(LIST); +TERM cnf_DefConvert(TERM, TERM, TERM*); +void cnf_FilePrint(TERM, FILE*); +TERM cnf_DefTargetConvert(TERM, TERM, TERM, LIST, LIST, LIST, LIST, + FLAGSTORE, PRECEDENCE, BOOL*); + +void cnf_FilePrintPrefix(TERM, FILE*); +void cnf_FPrint(TERM, FILE*); +TERM cnf_Flatten(TERM, SYMBOL); +PROOFSEARCH cnf_Flotter(LIST, LIST, LIST*, LIST*, HASH, HASH, FLAGSTORE, + PRECEDENCE, LIST*); +void cnf_Free(FLAGSTORE); + +LIST cnf_HandleDefinition(PROOFSEARCH, LIST, LIST, LIST, LIST); +void cnf_Init(FLAGSTORE); +TERM cnf_NegationNormalFormula(TERM); +TERM cnf_ObviousSimplifications(TERM); + +LIST cnf_QueryFlotter(PROOFSEARCH, TERM, LIST*); +void cnf_StdoutPrint(TERM); + +BOOL cnf_PropagateSubstEquations(TERM); + +BOOL cnf_HaveProof(LIST, TERM, FLAGSTORE, PRECEDENCE); + + +#endif diff --git a/test/spass/component.c b/test/spass/component.c new file mode 100644 index 0000000000000000000000000000000000000000..def8e30cab803eddb992264221f32a89c61043c4 --- /dev/null +++ b/test/spass/component.c @@ -0,0 +1,266 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * COMPONENTS OF CLAUSES * */ +/* * * */ +/* * $Module: COMPONENT * */ +/* * * */ +/* * Copyright (C) 1996, 1998, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "term.h" +#include "component.h" + + +CLITERAL literal_Create(BOOL used, int index, LIST varlist) +/********************************************************** + INPUT: A boolean used, an integer index and a list varlist. + RETURNS: A LITERAL is created. + MEMORY: The boolean, integer and varlist are no copies. +*** ********************************************************/ +{ + CLITERAL literal; + + literal = (CLITERAL)memory_Malloc(sizeof(CLITERAL_NODE)); + literal_PutUsed(literal,used); + literal_PutLitIndex(literal,index); + literal_PutLitVarList(literal,varlist); + + return literal; +} + + +void literal_Delete(CLITERAL literal) +/********************************************************** + INPUT: A literal. + RETURNS: None. + MEMORY: Deletes the LITERAL and frees the storage. +***********************************************************/ +{ + list_Delete(literal_GetLitVarList(literal)); + literal_Free(literal); +} + + +LITPTR litptr_Create(LIST Indexlist, LIST Termsymblist) +/********************************************************** + INPUT: A list indexes and a list of terms, i.e. a list of integers. + RETURNS: A LITPTR structure is created. + MEMORY: The integers in the created structure are the integers + in indexList, no copies. +***********************************************************/ +{ + LITPTR lit_ptr; + LIST Scan,varlist; + CLITERAL literal; + int index,n,k; + + n = list_Length(Indexlist); + + lit_ptr = (LITPTR)memory_Malloc(sizeof(LITPTR_NODE)); + litptr_SetLength(lit_ptr, n); + + if (n > 0) { + lit_ptr->litptr = (CLITERAL *)memory_Malloc(n * sizeof(CLITERAL)); + + k = 0; + for (Scan = Indexlist; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + index = (int)list_Car(Scan); + varlist = (LIST)list_Car(Termsymblist); + Termsymblist = list_Cdr(Termsymblist); + literal = literal_Create(FALSE,index,varlist); + + litptr_SetLiteral(lit_ptr, k, literal); + + k++; + } + } else + lit_ptr->litptr = NULL; + + return lit_ptr; +} + + +void litptr_Delete(LITPTR lit_ptr) +/********************************************************** + INPUT: A pointer to LITPTR. + MEMORY: Deletes the LITPTR and frees the storage. +***********************************************************/ +{ + int n,i; + + n = litptr_Length(lit_ptr); + + if (n > 0) { + for (i = 0; i < n; i++) + literal_Delete(litptr_Literal(lit_ptr,i)); + + memory_Free(lit_ptr->litptr, sizeof(CLITERAL) * n); + memory_Free(lit_ptr, sizeof(LITPTR_NODE)); + } else + memory_Free(lit_ptr, sizeof(LITPTR_NODE)); +} + + +void litptr_Print(LITPTR lit_ptr) +/************************************************************** + INPUT: A term. + RETURNS: void. + SUMMARY: Prints any term to stdout. + CAUTION: Uses the other term_Output functions. +***************************************************************/ +{ + int i,n; + + n = litptr_Length(lit_ptr); + /*n = lit_ptr->length;*/ + + if (n > 0) { + printf("\nlength of LITPTR: %d\n",n); + for (i = 0; i < n; i++) { + printf("Entries of literal %d : \n",i); + puts("----------------------"); + fputs("used:\t\t", stdout); + + if (literal_GetUsed(litptr_Literal(lit_ptr,i))) + /*if (lit_ptr->litptr[i]->used)*/ + puts("TRUE"); + else + puts("FALSE"); + printf("litindex:\t%d\n", + literal_GetLitIndex(litptr_Literal(lit_ptr,i))); + fputs("litvarlist:\t", stdout); + list_Apply((void (*)(POINTER)) symbol_Print, + literal_GetLitVarList(litptr_Literal(lit_ptr,i))); + puts("\n"); + } + }else + puts("No entries in litptr structure"); +} + + +BOOL litptr_AllUsed(LITPTR lit_ptr) +/************************************************************** + INPUT: A LITPTR. + RETURNS: TRUE if every literal in the LITPTR is used and + FALSE otherwise. +***************************************************************/ +{ + int n,i; + + n = litptr_Length(lit_ptr); + + for (i = 0; i < n; i++) + if (!(literal_GetUsed(litptr_Literal(lit_ptr,i)))) + return FALSE; + + return TRUE; +} + + +LIST subs_CompList(LITPTR litptr) +/********************************************************** + INPUT: A pointer litptr. + RETURNS: A list with indexes which represents the first component of + with respect to the actual bindings and to litptr. + CAUTION: The structure to which litptr points to + is changed destructively in the used slot. +***********************************************************/ +{ + BOOL found,hasinter; + LIST scan,complist,compindexlist; + int n,i,j,lit; + + compindexlist = list_Nil(); /* the result will be placed into this list */ + complist = list_Nil(); /* added afterwards */ + n = litptr_Length(litptr); + + if (n > 0) { + for (j = 0; j < n; j++) { + printf("\nj = %d\n",j); + if (!literal_GetUsed(litptr_Literal(litptr,j))){ + complist = list_Nil(); + complist = list_Cons((POINTER)j,complist); + compindexlist = list_Cons((POINTER)(litptr->litptr[j]->litindex), + compindexlist); + literal_PutUsed(litptr_Literal(litptr,j), TRUE); + j = n+1; + printf("\nj == %d\n",j); + } + } + + if (j == n){ + list_Delete(complist); /* There is no more component */ + return compindexlist; /* should be empty here */ + } + + found = TRUE; + while (found) { + found = FALSE; + for (scan = complist; !list_Empty(scan); scan = list_Cdr(scan)) { + lit = (int)list_Car(scan); + for (i = 0; i < n; i++) { + if (!literal_GetUsed(litptr_Literal(litptr,i))) { + printf("lit = %d\n",lit); + printf("i = %d\n",i); + + hasinter = list_HasIntersection(litptr->litptr[lit]->litvarlist, + litptr->litptr[i]->litvarlist); + + if (hasinter) { + puts("hasinter = TRUE"); + complist = list_Cons((POINTER)i,complist); + compindexlist = list_Cons((POINTER)(litptr->litptr[i]->litindex),compindexlist); + literal_PutUsed(litptr_Literal(litptr,i), TRUE); + found = TRUE; + } + } + } + } + + if (!found) { /* one component is finished */ + list_Delete(complist); + found = FALSE; + } + } + } + + return compindexlist; +} diff --git a/test/spass/component.h b/test/spass/component.h new file mode 100644 index 0000000000000000000000000000000000000000..14cb0962094258f95b32cf26d5fcc295d67f266b --- /dev/null +++ b/test/spass/component.h @@ -0,0 +1,151 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * COMPONENTS OF CLAUSES * */ +/* * * */ +/* * $Module: COMPONENT * */ +/* * * */ +/* * Copyright (C) 1996, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _COMPONENT_ +#define _COMPONENT_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "list.h" + +/**************************************************************/ +/* Structures */ +/**************************************************************/ + +typedef struct cliteral { + BOOL used; /* Flag if the index is already used */ + int litindex; /* Index of the literal in the original clause */ + LIST litvarlist; /* List of variables of the literal */ +} *CLITERAL, CLITERAL_NODE; + + +typedef struct litptr { + CLITERAL *litptr; /* Array of Pointer to literals */ + int length; /* Number of literal in the array *litptr */ +} *LITPTR, LITPTR_NODE; + +/**************************************************************/ +/* Macros */ +/**************************************************************/ + +static __inline__ BOOL literal_GetUsed(CLITERAL C) +{ + return C->used; +} + +static __inline__ int literal_GetLitIndex(CLITERAL C) +{ + return C->litindex; +} + +static __inline__ LIST literal_GetLitVarList(CLITERAL C) +{ + return C->litvarlist; +} + +static __inline__ void literal_PutUsed(CLITERAL C,BOOL Bool) +{ + C->used = Bool; +} + +static __inline__ void literal_PutLitIndex(CLITERAL C, int I) +{ + C->litindex = I; +} + +static __inline__ void literal_PutLitVarList(CLITERAL C, LIST L) +{ + C->litvarlist = L; +} + +static __inline__ CLITERAL litptr_Literal(LITPTR C, int I) +{ + return C->litptr[I]; +} + +static __inline__ void litptr_SetLiteral(LITPTR LP, int I, CLITERAL CL) +{ + LP->litptr[I] = CL; +} + + +static __inline__ int litptr_Length(LITPTR C) +{ + return C->length; +} + +static __inline__ void litptr_SetLength(LITPTR C, int n) +{ + C->length = n; +} + +static __inline__ void litptr_IncLength(LITPTR C) +{ + (C->length)++; +} + +static __inline__ void literal_Free(CLITERAL Lit) +{ + memory_Free(Lit, sizeof(CLITERAL_NODE)); +} + + +/**************************************************************/ +/* Functions on a Component and on a Literal */ +/**************************************************************/ + +CLITERAL literal_Create(BOOL, int, LIST); +void literal_Delete(CLITERAL); + +LITPTR litptr_Create(LIST, LIST); +void litptr_Delete(LITPTR); +void litptr_Print(LITPTR); +BOOL litptr_AllUsed(LITPTR); + + +#endif diff --git a/test/spass/condensing.c b/test/spass/condensing.c new file mode 100644 index 0000000000000000000000000000000000000000..fca04bf614091822182effa3f35662c9d42da7a4 --- /dev/null +++ b/test/spass/condensing.c @@ -0,0 +1,100 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CONDENSATION OF CLAUSES * */ +/* * * */ +/* * $Module: CONDENSING * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "subsumption.h" +#include "misc.h" +#include "condensing.h" + + +LIST cond_CondFast(CLAUSE c) +/********************************************************** + INPUT: A clause c. + RETURNS: A list with indexes with respect to c that can + be deleted due to condensing. + CAUTION: None. +***********************************************************/ +{ + int vec, i, j, k; + LIST indexlist; + + indexlist = list_Nil(); + vec = vec_ActMax(); + + for (i = 0; i < clause_Length(c); i++) { + vec_Push((POINTER) i); + } + + for (k = clause_Length(c) - 1; k >= 0; k--) { + for (i = vec; i < vec_ActMax(); i++) { + if ((int)vec_GetNth(i) != k) { + cont_StartBinding(); + if (unify_Match(cont_LeftContext(), + clause_GetLiteralTerm(c,k), + clause_GetLiteralTerm(c,(int)vec_GetNth(i)))) { + cont_BackTrack(); + for (j = vec; j < vec_ActMax(); j++) { + if (k == (int)vec_GetNth(j)) { + vec_Swap((vec_ActMax() -1) ,j); + j = vec_ActMax(); + } + } + + if (subs_IdcRes(c,vec,(vec_ActMax() -1))) { + indexlist = list_Cons((POINTER)k,indexlist); + vec_Pop(); + } + + i = vec_ActMax()+1; + } + else + cont_BackTrack(); + } + } + } + + vec_SetMax(vec); + return indexlist; +} diff --git a/test/spass/condensing.h b/test/spass/condensing.h new file mode 100644 index 0000000000000000000000000000000000000000..7da40a50fe755ed24ed12b0c0f47d8a72d860605 --- /dev/null +++ b/test/spass/condensing.h @@ -0,0 +1,64 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CONDENSATION OF CLAUSES * */ +/* * * */ +/* * $Module: CONDENSING * */ +/* * * */ +/* * Copyright (C) 1996, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _CONDENSING_ +#define _CONDENSING_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "unify.h" + + +/**************************************************************/ +/* Function Prototypes */ +/**************************************************************/ + +LIST cond_CondFast(CLAUSE); + + +#endif diff --git a/test/spass/context.c b/test/spass/context.c new file mode 100644 index 0000000000000000000000000000000000000000..7d3aacbe714191dcf728fdfde53c796d53513728 --- /dev/null +++ b/test/spass/context.c @@ -0,0 +1,636 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CONTEXTS FOR VARIABLES * */ +/* * * */ +/* * $Module: CONTEXT * */ +/* * * */ +/* * Copyright (C) 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "context.h" + +/**************************************************************/ +/* Global Variables */ +/**************************************************************/ + +int cont_NOOFCONTEXTS; +LIST cont_LISTOFCONTEXTS; +int cont_BINDINGS; + +SYMBOL cont_INDEXVARSCANNER; + +CONTEXT cont_LASTBINDING; /* The last binding made. */ +CONTEXT cont_CURRENTBINDING; /* Help variable. */ + +CONTEXT cont_LEFTCONTEXT; +CONTEXT cont_RIGHTCONTEXT; +CONTEXT cont_INSTANCECONTEXT; + +cont_STACK_TYPE cont_STACK; +int cont_STACKPOINTER; + +cont_CHECKSTACK_TYPE cont_CHECKSTACK; +int cont_CHECKSTACKPOINTER; + +CONTEXT cont_STATELASTBINDING; /* Storage to save state of trails. */ +int cont_STATEBINDINGS; /* Storage to save number of current bindings. */ +int cont_STATESTACK; /* Storage to save state of stack. */ +int cont_STATETOPSTACK; /* Storage to save state of the top element of the stack. */ + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INITIALIZATION * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +void cont_Init(void) +/********************************************************** + INPUT: None. + RETURNS: None. + EFFECT: Initializes the unify module. +********************************************************/ +{ + cont_LASTBINDING = (CONTEXT)NULL; + + cont_ResetIndexVarScanner(); + + cont_NOOFCONTEXTS = 0; + cont_LISTOFCONTEXTS = list_Nil(); + cont_BINDINGS = 0; + + cont_INSTANCECONTEXT = (CONTEXT)memory_Malloc(sizeof(CONTEXT_NODE)); + + cont_LEFTCONTEXT = cont_Create(); + cont_RIGHTCONTEXT = cont_Create(); + + cont_StackInit(); + cont_StackPush(0); + cont_StackPop(); +} + + +void cont_Check(void) +/********************************************************** + INPUT: None. + RETURNS: None. + EFFECT: Frees internal structures of the unify module. +********************************************************/ +{ +#ifdef CHECK + if (cont_LASTBINDING || (cont_BINDINGS != 0) || + !symbol_Equal(cont_INDEXVARSCANNER, + symbol_GetInitialIndexVarCounter())) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_Check: There are variable bindings not reset.\n"); + misc_FinishErrorReport(); + } +#endif +} + + +void cont_Free(void) +/********************************************************** + INPUT: None. + RETURNS: None. + EFFECT: Frees internal structures of the unify module. +********************************************************/ +{ + cont_Check(); + + while (cont_NOOFCONTEXTS > 0) + cont_Delete(list_Car(cont_LISTOFCONTEXTS)); /* Decreases NOOFCONTEXTS */ + + cont_BINDINGS = 0; + + memory_Free(cont_INSTANCECONTEXT, sizeof(CONTEXT_NODE)); +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * TERM EQUALITY WITH RESPECT TO BOUND VARIABLES * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +BOOL cont_TermEqual(CONTEXT Context1, TERM Term1, CONTEXT Context2, TERM Term2) +/********************************************************* + INPUT: Two terms and two contexts. + RETURNS: TRUE iff the two terms are equal, where + variables are interpreted with respect to + the bindings in the contexts. +********************************************************/ +{ +#ifdef CHECK + if (!(term_IsTerm(Term1) && term_IsTerm(Term2))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_TermEqual: Input terms are corrupted.\n"); + misc_FinishErrorReport(); + } +#endif + + Term1 = cont_Deref(&Context1,Term1); + Term2 = cont_Deref(&Context2,Term2); + + if (!term_EqualTopSymbols(Term1, Term2)) + return FALSE; + else if (term_ArgumentList(Term1)) { + LIST Scan1, Scan2; + for (Scan1=term_ArgumentList(Term1), Scan2=term_ArgumentList(Term2); + list_Exist(Scan1) && list_Exist(Scan2); + Scan1=list_Cdr(Scan1), Scan2=list_Cdr(Scan2)) + if (!cont_TermEqual(Context1,list_Car(Scan1), Context2,list_Car(Scan2))) + return FALSE; + return (list_Empty(Scan1) ? list_Empty(Scan2) : FALSE); + } else + return TRUE; +} + + +BOOL cont_TermEqualModuloBindings(CONTEXT IndexContext, CONTEXT CtL, TERM TermL, + CONTEXT CtR, TERM TermR) +/********************************************************* + INPUT: Two contexts, two terms. + RETURNS: The boolean value TRUE if the terms are equal. + CAUTION: EQUAL FUNCTION- OR PREDICATE SYMBOLS SHARE THE + SAME ARITY. THIS IS NOT VALID FOR JUNCTORS! +*******************************************************/ +{ +#ifdef CHECK + if (!(term_IsTerm(TermL) && term_IsTerm(TermR))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_TermEqualModuloBindings: Input terms are corrupted.\n"); + misc_FinishErrorReport(); + } +#endif + + while (term_IsVariable(TermL)) { + SYMBOL TermTop; + + TermTop = term_TopSymbol(TermL); + + if (symbol_IsIndexVariable(TermTop)) + CtL = IndexContext; + else if (CtL == cont_InstanceContext()) + break; + + if (cont_VarIsBound(CtL, TermTop)) { + CONTEXT CHelp; + + CHelp = cont_ContextBindingContext(CtL, TermTop); + TermL = cont_ContextBindingTerm(CtL, TermTop); + CtL = CHelp; + } else + break; + } + + while (term_IsVariable(TermR)) { + SYMBOL TermTop; + + TermTop = term_TopSymbol(TermR); + + if (symbol_IsIndexVariable(TermTop)) + CtR = IndexContext; + else if (CtR == cont_InstanceContext()) + break; + + if (cont_VarIsBound(CtR, TermTop)) { + CONTEXT CHelp; + + CHelp = cont_ContextBindingContext(CtR, TermTop); + TermR = cont_ContextBindingTerm(CtR, TermTop); + CtR = CHelp; + } else + break; + } + + if (!term_EqualTopSymbols(TermL, TermR)) + return FALSE; + else + if (term_IsVariable(TermL)) { + if (CtL == CtR) + return TRUE; + else + return FALSE; + } + else + if (term_IsComplex(TermL)) { + LIST ScanL, ScanR; + + for (ScanL=term_ArgumentList(TermL), ScanR=term_ArgumentList(TermR); + list_Exist(ScanL) && list_Exist(ScanR); + ScanL=list_Cdr(ScanL), ScanR=list_Cdr(ScanR)) + if (!cont_TermEqualModuloBindings(IndexContext, CtL, list_Car(ScanL), + CtR, list_Car(ScanR))) + return FALSE; + + return (list_Empty(ScanL) ? list_Empty(ScanR) : FALSE); + + } + else + return TRUE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * APPLY BINDINGS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +TERM cont_CopyAndApplyBindings(CONTEXT TermContext, TERM Term) +{ + while (term_IsVariable(Term)) { + SYMBOL TermTop; + + TermTop = term_TopSymbol(Term); + + if (cont_VarIsBound(TermContext, TermTop)) { + CONTEXT HelpContext; + + HelpContext = cont_ContextBindingContext(TermContext, TermTop); + Term = cont_ContextBindingTerm(TermContext, TermTop); + TermContext = HelpContext; + } else + break; + } + + if (term_IsComplex(Term)) { + LIST Scan, ArgumentList; + for (Scan = ArgumentList = list_Copy(term_ArgumentList(Term)); + !list_Empty(Scan); + Scan = list_Cdr(Scan)) + list_Rplaca(Scan, cont_CopyAndApplyBindings(TermContext, list_Car(Scan))); + return term_Create(term_TopSymbol(Term), ArgumentList); + } else + return term_Create(term_TopSymbol(Term), list_Nil()); +} + + +TERM cont_CopyAndApplyBindingsCom(const CONTEXT Context, TERM Term) +{ + while (term_IsVariable(Term) && cont_VarIsBound(Context, term_TopSymbol(Term))) + Term = cont_ContextBindingTerm(Context, term_TopSymbol(Term)); + + if (term_IsComplex(Term)) { + LIST Scan, ArgumentList; + for (Scan = ArgumentList = list_Copy(term_ArgumentList(Term)); + !list_Empty(Scan); + Scan = list_Cdr(Scan)) + list_Rplaca(Scan, cont_CopyAndApplyBindingsCom(Context, list_Car(Scan))); + return term_Create(term_TopSymbol(Term), ArgumentList); + } else + return term_Create(term_TopSymbol(Term), list_Nil()); +} + + +TERM cont_ApplyBindingsModuloMatching(const CONTEXT Context, TERM Term, + BOOL VarCheck) +/********************************************************** + INPUT: A context, a term, and a boolean flag. + RETURNS: <Term> is destructively changed with respect to + established bindings in the context. + If <VarCheck> is true, all variables in <Term> + must be bound in the context. When compiled with + "CHECK" on, this condition is in fact checked. + This function only makes sense after a matching operation. +***********************************************************/ +{ + TERM RplacTerm; + LIST Arglist; + SYMBOL Top; + +#ifdef CHECK + if (VarCheck && symbol_IsVariable(term_TopSymbol(Term)) && + !cont_VarIsBound(Context, term_TopSymbol(Term))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_ApplyBindingsModuloMatching:"); + misc_ErrorReport(" Used in forbidden context.\n"); + misc_FinishErrorReport(); + } +#endif + + Top = term_TopSymbol(Term); + + if (symbol_IsVariable(Top)) { + + if (cont_VarIsBound(Context, Top)) { + RplacTerm = cont_ContextBindingTerm(Context, Top); + Arglist = term_CopyTermList(term_ArgumentList(RplacTerm)); + term_RplacTop(Term, term_TopSymbol(RplacTerm)); + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term, Arglist); + } + } + else { + + for (Arglist = term_ArgumentList(Term); + !list_Empty(Arglist); + Arglist = list_Cdr(Arglist)) + cont_ApplyBindingsModuloMatching(Context, list_Car(Arglist), VarCheck); + } + + return Term; +} + + +static TERM cont_CopyAndApplyIndexVariableBindings(const CONTEXT Context, TERM Term) +{ + SYMBOL TermTop; + +#ifdef CHECK + if (symbol_IsIndexVariable(term_TopSymbol(Term)) && + !cont_VarIsBound(Context, term_TopSymbol(Term))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_CopyAndApplyIndexVariableBindings:"); + misc_ErrorReport(" Expected bound index variable."); + misc_FinishErrorReport(); + } +#endif + + TermTop = term_TopSymbol(Term); + + while (symbol_IsIndexVariable(TermTop)) { + if (cont_VarIsBound(Context, TermTop)) { + Term = cont_ContextBindingTerm(Context, TermTop); + TermTop = term_TopSymbol(Term); + } + } + + if (term_IsComplex(Term)) { + LIST Scan, ArgumentList; + for (Scan = ArgumentList = list_Copy(term_ArgumentList(Term)); + !list_Empty(Scan); + Scan = list_Cdr(Scan)) + list_Rplaca(Scan, cont_CopyAndApplyIndexVariableBindings(Context, list_Car(Scan))); + return term_Create(TermTop, ArgumentList); + } else + return term_Create(TermTop, list_Nil()); +} + + +TERM cont_ApplyBindingsModuloMatchingReverse(const CONTEXT Context, TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: <Term> is destructively changed with respect to + established bindings in the leftmost context. This + function only make sense after a matching operation (reverse). +***********************************************************/ +{ + TERM RplacTerm; + LIST Arglist; + SYMBOL Top; + +#ifdef CHECK + if (symbol_IsVariable(term_TopSymbol(Term)) && + !cont_VarIsBound(Context, term_TopSymbol(Term))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_ApplyBindingsModuloMatchingReverse:"); + misc_ErrorReport(" Used in forbidden context.\n"); + misc_FinishErrorReport(); + } +#endif + + Top = term_TopSymbol(Term); + + if (symbol_IsVariable(Top)) { + + if (cont_VarIsBound(Context, Top)) { + RplacTerm = + cont_CopyAndApplyIndexVariableBindings(Context, + cont_ContextBindingTerm(Context, Top)); + term_RplacTop(Term, term_TopSymbol(RplacTerm)); + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term, term_ArgumentList(RplacTerm)); + term_Free(RplacTerm); + } + } + else { + + for (Arglist = term_ArgumentList(Term); !list_Empty(Arglist); + Arglist = list_Cdr(Arglist)) + cont_ApplyBindingsModuloMatchingReverse(Context, list_Car(Arglist)); + } + + return Term; +} + + +BOOL cont_BindingsAreRenamingModuloMatching(const CONTEXT RenamingContext) +{ + CONTEXT Context; + +#ifdef CHECK + if (!cont_IsContextEmpty(RenamingContext)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_BindingsAreRenamingModuloMatching:"); + misc_ErrorReport(" Renaming context contains bindings.\n"); + misc_FinishErrorReport(); + } +#endif + + cont_StartBinding(); + + Context = cont_LastBinding(); + + while (Context) { + + if (!symbol_IsIndexVariable(cont_BindingSymbol(Context))) { + SYMBOL CodomainSymbol; + + CodomainSymbol = term_TopSymbol(cont_BindingTerm(Context)); + + if (symbol_IsVariable(CodomainSymbol)) { + if (cont_VarIsRenamed(RenamingContext, CodomainSymbol)) { + cont_BackTrack(); + return FALSE; + } else { + cont_CreateBinding(RenamingContext, CodomainSymbol, NULL, NULL); + cont_SetContextBindingRenaming(RenamingContext, CodomainSymbol, CodomainSymbol); + } + } else { + cont_BackTrack(); + return FALSE; + } + } + + Context = cont_BindingLink(Context); + } + + cont_BackTrack(); + return TRUE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * MISC FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +SYMBOL cont_TermMaxVar(CONTEXT Context, TERM Term) +/********************************************************* + INPUT: A context and a term. + RETURNS: The maximal variable in <Term> with respect to + the bindings in <Context> +********************************************************/ +{ + LIST scan; + SYMBOL result; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_TermMaxVar: Input term is corrupted.\n"); + misc_FinishErrorReport(); + } +#endif + + Term = cont_Deref(&Context,Term); + result = symbol_Null(); + + if (term_IsStandardVariable(Term)) { + if (term_TopSymbol(Term) > result) + result = term_TopSymbol(Term); + } else { + for (scan = term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) { + SYMBOL max = cont_TermMaxVar(Context, list_Car(scan)); + + if (max > result) + result = max; + } + } + + return result; +} + + +NAT cont_TermSize(CONTEXT Context, TERM Term) +/********************************************************* + INPUT: A context and a term. + RETURNS: The number of symbols in <Term> with respect to + the bindings in <Context> +********************************************************/ +{ + NAT result; + LIST scan; + + Term = cont_Deref(&Context, Term); + result = 1; + for (scan = term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) + result += cont_TermSize(Context, list_Car(scan)); + + return result; +} + + +BOOL cont_TermContainsSymbol(CONTEXT Context, TERM Term, SYMBOL Symbol) +/********************************************************* + INPUT: A context, a term and a symbol. + RETURNS: TRUE, if <Symbol> occurs in <Term> with respect to + the bindings in <Context>, FALSE otherwise. +********************************************************/ +{ + LIST scan; + + Term = cont_Deref(&Context, Term); + + if (symbol_Equal(term_TopSymbol(Term), Symbol)) + return TRUE; + else + for (scan = term_ArgumentList(Term); !list_Empty(scan); scan = list_Cdr(scan)) { + if (cont_TermContainsSymbol(Context, list_Car(scan), Symbol)) + return TRUE; + } + + return FALSE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * OUTPUT * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +void cont_TermPrintPrefix(CONTEXT Context, TERM Term) +/************************************************************** + INPUT: A context and a term. + RETURNS: none. + SUMMARY: Prints the term modulo the context to stdout. + CAUTION: none. +***************************************************************/ +{ + Term = cont_Deref(&Context, Term); + + symbol_Print(term_TopSymbol(Term)); + + if (term_IsComplex(Term)) { + LIST List; + + putchar('('); + + for (List = term_ArgumentList(Term); !list_Empty(List); + List = list_Cdr(List)) { + cont_TermPrintPrefix(Context, list_Car(List)); + + if (!list_Empty(list_Cdr(List))) + putchar(','); + } + + putchar(')'); + } +} diff --git a/test/spass/context.h b/test/spass/context.h new file mode 100644 index 0000000000000000000000000000000000000000..a3239ac825385ca9ad5241e620208585bf340d46 --- /dev/null +++ b/test/spass/context.h @@ -0,0 +1,1049 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CONTEXTS FOR VARIABLES * */ +/* * * */ +/* * $Module: CONTEXT * */ +/* * * */ +/* * Copyright (C) 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + + +#define SHOWBINDINGS 0 + +#ifndef _CONTEXT_ +#define _CONTEXT_ + + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "term.h" +#include "symbol.h" +#include "list.h" + +/**************************************************************/ +/* Structures */ +/**************************************************************/ + +/* Set 'SHOWBINDINGS' to non-zero value to enable debug output. */ +/* #define SHOWBINDINGS 1 */ + +#define cont__SIZE symbol__MAXVARIABLES + +extern int cont_NOOFCONTEXTS; +extern LIST cont_LISTOFCONTEXTS; +extern int cont_BINDINGS; + +/* An array to remember bindings for the variables. The array */ +/* is indexed by the variable index and holds the binding term. */ + +typedef struct binding { + SYMBOL symbol; + SYMBOL renaming; + TERM term; + struct binding *context; + struct binding *link; +} *CONTEXT, CONTEXT_NODE; + +extern CONTEXT cont_LASTBINDING; /* The last binding made. */ +extern CONTEXT cont_CURRENTBINDING; /* Help variable. */ + +extern SYMBOL cont_INDEXVARSCANNER; + +/* Two contexts are allocated by default */ + +extern CONTEXT cont_LEFTCONTEXT; +extern CONTEXT cont_RIGHTCONTEXT; +extern CONTEXT cont_INSTANCECONTEXT; /* This context is used as a label only (dummy context) */ + + +static __inline__ CONTEXT cont_LeftContext(void) +{ + return cont_LEFTCONTEXT; +} + +static __inline__ CONTEXT cont_RightContext(void) +{ + return cont_RIGHTCONTEXT; +} + +static __inline__ CONTEXT cont_InstanceContext(void) +{ + return cont_INSTANCECONTEXT; +} + +/**************************************************************/ +/* A stack for the number of established bindings */ +/**************************************************************/ + +#define cont__STACKSIZE 1000 + +typedef int cont_STACK_TYPE[cont__STACKSIZE]; + +extern cont_STACK_TYPE cont_STACK; +extern int cont_STACKPOINTER; + +/* Stack operations */ + +static __inline__ void cont_StackInit(void) +{ + cont_STACKPOINTER = 1; +} + +static __inline__ void cont_StackPush(int Entry) +{ +#ifdef CHECK + if (cont_STACKPOINTER >= cont__STACKSIZE) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_StackPush: Context stack overflow!\n"); + misc_FinishErrorReport(); + } +#endif + + cont_STACK[cont_STACKPOINTER++] = Entry; +} + +static __inline__ void cont_StackPop(void) +{ + --cont_STACKPOINTER; +} + +static __inline__ int cont_StackPopResult(void) +{ + return cont_STACK[--cont_STACKPOINTER]; +} + +static __inline__ void cont_StackNPop(int N) +{ + cont_STACKPOINTER -= N; +} + +static __inline__ int cont_StackTop(void) +{ + return cont_STACK[cont_STACKPOINTER - 1]; +} + +static __inline__ int cont_StackNthTop(int N) +{ + return cont_STACK[cont_STACKPOINTER - (1 + N)]; +} + +static __inline__ void cont_StackRplacTop(int Entry) +{ + cont_STACK[cont_STACKPOINTER - 1] = Entry; +} + +static __inline__ void cont_StackRplacNthTop(int N, int Entry) +{ + cont_STACK[cont_STACKPOINTER - (1 + N)] = Entry; +} + +static __inline__ void cont_StackRplacNth(int N, int Entry) +{ + cont_STACK[N] = Entry; +} + +static __inline__ int cont_StackBottom(void) +{ + return cont_STACKPOINTER; +} + +static __inline__ void cont_StackSetBottom(int Pointer) +{ + cont_STACKPOINTER = Pointer; +} + +static __inline__ BOOL cont_StackEmpty(int Pointer) +{ + return cont_STACKPOINTER == Pointer; +} + + +static __inline__ void cont_StartBinding(void) +{ + cont_StackPush(cont_BINDINGS); + + cont_BINDINGS = 0; +} + +static __inline__ int cont_BindingsSinceLastStart(void) +{ + return cont_BINDINGS; +} + +static __inline__ void cont_StopAndStartBinding(void) +{ + cont_StackRplacTop(cont_StackTop() + cont_BINDINGS); + + cont_BINDINGS = 0; +} + +/**************************************************************/ +/* Access */ +/**************************************************************/ + +static __inline__ CONTEXT cont_Binding(CONTEXT C, SYMBOL Var) +{ + return &(C)[Var]; +} + +static __inline__ CONTEXT cont_BindingLink(CONTEXT B) +{ + return B->link; +} + +static __inline__ void cont_SetBindingLink(CONTEXT B, CONTEXT L) +{ + B->link = L; +} + +static __inline__ TERM cont_BindingTerm(CONTEXT B) +{ + return B->term; +} + +static __inline__ void cont_SetBindingTerm(CONTEXT B, TERM T) +{ + B->term = T; +} + +static __inline__ SYMBOL cont_BindingSymbol(CONTEXT B) +{ + return B->symbol; +} + +static __inline__ void cont_SetBindingSymbol(CONTEXT B, SYMBOL S) +{ + B->symbol = S; +} + +static __inline__ SYMBOL cont_BindingRenaming(CONTEXT B) +{ + return B->renaming; +} + +static __inline__ void cont_SetBindingRenaming(CONTEXT B, SYMBOL S) +{ + B->renaming = S; +} + +static __inline__ CONTEXT cont_BindingContext(CONTEXT B) +{ + return B->context; +} + +static __inline__ void cont_SetBindingContext(CONTEXT B, CONTEXT C) +{ + B->context = C; +} + +static __inline__ CONTEXT cont_ContextBindingLink(CONTEXT C,SYMBOL Var) +{ + return C[Var].link; +} + +static __inline__ TERM cont_ContextBindingTerm(CONTEXT C,SYMBOL Var) +{ + return C[Var].term; +} + +static __inline__ void cont_SetContextBindingTerm(CONTEXT C, SYMBOL Var, TERM t) +{ + C[Var].term = t; +} + +static __inline__ SYMBOL cont_ContextBindingSymbol(CONTEXT C,SYMBOL Var) +{ + return C[Var].symbol; +} + +static __inline__ SYMBOL cont_ContextBindingRenaming(CONTEXT C,SYMBOL Var) +{ + return C[Var].renaming; +} + +static __inline__ void cont_SetContextBindingRenaming(CONTEXT C, SYMBOL Var, + SYMBOL R) +{ + C[Var].renaming = R; +} + +static __inline__ CONTEXT cont_ContextBindingContext(CONTEXT C,SYMBOL Var) +{ + return C[Var].context; +} + +/**************************************************************/ +/* Predicates */ +/**************************************************************/ + +static __inline__ BOOL cont_VarIsBound(CONTEXT C, SYMBOL Var) +{ + return cont_ContextBindingTerm(C,Var) != (TERM) NULL; +} + +static __inline__ BOOL cont_VarIsUsed(CONTEXT C, SYMBOL Var) +{ + return cont_ContextBindingContext(C,Var) != (CONTEXT) NULL; +} + +static __inline__ BOOL cont_VarIsLinked(CONTEXT C, SYMBOL Var) +{ + return cont_ContextBindingLink(C,Var) != (CONTEXT) NULL; +} + +static __inline__ BOOL cont_VarIsRenamed(CONTEXT C, SYMBOL Var) +{ + return cont_ContextBindingRenaming(C, Var) != symbol_Null(); +} + +static __inline__ BOOL cont_VarIsClosed(CONTEXT C,SYMBOL Var) +{ + return !cont_VarIsBound(C,Var) && cont_VarIsUsed(C,Var); +} + +static __inline__ BOOL cont_BindingIsBound(CONTEXT B) +{ + return cont_BindingTerm(B) != (TERM) NULL; +} + +static __inline__ BOOL cont_BindingIsUsed(CONTEXT B) +{ + return cont_BindingContext(B) != (CONTEXT) NULL; +} + +/**************************************************************/ +/* Aux functions for backtracking */ +/**************************************************************/ + +static __inline__ CONTEXT cont_LastBinding(void) +{ + return cont_LASTBINDING; +} + +static __inline__ void cont_SetLastBinding(CONTEXT B) +{ + cont_LASTBINDING = B; +} + +static __inline__ TERM cont_LastBindingTerm(void) +{ + return cont_BindingTerm(cont_LastBinding()); +} + +static __inline__ SYMBOL cont_LastBindingSymbol(void) +{ + return cont_BindingSymbol(cont_LastBinding()); +} + +static __inline__ CONTEXT cont_LastBindingContext(void) +{ + return cont_BindingContext(cont_LastBinding()); +} + +static __inline__ BOOL cont_LastIsBound(void) +{ + return cont_BindingIsBound(cont_LastBinding()); +} + +static __inline__ BOOL cont_LastIsUsed(void) +{ + return cont_LastBindingContext() != (CONTEXT) NULL; +} + +static __inline__ BOOL cont_LastIsClosed(void) +{ + return !cont_LastIsBound() && cont_LastIsUsed(); +} + +static __inline__ BOOL cont_IsInContext(CONTEXT C, SYMBOL Var, CONTEXT B) +{ + return cont_Binding(C, Var) == B; +} + +static __inline__ CONTEXT cont_ContextOfBinding(CONTEXT B) +{ + CONTEXT Result; + LIST Scan; + + for (Result = NULL, Scan = cont_LISTOFCONTEXTS; + list_Exist(Scan); + Scan = list_Cdr(Scan)) { + if (cont_IsInContext(list_Car(Scan), cont_BindingSymbol(B), B)) { + Result = list_Car(Scan); + break; + } + } + +#ifdef CHECK + if (Result == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_ContextOfBinding: Unknown context.\n"); + misc_FinishErrorReport(); + } +#endif + + return Result; +} + +/**************************************************************/ +/* Initialization */ +/**************************************************************/ + +static __inline__ void cont_InitBinding(CONTEXT C, SYMBOL Var) +{ + cont_CURRENTBINDING = cont_Binding(C, Var); + cont_SetBindingLink(cont_CURRENTBINDING, (CONTEXT)NULL); + cont_SetBindingTerm(cont_CURRENTBINDING, (TERM)NULL); + cont_SetBindingSymbol(cont_CURRENTBINDING, Var); + cont_SetBindingRenaming(cont_CURRENTBINDING, symbol_Null()); + cont_SetBindingContext(cont_CURRENTBINDING, (CONTEXT)NULL); +} + +static __inline__ void cont_InitContext(CONTEXT C) +{ + int i; + + for (i = 0; i < cont__SIZE; i++) + cont_InitBinding(C, i); +} + +/**************************************************************/ +/* Creation and deletion of contexts */ +/**************************************************************/ + +static __inline__ CONTEXT cont_Create(void) +{ + CONTEXT Result; + + Result = (CONTEXT)memory_Malloc(cont__SIZE*sizeof(CONTEXT_NODE)); + + cont_InitContext(Result); + + cont_LISTOFCONTEXTS = list_Cons(Result, cont_LISTOFCONTEXTS); + cont_NOOFCONTEXTS++; + + return Result; +} + +static __inline__ void cont_Delete(CONTEXT C) +{ +#ifdef CHECK + if ((cont_NOOFCONTEXTS == 0) || + !list_PointerMember(cont_LISTOFCONTEXTS, C)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_Delete: Context %ld not registered.\n", + (unsigned long)C); + misc_FinishErrorReport(); + } +#endif + + cont_LISTOFCONTEXTS = list_PointerDeleteOneElement(cont_LISTOFCONTEXTS, C); + + cont_NOOFCONTEXTS--; + + memory_Free(C, cont__SIZE*sizeof(CONTEXT_NODE)); +} + +static __inline__ void cont_ResetIndexVarScanner(void) +{ + cont_INDEXVARSCANNER = symbol_GetInitialIndexVarCounter(); +} + +/**************************************************************/ +/* Output bindings */ +/**************************************************************/ + +static __inline__ void cont_BindingOutput(CONTEXT C, SYMBOL Var) +{ + symbol_Print(cont_ContextBindingSymbol(C, Var)); + putchar(':'); + symbol_Print(Var); + + fputs(" -> ", stdout); + + if (cont_VarIsBound(C, Var)) { + term_PrintPrefix(cont_ContextBindingTerm(C, Var)); + } else + fputs("unbound", stdout); + + fputs(" in ", stdout); + + if (cont_VarIsUsed(C, Var)) { + printf("%ld", (unsigned long)cont_ContextBindingContext(C, Var)); + } else + fputs("NULL (unused)", stdout); + + fputs(". ", stdout); + + if (cont_VarIsClosed(C, Var)) { + fputs("(closed)", stdout); + } + + if (!cont_VarIsBound(C, Var) && + !cont_VarIsUsed(C, Var)) { + fputs(",(free)", stdout); + } + + if (cont_VarIsRenamed(C, Var)) { + fputs(",(renamed): ", stdout); + symbol_Print(Var); + fputs(" -> ", stdout); + symbol_Print(cont_ContextBindingRenaming(C, Var)); + } + + fflush(stdout); +} + +static __inline__ void cont_PrintCurrentTrail(void) +{ + fputs("\nPrint bindings:", stdout); + cont_CURRENTBINDING = cont_LastBinding(); + while (cont_CURRENTBINDING) { + cont_BindingOutput(cont_ContextOfBinding(cont_CURRENTBINDING), + cont_BindingSymbol(cont_CURRENTBINDING)); + cont_CURRENTBINDING = cont_BindingLink(cont_CURRENTBINDING); + if (cont_CURRENTBINDING) + putchar('\n'); + } + fflush(stdout); +} + +/**************************************************************/ +/* Close bindings */ +/**************************************************************/ + +static __inline__ void cont_CloseBindingHelp(CONTEXT C, SYMBOL Var) +{ + cont_SetContextBindingTerm(C, Var, NULL); +} + +static __inline__ void cont_CloseBindingBindingHelp(CONTEXT B) +{ + cont_SetBindingTerm(B, NULL); +} + +#if SHOWBINDINGS +static __inline__ void cont_CloseBinding(CONTEXT C, SYMBOL Var) +{ + fputs("\nClose binding from ", stdout); + cont_BindingOutput(C, Var); + cont_CloseBindingHelp(C, Var); +} +#else +static __inline__ void cont_CloseBinding(CONTEXT C, SYMBOL Var) +{ + cont_CloseBindingHelp(C, Var); +} +#endif + +static __inline__ void cont_CloseBindingBinding(CONTEXT B) { + cont_CloseBindingBindingHelp(B); +} + +/**************************************************************/ +/* Establish bindings */ +/**************************************************************/ + +static __inline__ void cont_CreateBindingHelp(CONTEXT C, SYMBOL Var, + CONTEXT CTerm, TERM Term) +{ +#ifdef CHECK + if (cont_VarIsBound(C, Var)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_CreateBindingHelp: Variable already bound.\n"); + misc_FinishErrorReport(); + } +#endif + + cont_CURRENTBINDING = cont_Binding(C,Var); + cont_SetBindingTerm(cont_CURRENTBINDING, Term); + cont_SetBindingContext(cont_CURRENTBINDING, CTerm); + cont_SetBindingLink(cont_CURRENTBINDING, cont_LastBinding()); + cont_SetLastBinding(cont_CURRENTBINDING); +} + +#if SHOWBINDINGS + +static __inline__ int cont_CreateBinding(CONTEXT C, SYMBOL Var, CONTEXT CTerm, TERM Term) +{ + cont_CreateBindingHelp(C,Var,CTerm,Term); + fputs("\nEstablish binding from ", stdout); + cont_BindingOutput(C, Var); + return ++cont_BINDINGS; +} + +static __inline__ int cont_CreateClosedBinding(CONTEXT C, SYMBOL Var) +{ + cont_CreateBindingHelp(C, Var, C, NULL); + fputs("\nEstablish closed binding from ", stdout); + cont_BindingOutput(C,Var); + return ++cont_BINDINGS; +} + +#else + +static __inline__ int cont_CreateBinding(CONTEXT C, SYMBOL Var, CONTEXT CTerm, TERM Term) +{ + cont_CreateBindingHelp(C,Var,CTerm,Term); + return ++cont_BINDINGS; +} + +static __inline__ int cont_CreateClosedBinding(CONTEXT C, SYMBOL Var) +{ + cont_CreateBindingHelp(C, Var, C, NULL); + return ++cont_BINDINGS; +} + +#endif + +/**************************************************************/ +/* Backtracking */ +/**************************************************************/ + +static __inline__ void cont_BackTrackLastBindingHelp(void) +{ + cont_CURRENTBINDING = cont_LastBinding(); + cont_SetLastBinding(cont_BindingLink(cont_CURRENTBINDING)); + cont_SetBindingTerm(cont_CURRENTBINDING, NULL); + cont_SetBindingContext(cont_CURRENTBINDING, NULL); + cont_SetBindingRenaming(cont_CURRENTBINDING, symbol_Null()); + cont_SetBindingLink(cont_CURRENTBINDING, NULL); + + cont_BINDINGS--; +} + +#if SHOWBINDINGS + +static __inline__ void cont_BackTrackLastBinding(void) +{ + CONTEXT LastContext; + SYMBOL LastSymbol; + + LastContext = cont_ContextOfBinding(cont_LastBinding()); + LastSymbol = cont_LastBindingSymbol(); + fputs("\nBacktrack binding from ", stdout); + cont_BindingOutput(LastContext, LastSymbol); + cont_BackTrackLastBindingHelp(); +} + +static __inline__ int cont_BackTrack(void) +{ + printf("\nBacktrack %d bindings:", cont_BINDINGS); + + while (cont_BINDINGS > 0) + cont_BackTrackLastBinding(); + + if (!cont_StackEmpty(0)) + cont_BINDINGS = cont_StackPopResult(); + + fflush(stdout); + return 0; +} + +static __inline__ int cont_StopAndBackTrack(void) +{ +#ifdef CHECK + if (cont_BINDINGS > 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_StopAndBackTrack: Bindings not reset!\n"); + misc_FinishErrorReport(); + } else if (cont_StackEmpty(0)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_StopAndBackTrack: No bindings on stack!\n"); + misc_FinishErrorReport(); + } +#endif + cont_BINDINGS = cont_StackPopResult(); + + printf("\nStop and Backtrack %d bindings:", cont_BINDINGS); + + while (cont_BINDINGS > 0) + cont_BackTrackLastBinding(); + + fflush(stdout); + return 0; +} + +static __inline__ int cont_BackTrackAndStart(void) +{ + printf("\nBacktrack %d bindings:", cont_BINDINGS); + + while (cont_BINDINGS > 0) + cont_BackTrackLastBinding(); + + fflush(stdout); + return 0; +} + +static __inline__ void cont_Reset(void) +{ + fputs("\nReset bindings:", stdout); + while (cont_LastBinding()) + cont_BackTrackLastBinding(); + + cont_BINDINGS = 0; + cont_StackInit(); + cont_ResetIndexVarScanner(); + fflush(stdout); +} + +#else + +static __inline__ void cont_BackTrackLastBinding(void) +{ + cont_BackTrackLastBindingHelp(); +} + +static __inline__ int cont_BackTrack(void) +{ + while (cont_BINDINGS > 0) + cont_BackTrackLastBinding(); + + if (!cont_StackEmpty(0)) + cont_BINDINGS = cont_StackPopResult(); + + return 0; +} + +static __inline__ int cont_StopAndBackTrack(void) +{ +#ifdef CHECK + if (cont_BINDINGS > 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_StopAndBackTrack: Bindings not reset!\n"); + misc_FinishErrorReport(); + } else if (cont_StackEmpty(0)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_StopAndBackTrack: No bindings on stack!\n"); + misc_FinishErrorReport(); + } +#endif + cont_BINDINGS = cont_StackPopResult(); + + while (cont_BINDINGS > 0) + cont_BackTrackLastBinding(); + + return 0; +} + +static __inline__ int cont_BackTrackAndStart(void) +{ + while (cont_BINDINGS > 0) + cont_BackTrackLastBinding(); + + return 0; +} + +static __inline__ void cont_Reset(void) +{ + while (cont_LastBinding()) + cont_BackTrackLastBinding(); + + cont_BINDINGS = 0; + cont_StackInit(); + cont_ResetIndexVarScanner(); +} + +#endif + +/**************************************************************/ +/* Check state of bindings */ +/**************************************************************/ + +#define cont__CHECKSTACKSIZE 1000 +#define cont__CHECKSTACKEMPTY 0 + +typedef POINTER cont_CHECKSTACK_TYPE[cont__CHECKSTACKSIZE]; + +extern cont_CHECKSTACK_TYPE cont_CHECKSTACK; +extern int cont_CHECKSTACKPOINTER; + +/* Stack operations */ + +static __inline__ void cont_CheckStackInit(void) +{ + cont_CHECKSTACKPOINTER = cont__CHECKSTACKEMPTY; +} + +static __inline__ void cont_CheckStackPush(POINTER Entry) +{ +#ifdef CHECK + if (cont_CHECKSTACKPOINTER >= cont__STACKSIZE) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_CheckStackPush: Context check stack overflow!\n"); + misc_FinishErrorReport(); + } +#endif + + cont_CHECKSTACK[cont_CHECKSTACKPOINTER++] = Entry; +} + +static __inline__ void cont_CheckStackPop(void) +{ + --cont_CHECKSTACKPOINTER; +} + +static __inline__ POINTER cont_CheckStackPopResult(void) +{ + return cont_CHECKSTACK[--cont_CHECKSTACKPOINTER]; +} + +static __inline__ void cont_CheckStackNPop(int N) +{ + cont_CHECKSTACKPOINTER -= N; +} + +static __inline__ POINTER cont_CheckStackTop(void) +{ + return cont_CHECKSTACK[cont_CHECKSTACKPOINTER - 1]; +} + +static __inline__ POINTER cont_CheckStackNthTop(int N) +{ + return cont_CHECKSTACK[cont_CHECKSTACKPOINTER - (1 + N)]; +} + +static __inline__ void cont_CheckStackRplacTop(POINTER Entry) +{ + cont_CHECKSTACK[cont_CHECKSTACKPOINTER - 1] = Entry; +} + +static __inline__ void cont_CheckStackRplacNthTop(int N, POINTER Entry) +{ + cont_CHECKSTACK[cont_CHECKSTACKPOINTER - (1 + N)] = Entry; +} + +static __inline__ void cont_CheckStackRplacNth(int N, POINTER Entry) +{ + cont_CHECKSTACK[N] = Entry; +} + +static __inline__ int cont_CheckStackBottom(void) +{ + return cont_CHECKSTACKPOINTER; +} + +static __inline__ void cont_CheckStackSetBottom(int Pointer) +{ + cont_CHECKSTACKPOINTER = Pointer; +} + +static __inline__ BOOL cont_CheckStackEmpty(int Pointer) +{ + return cont_CHECKSTACKPOINTER == Pointer; +} + +extern CONTEXT cont_STATELASTBINDING; /* Storage to save state of trails. */ +extern int cont_STATEBINDINGS; /* Storage to save number of current bindings. */ +extern int cont_STATESTACK; /* Storage to save state of stack. */ +extern int cont_STATETOPSTACK; /* Storage to save state of the top element of the stack. */ + +static __inline__ BOOL cont_CheckLastBinding(CONTEXT Check, int Bindings) +{ + CONTEXT Scan; + BOOL Result; + + Scan = cont_LastBinding(); + + while (Bindings > 0) { + Scan = cont_BindingLink(Scan); + Bindings--; + } + if (Check == Scan) + Result = TRUE; + else + Result = FALSE; + + return Result; +} + +static __inline__ void cont_CheckState(void) +{ + if (cont_CheckStackEmpty(cont__CHECKSTACKEMPTY)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_CheckState: No states saved.\n"); + misc_FinishErrorReport(); + } + + cont_STATETOPSTACK = (int)cont_CheckStackPopResult(); + cont_STATESTACK = (int)cont_CheckStackPopResult(); + cont_STATEBINDINGS = (int)cont_CheckStackPopResult(); + cont_STATELASTBINDING = (CONTEXT)cont_CheckStackPopResult(); + + if ((cont_STATELASTBINDING != cont_LastBinding()) || + (cont_STATEBINDINGS != cont_BINDINGS) || + (!cont_StackEmpty(cont_STATESTACK)) || + (cont_STATETOPSTACK != cont_StackTop())) { + misc_StartErrorReport(); + misc_ErrorReport("\n In cont_CheckState: State of contexts does not match saved state."); + misc_ErrorReport("\nTrail: Saved state: %ld; current state: %ld.", + (long)cont_STATELASTBINDING, (long)cont_LastBinding()); + misc_ErrorReport("\nNumber of bindings: Saved state: %d; current state: %d.", + cont_STATEBINDINGS, cont_BINDINGS); + misc_ErrorReport("\nBinding stack pointer: Saved state: %d; current state: %d.", + cont_STATESTACK, cont_StackBottom()); + misc_ErrorReport("\nNumber of bindings on top of stack: Saved state: %d; current state: %d.\n\n", + cont_STATETOPSTACK, cont_StackTop()); + misc_FinishErrorReport(); + } +} + +static __inline__ void cont_SaveState(void) +{ + cont_CheckStackPush((POINTER)cont_LastBinding()); + cont_CheckStackPush((POINTER)cont_BINDINGS); + cont_CheckStackPush((POINTER)cont_StackBottom()); + cont_CheckStackPush((POINTER)cont_StackTop()); +} + +static __inline__ BOOL cont_IsContextEmpty(const CONTEXT Check) +{ + int i; + + for (i = 0; i < cont__SIZE; i++) + if (cont_VarIsBound(Check, i) || + cont_VarIsUsed(Check, i) || + cont_VarIsLinked(Check, i) || + cont_VarIsRenamed(Check, i)) + return FALSE; + + return TRUE; +} + +/**************************************************************/ +/* Generation of index variables */ +/**************************************************************/ + +static __inline__ SYMBOL cont_NextIndexVariable(const CONTEXT IndexContext) +{ + if (symbol_Equal(cont_INDEXVARSCANNER, symbol_LastIndexVariable())) + cont_INDEXVARSCANNER = symbol_CreateIndexVariable(); + else + for (;;) { + cont_INDEXVARSCANNER = symbol_NextIndexVariable(cont_INDEXVARSCANNER); + if (!cont_VarIsUsed(IndexContext, cont_INDEXVARSCANNER)) + break; + else + if (symbol_Equal(cont_INDEXVARSCANNER, symbol_LastIndexVariable())) { + cont_INDEXVARSCANNER = symbol_CreateIndexVariable(); + break; + } + } + return cont_INDEXVARSCANNER; +} + +/**************************************************************/ +/* Dereferencing of terms wrt. contexts */ +/**************************************************************/ + +static __inline__ TERM cont_Deref(CONTEXT* Context, TERM Term) +/************************************************************** + INPUT: A call-by-ref context and a term. + RETURNS: The dereferenced term and the corresponding context. + SUMMARY: Dereferences bindings of variables. + CAUTION: In general, the context of the returned term + is different to the input context. +***************************************************************/ +{ + + while (term_IsVariable(Term) && *Context != cont_InstanceContext()) { + SYMBOL TermTop; + + TermTop = term_TopSymbol(Term); + + if (cont_VarIsBound(*Context, TermTop)) { + CONTEXT HelpContext; + + HelpContext = cont_ContextBindingContext(*Context, TermTop); + Term = cont_ContextBindingTerm(*Context, TermTop); + *Context = HelpContext; + } + else + return Term; + } + + return Term; +} + +/**************************************************************/ +/* Functions for Initialization and Controlling */ +/**************************************************************/ + +void cont_Init(void); +void cont_Check(void); +void cont_Free(void); + +/**************************************************************/ +/* Functions for Term Equality Test with respect to Bindings */ +/**************************************************************/ + +BOOL cont_TermEqual(CONTEXT, TERM, CONTEXT, TERM); +BOOL cont_TermEqualModuloBindings(CONTEXT, CONTEXT, TERM, CONTEXT, TERM); + +/**************************************************************/ +/* Functions for Applying Bindings */ +/**************************************************************/ + +TERM cont_CopyAndApplyBindings(CONTEXT, TERM); +TERM cont_CopyAndApplyBindingsCom(const CONTEXT, TERM); + +TERM cont_ApplyBindingsModuloMatching(const CONTEXT, TERM, BOOL); +TERM cont_ApplyBindingsModuloMatchingReverse(const CONTEXT, TERM); + +BOOL cont_BindingsAreRenamingModuloMatching(const CONTEXT); + +/**************************************************************/ +/* Misc Functions */ +/**************************************************************/ + +SYMBOL cont_TermMaxVar(CONTEXT, TERM); +NAT cont_TermSize(CONTEXT, TERM); +BOOL cont_TermContainsSymbol(CONTEXT, TERM, SYMBOL); + +/**************************************************************/ +/* Functions for Output */ +/**************************************************************/ + +void cont_TermPrintPrefix(CONTEXT, TERM); + +#endif diff --git a/test/spass/defs.c b/test/spass/defs.c new file mode 100644 index 0000000000000000000000000000000000000000..0b6268b9398a8519ad6e9e4d9bd1c9955efe7871 --- /dev/null +++ b/test/spass/defs.c @@ -0,0 +1,1359 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * DEFINITIONS * */ +/* * * */ +/* * $Module: DEFS * */ +/* * * */ +/* * Copyright (C) 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "cnf.h" +#include "defs.h" +#include "foldfg.h" + +static void def_DeleteFromClauses(DEF); +static void def_DeleteFromTerm(DEF); + +DEF def_CreateFromClauses(TERM ExpTerm, TERM PredTerm, LIST Clauses, LIST Lits, + BOOL Con) +/********************************************************** + INPUT: Two terms, a list of clausenumbers, a list of literal indices and + a boolean saying whether all clauses derived by expanding the + predicate should be conclauses. + RETURNS: A definition consisting of the 2 terms as expansion term and + predicate term and the list of parent clause numbers and a list + of the indices of the defined predicate in the parent clauses. + ToProve and label are set to NULL. +********************************************************/ +{ + DEF result; + +#ifdef CHECK + if (!term_IsTerm(ExpTerm) || !term_IsTerm(PredTerm)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_CreateFromClause: Illegal input."); + misc_FinishErrorReport(); + } + if (list_Empty(Clauses)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_CreateFromClause: No parent clause given."); + misc_FinishErrorReport(); + } +#endif + + result = (DEF) memory_Malloc(sizeof(DEF_NODE)); + result->expansion = ExpTerm; + result->predicate = PredTerm; + result->toprove = (TERM) NULL; + result->parentclauses = list_PairCreate(Clauses, Lits); + result->label = (const char*) NULL; + result->conjecture = Con; + + return result; +} + +DEF def_CreateFromTerm(TERM ExpTerm, TERM PredTerm, TERM ToProve, const char* Label) +/********************************************************** + INPUT: 3 terms and a term label. + RETURNS: A definition consisting of the 3 terms as expansion term, + predicate term and term to prove before applying the + definition and the label of the parent term. + The list of clausenumbers is set to NULL. +********************************************************/ +{ + DEF result; + +#ifdef CHECK + if (!term_IsTerm(ExpTerm) || !term_IsTerm(PredTerm)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_CreateFromTerm: Illegal input."); + misc_FinishErrorReport(); + } + if (Label == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_CreateFromTerm: No parent clause given."); + misc_FinishErrorReport(); + } +#endif + + result = (DEF) memory_Malloc(sizeof(DEF_NODE)); + result->expansion = ExpTerm; + result->predicate = PredTerm; + result->toprove = ToProve; + result->parentclauses = list_PairCreate(list_Nil(), list_Nil()); + result->label = Label; + result->conjecture = FALSE; + + return result; +} + +static void def_DeleteFromClauses(DEF D) +/********************************************************** + INPUT: A definition derived from clauses. + EFFECT: The definition is deleted, INCLUDING THE TERMS AND + THE LIST OF CLAUSE NUMBERS. +********************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(def_Expansion(D)) || !term_IsTerm(def_Predicate(D))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_DeleteFormClauses: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + /* ToProve and Label are NULL */ + term_Delete(def_Expansion(D)); + term_Delete(def_Predicate(D)); + list_Delete(def_ClauseNumberList(D)); + list_Delete(def_ClauseLitsList(D)); + list_PairFree(D->parentclauses); + + memory_Free(D, sizeof(DEF_NODE)); +} + +static void def_DeleteFromTerm(DEF D) +/********************************************************** + INPUT: A definition derived from a term. + EFFECT: The definition is deleted, INCLUDING THE TERMS. + THE LABEL IS NOT FREED. +********************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(def_Expansion(D)) || !term_IsTerm(def_Predicate(D))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_DeleteFromTerm: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + /* List of clausenumbers is NULL */ + term_Delete(def_Expansion(D)); + term_Delete(def_Predicate(D)); + if (def_ToProve(D) != (TERM) NULL) + term_Delete(def_ToProve(D)); + list_PairFree(D->parentclauses); + memory_Free(D, sizeof(DEF_NODE)); +} + +void def_Delete(DEF D) +/********************************************************** + INPUT: A definition derived from a term. + EFFECT: The definition is deleted. + CAUTION: All elements of the definition except of the label are freed. +********************************************************/ +{ + if (!list_Empty(def_ClauseNumberList(D))) + def_DeleteFromClauses(D); + else + def_DeleteFromTerm(D); +} + +int def_PredicateOccurrences(TERM Term, SYMBOL P) +/**************************************************** + INPUT: A term and a predicate symbol. + RETURNS: The number of occurrences of the predicate symbol in Term +**************************************************/ +{ + /* Quantifiers */ + if (fol_IsQuantifier(term_TopSymbol(Term))) + return def_PredicateOccurrences(term_SecondArgument(Term), P); + + /* Junctors and NOT */ + if (fol_IsJunctor(term_TopSymbol(Term)) || + symbol_Equal(term_TopSymbol(Term),fol_Not())){ + LIST scan; + int count; + count = 0; + for (scan=term_ArgumentList(Term); !list_Empty(scan); scan=list_Cdr(scan)) { + count += def_PredicateOccurrences((TERM) list_Car(scan), P); + /* Only the cases count==1 and count>1 are important */ + if (count > 1) + return count; + } + return count; + } + + if (symbol_Equal(term_TopSymbol(Term), P)) + return 1; + return 0; +} + +LIST def_ExtractDefsFromTerm(TERM Term, const char* Label) +/************************************************************** + INPUT: A term and its label. + RETURNS: A list of definitions found in the term. + NOTE: The Term is not changed, the definitions contain copies. +***************************************************************/ +{ + TERM andterm; + BOOL found; + int pol; + LIST univars, termlist, defslist, scan; + + /* First check if there is a top level and() so that the Term may + contain several definitions */ + + andterm = Term; + found = FALSE; + pol = 1; + univars = list_Nil(); + + /* Traverse top down universal quantifiers */ + while (!found) { + if ((symbol_Equal(term_TopSymbol(andterm), fol_All()) && (pol == 1)) + || (symbol_Equal(term_TopSymbol(andterm), fol_Exist()) && (pol == -1))) { + univars = list_Nconc(univars, list_Copy(fol_QuantifierVariables(andterm))); + andterm = term_SecondArgument(andterm); + } + else { + if (symbol_Equal(term_TopSymbol(andterm), fol_Not())) { + pol = -pol; + andterm = term_FirstArgument(andterm); + } + else + found = TRUE; + } + } + + termlist = list_Nil(); + /* Check if conjunction was found */ + if ((symbol_Equal(term_TopSymbol(andterm), fol_And()) && (pol == 1)) + || (symbol_Equal(term_TopSymbol(andterm), fol_Or()) && (pol == -1))) { + LIST l; + /* Flatten nested and/or */ + /* Make copy of relevant subterm */ + andterm = cnf_Flatten(term_Copy(andterm), term_TopSymbol(andterm)); + for (l=term_ArgumentList(andterm); !list_Empty(l); l=list_Cdr(l)) { + TERM newterm; + newterm = fol_CreateQuantifierAddFather(fol_All(), term_CopyTermList(univars), + list_List(list_Car(l))); + termlist = list_Cons(newterm, termlist); + } + /* Arguments are used in new terms */ + list_Delete(term_ArgumentList(andterm)); + term_Free(andterm); + } + else + termlist = list_List(term_Copy(Term)); + + list_Delete(univars); + + /* Now we have a list of terms that may contain definitions */ + defslist = list_Nil(); + for (scan=termlist; !list_Empty(scan); scan=list_Cdr(scan)) { + TERM cand; + TERM foundpred, toprove; + + /* Candidate from list */ + cand = (TERM) list_Car(scan); + term_AddFatherLinks(cand); + + if (cnf_ContainsDefinition(cand, &foundpred)) { + DEF def; +#ifdef CHECK + if (!fol_CheckFormula(cand)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_ExtractDefsFromTerm: Illegal term cand"); + misc_FinishErrorReport(); + } +#endif + cand = cnf_DefConvert(cand, foundpred, &toprove); +#ifdef CHECK + if (!fol_CheckFormula(cand)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_ExtractDefsFromTerm: Illegal term cand"); + misc_FinishErrorReport(); + } +#endif + def = def_CreateFromTerm(term_Copy(term_SecondArgument(term_Superterm(foundpred))), + term_Copy(foundpred), toprove, Label); + + if (def_PredicateOccurrences(cand, term_TopSymbol(foundpred)) > 1) + def_RemoveAttribute(def, PREDOCCURONCE); + else + def_AddAttribute(def, PREDOCCURONCE); + if (symbol_Equal(term_TopSymbol(foundpred), fol_Equality())) + def_AddAttribute(def, ISEQUALITY); + else + def_RemoveAttribute(def, ISEQUALITY); + + defslist = list_Cons(def, defslist); + } + term_Delete(cand); + } + + list_Delete(termlist); + return defslist; +} + +void def_ExtractDefsFromClauselist(PROOFSEARCH Search, LIST Clauselist) +/************************************************************** + INPUT: A proofsearch object and a list of clauses + RETURNS: Nothing. + EFFECT: The definitions found in the clauselist object are stored in + the proofsearch object. + NOTE: The clause list is not changed. + The old list of definitions in the proofsearch object is + overwritten. +***************************************************************/ +{ + LIST scan, defslist; + FLAGSTORE FlagStore; + PRECEDENCE Precedence; + + defslist = list_Nil(); + FlagStore = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + for (scan=Clauselist; !list_Empty(scan); scan=list_Cdr(scan)) { + CLAUSE Clause; + NAT index; + LIST pair; + + Clause = (CLAUSE) list_Car(scan); + /* Check if clause contains a predicate that may be part of a definition */ + if (clause_ContainsPotPredDef(Clause, FlagStore, Precedence, &index, &pair)) { + LIST l, compl, compllits; + BOOL done; + + compl = compllits = list_Nil(); + done = FALSE; + + /* Search for complement clauses */ + for (l=Clauselist; !list_Empty(l) && !done; l=list_Cdr(l)) { + int predindex; + if (clause_IsPartOfDefinition((CLAUSE) list_Car(l), + clause_GetLiteralTerm(Clause, index), + &predindex, pair)) { + compl = list_Cons(list_Car(l), compl); + compllits = list_Cons((POINTER) predindex, compllits); + + if (list_Empty(list_PairFirst(pair)) && + list_Empty(list_PairSecond(pair))) + done = TRUE; + } + } + + /* All complements found ? */ + if (done) { + LIST l2, clausenumbers, args; + DEF def; + NAT i; + TERM defterm, predterm; + BOOL con; + + clausenumbers = list_Nil(); + con = clause_GetFlag(Clause, CONCLAUSE); + + for (l2=compl; !list_Empty(l2); l2=list_Cdr(l2)) { + clausenumbers = list_Cons((POINTER) clause_Number((CLAUSE) list_Car(l2)), + clausenumbers); + if (clause_GetFlag((CLAUSE) list_Car(l2), CONCLAUSE)) + con = TRUE; + } + clausenumbers = list_Cons((POINTER) clause_Number(Clause), + clausenumbers); + compllits = list_Cons((POINTER) index, compllits); + + /* Build definition term */ + predterm = term_Copy(clause_GetLiteralTerm(Clause, index)); + args = list_Nil(); + for (i = 0; i < clause_Length(Clause); i++) + if (i != index) + args = list_Cons(term_Copy(clause_GetLiteralTerm(Clause, i)), args); + defterm = term_CreateAddFather(fol_Or(), args); + /* The expansion is negative here, so it must be inverted */ + defterm = term_Create(fol_Not(), list_List(defterm)); + defterm = cnf_NegationNormalFormula(defterm); + def = def_CreateFromClauses(defterm, predterm, clausenumbers, compllits, con); + defslist = list_Cons(def, defslist); + if (flag_GetFlagValue(FlagStore, flag_PAPPLYDEFS)) { + fputs("\nNew definition found :", stdout); + def_Print(def); + } + } + else { + list_Delete(compllits); + list_Delete(list_PairSecond(pair)); + list_Delete(list_PairFirst(pair)); + } + list_Delete(compl); + list_PairFree(pair); + } + } + + if (flag_GetFlagValue(FlagStore, flag_PAPPLYDEFS)) { + if (!list_Empty(defslist)) { + fputs("\nFound definitions :\n", stdout); + for (scan = defslist; !list_Empty(scan); scan = list_Cdr(scan)) { + def_Print((DEF) list_Car(scan)); + fputs("\n---\n", stdout); + } + } + } + + for (scan=defslist; !list_Empty(scan); scan=list_Cdr(scan)) + symbol_AddProperty(term_TopSymbol(def_Predicate((DEF) list_Car(scan))), ISDEF); + + prfs_SetDefinitions(Search, list_Nconc(prfs_Definitions(Search), defslist)); +} + +TERM def_ApplyDefToTermOnce(DEF Def, TERM Term, FLAGSTORE FlagStore, + PRECEDENCE Precedence, BOOL* Complete) +/************************************************************** + INPUT: A DEF structure, a term and a boolean that is set + to TRUE if no occurrences of the defined predicate + remain in the term. A flag store and a precedence. + RETURNS: A term where all occurrences of the definitions + predicate are expanded if possible. + NOTE: The Term is not changed. +***************************************************************/ +{ + TERM newtarget, oldtarget, targetpredicate, totoplevel, toprove; + LIST targettermvars, varsfortoplevel; + BOOL applicable; + + oldtarget = Term; + *Complete = TRUE; + + while (TRUE) { + newtarget = term_Copy(oldtarget); + term_AddFatherLinks(newtarget); + targettermvars = varsfortoplevel = list_Nil(); + + if (cnf_ContainsPredicate(newtarget, term_TopSymbol(def_Predicate(Def)), + &targetpredicate, &totoplevel, &targettermvars, + &varsfortoplevel)) { + *Complete = FALSE; + applicable = FALSE; + /* Check if definition is not always applicable */ + if (term_Equal(def_ToProve(Def), term_Null())) { + applicable = TRUE; + newtarget = cnf_ApplyDefinitionOnce(def_Predicate(Def), term_Copy(def_Expansion(Def)), + newtarget, targetpredicate, FlagStore); + if (oldtarget != Term) + term_Delete(oldtarget); + oldtarget = newtarget; + list_Delete(targettermvars); + list_Delete(varsfortoplevel); + } + else { + toprove = term_Copy(def_ToProve(Def)); + newtarget = cnf_DefTargetConvert(newtarget, totoplevel, toprove, + term_ArgumentList(def_Predicate(Def)), + term_ArgumentList(targetpredicate), + targettermvars, varsfortoplevel, + FlagStore, Precedence, + &applicable); + list_Delete(targettermvars); + list_Delete(varsfortoplevel); + if (applicable) { + newtarget = cnf_ApplyDefinitionOnce(def_Predicate(Def), term_Copy(def_Expansion(Def)), + newtarget, targetpredicate, FlagStore); + if (oldtarget != Term) + term_Delete(oldtarget); + oldtarget = newtarget; + } + else { + /* Predicate still exists but cannot be expanded */ + term_Delete(newtarget); + if (oldtarget == Term) + return NULL; + else { + oldtarget = cnf_ObviousSimplifications(oldtarget); + return oldtarget; + } + } + } + } + else { + *Complete = TRUE; + /* Predicate does no longer exist */ + term_Delete(newtarget); + /* No expansion possible */ + if (oldtarget == Term) + return NULL; + else { + oldtarget = cnf_ObviousSimplifications(oldtarget); + return oldtarget; + } + } + } + return NULL; /* Unreachable */ +} + +TERM def_ApplyDefToTermExhaustive(PROOFSEARCH Search, TERM Term) +/************************************************************** + INPUT: A proofsearch object and a term. + RETURNS: An expanded term. + NOTE: All occurences of defined predicates are expanded in the term, + until no further changes are possible. + CAUTION: If cyclic definitions exist, this will crash. +***************************************************************/ +{ + TERM oldterm, newterm; + BOOL done, complete; + FLAGSTORE FlagStore; + PRECEDENCE Precedence; + + done = FALSE; + oldterm = Term; + FlagStore = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + while (!done) { + LIST l; + done = TRUE; + /* Apply all definitions to term until no more changes occur */ + for (l=prfs_Definitions(Search); !list_Empty(l); l=list_Cdr(l)) { + newterm = def_ApplyDefToTermOnce((DEF) list_Car(l), oldterm, + FlagStore, Precedence, &complete); + if (newterm != NULL) { + if (oldterm != Term) + term_Delete(oldterm); + oldterm = newterm; + done = FALSE; + } + } + } + if (oldterm == Term) + return NULL; + else + return oldterm; +} + +LIST def_ApplyDefToClauseOnce(DEF Def, CLAUSE Clause, + FLAGSTORE FlagStore, PRECEDENCE Precedence) +/************************************************************** + INPUT: A DEF structure, a clause, a flag store and a + precedence. + RETURNS: A list of new clauses. + NOTE: The clause is not changed. + All occurences of the defined predicate are expanded + in the clause and in the derived clauses. +***************************************************************/ +{ + LIST result, l; + + result = list_List(Clause); + + for (l = result; !list_Empty(l); l = list_Cdr(l)) { + if (clause_ContainsSymbol((CLAUSE) list_Car(l), + term_TopSymbol(def_Predicate(Def)))) { + result = list_Nconc(result, + cnf_ApplyDefinitionToClause((CLAUSE) list_Car(l), + def_Predicate(Def), + def_Expansion(Def), + FlagStore, Precedence)); + /* Remove temporary clause */ + if ((CLAUSE) list_Car(l) != Clause) + clause_Delete((CLAUSE) list_Car(l)); + list_Rplaca(l, NULL); + } + } + result = list_PointerDeleteElement(result, NULL); + + /* Make sure the original clause is no longer in the list */ + if (!list_Empty(result)) + if (list_First(result) == Clause) + result = list_Pop(result); + + for (l = result; !list_Empty(l); l=list_Cdr(l)) { + CLAUSE c; + c = (CLAUSE) list_Car(l); + if (def_Conjecture(Def)) + clause_SetFlag((CLAUSE) list_Car(l), CONCLAUSE); + clause_SetFromDefApplication(c); + clause_SetParentClauses(c, list_Cons((POINTER) clause_Number(Clause), + list_Copy(def_ClauseNumberList(Def)))); + /* Parent literal is not available, as the predicate may occur several + times in the target clause */ + clause_SetParentLiterals(c, list_Cons((POINTER) 0, + list_Copy(def_ClauseLitsList(Def)))); + } + return result; +} + +LIST def_ApplyDefToClauseExhaustive(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proofsearch object and a clause. + RETURNS: A list of derived clauses. + NOTE: All occurences of defined predicates are expanded in the clause. + until no further changes are possible. + CAUTION: If cyclic definitions exist, this will crash. +***************************************************************/ +{ + LIST newclauses, scan, result; + CLAUSE orig; + FLAGSTORE FlagStore; + PRECEDENCE Precedence; + + orig = clause_Copy(Clause); + newclauses = list_List(orig); + result = list_Nil(); + FlagStore = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + while (!list_Empty(newclauses)) { + /* Check all clauses */ + LIST l, nextlist; + + /* List of clauses derived from newclauses by expanding predicates */ + nextlist = list_Nil(); + + for (l=newclauses; !list_Empty(l); l=list_Cdr(l)) { + LIST clauses; + CLAUSE c; + + c = (CLAUSE) list_Car(l); + + /* Apply all definitions to the clause */ + + /* List of clauses derived from one clause in newclauses by */ + /* expanding all possible predicates */ + clauses = list_Nil(); + + for (scan=prfs_Definitions(Search); !list_Empty(scan); scan=list_Cdr(scan)) + clauses = list_Nconc(clauses, def_ApplyDefToClauseOnce((DEF) list_Car(scan), c, FlagStore, Precedence)); + + /* If expansions were made delete old clause */ + if (!list_Empty(clauses)) { + /* DOCPROOF ? */ + if (c != Clause) { + if (flag_GetFlagValue(FlagStore, flag_DOCPROOF)) { + prfs_InsertDocProofClause(Search, c); + } + else + clause_Delete(c); + } + nextlist = list_Nconc(nextlist, clauses); + } + else { + /* No more expansions possible for this clause */ + /* If it is not the original clause, add it to the result list */ + if (c != Clause) + result = list_Cons(c, result); + } + } + list_Delete(newclauses); + newclauses = nextlist; + } + + return result; +} + + +void def_Print(DEF D) +/************************************************************** + INPUT: A DEF structure. + RETURNS: None. + EFFECT: Prints the definition to stdout. +***************************************************************/ +{ + LIST scan, scan2; + fputs("\n\nAtom: ", stdout); + fol_PrettyPrint(def_Predicate(D)); + fputs("\nExpansion: \n", stdout); + fol_PrettyPrint(def_Expansion(D)); + if (!list_Empty(def_ClauseNumberList(D))) { + fputs("\nParent clauses: ", stdout); + for (scan = def_ClauseNumberList(D), scan2 = def_ClauseLitsList(D); + !list_Empty(scan); scan = list_Cdr(scan), scan2 = list_Cdr(scan2)) + printf("%d.%d ", (NAT) list_Car(scan), (NAT) list_Car(scan2)); + if (D->conjecture) + fputs("\nDerived from conjecture clauses.", stdout); + else + fputs("\nNot derived from conjecture clauses.", stdout); + } + else { + fputs("\nLabel: ", stdout); + fputs(def_Label(D), stdout); + puts("\nGuard:"); + if (def_ToProve(D) != NULL) + fol_PrettyPrint(def_ToProve(D)); + else + fputs("Nothing.", stdout); + } + + fputs("\nAttributes: ", stdout); + if (def_HasAttribute(D, ISEQUALITY) || def_HasAttribute(D, PREDOCCURONCE)) { + if (def_HasAttribute(D, ISEQUALITY)) + fputs(" Equality ", stdout); + if (def_HasAttribute(D, PREDOCCURONCE)) + fputs(" No Multiple Occurrences ", stdout); + } + else { + fputs(" None ", stdout); + } +} + +LIST def_ApplyDefToClauselist(PROOFSEARCH Search, DEF Def, + LIST Clauselist, BOOL Destructive) +/************************************************************** + INPUT: A proofsearch object, a DEF structure, a list of unshared clauses + and a boolean saying whether the parent clause of an expansion + should be deleted. + RETURNS: None. + EFFECT: For each occurrence of the defined predicate in a clause in the list, + a new clause with expanded predicate is added to the list. +***************************************************************/ +{ + LIST l, newclauses, allnew; + FLAGSTORE FlagStore; + PRECEDENCE Precedence; + + allnew = list_Nil(); + FlagStore = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + for (l = Clauselist; !list_Empty(l); l = list_Cdr(l)) { + newclauses = def_ApplyDefToClauseOnce(Def, (CLAUSE) list_Car(l), + FlagStore, Precedence); + /* Expansions were possible, delete the original clause */ + if (Destructive && !list_Empty(newclauses)) { + if (flag_GetFlagValue(FlagStore, flag_DOCPROOF)) + prfs_InsertDocProofClause(Search, (CLAUSE) list_Car(l)); + else + clause_Delete((CLAUSE) list_Car(l)); + list_Rplaca(l, NULL); + } + allnew = list_Nconc(allnew, newclauses); + } + if (Destructive) + Clauselist = list_PointerDeleteElement(Clauselist, NULL); + + + if (flag_GetFlagValue(FlagStore, flag_PAPPLYDEFS)) { + if (!list_Empty(allnew)) { + fputs("\nNew clauses after applying definitions : \n", stdout); + clause_ListPrint(allnew); + } + } + + Clauselist = list_Nconc(Clauselist, allnew); + return Clauselist; +} + +LIST def_ApplyDefToTermlist(DEF Def, LIST Termlist, + FLAGSTORE FlagStore, PRECEDENCE Precedence, + BOOL* Complete, BOOL Destructive) +/************************************************************** + INPUT: A DEF structure and a list of pairs (label, term), + a flag store, a precedence and a pointer to a + boolean. + If Destructive is TRUE the father of an expanded + term is deleted. + RETURNS: The changed list of terms. + EFFECT: For each occurrence of the defined predicate in a + term in the list, a new term with expanded predicate + is added to the list. + If every occurrence of the predicate could be + expanded, Complete is set to TRUE. +***************************************************************/ +{ + LIST l, newterms; + + newterms = list_Nil(); + + *Complete = TRUE; + for (l=Termlist; !list_Empty(l); l=list_Cdr(l)) { + TERM newterm; + TERM oldterm; + BOOL complete; + oldterm = list_PairSecond(list_Car(l)); + newterm = def_ApplyDefToTermOnce(Def, oldterm, FlagStore, + Precedence, &complete); + if (!complete) + *Complete = FALSE; + /* destructive part of function */ + if (newterm != NULL) { + newterms = list_Cons(list_PairCreate(NULL, newterm),newterms); + if (Destructive) { + /* Delete oldterm from Termlist */ + term_Delete(list_PairSecond(list_Car(l))); + if (list_PairFirst(list_Car(l)) != NULL) + string_StringFree(list_PairFirst(list_Car(l))); + + list_PairFree(list_Car(l)); + list_Rplaca(l, NULL); + } + } + } + Termlist = list_PointerDeleteElement(Termlist, NULL); + + if (flag_GetFlagValue(FlagStore, flag_PAPPLYDEFS)) { + if (!list_Empty(newterms)) { + fputs("\n\nNew terms after applying definitions : \n", stdout); + for (l=newterms; !list_Empty(l); l=list_Cdr(l)) { + fputs("\n", stdout); + fol_PrettyPrint(list_PairSecond(list_Car(l))); + } + } + } + + Termlist = list_Nconc(Termlist, newterms); + return Termlist; +} + +void def_ExtractDefsFromTermlist(PROOFSEARCH Search, LIST Axioms, LIST Conj) +/************************************************************** + INPUT: A proofsearch object and 2 lists of pairs label/term. + RETURNS: None. + EFFECT: Add all found definitions to the proofsearch object. + The old list of definitions in the proofsearch object is + overwritten. +***************************************************************/ +{ + LIST l, deflist; + FLAGSTORE FlagStore; + + deflist = list_Nil(); + FlagStore = prfs_Store(Search); + + for (l=Axioms; !list_Empty(l); l=list_Cdr(l)) { + fol_NormalizeVars(list_PairSecond(list_Car(l))); /* Is needed for proper variable match ! */ + deflist = list_Nconc(deflist, + def_ExtractDefsFromTerm(list_PairSecond(list_Car(l)), + list_PairFirst(list_Car(l)))); + } + for (l=Conj; !list_Empty(l); l=list_Cdr(l)) { + fol_NormalizeVars(list_PairSecond(list_Car(l))); /* Is needed for proper variable match ! */ + deflist = list_Nconc(deflist, + def_ExtractDefsFromTerm(list_PairSecond(list_Car(l)), + list_PairFirst(list_Car(l)))); + } + for (l=deflist; !list_Empty(l); l=list_Cdr(l)) + symbol_AddProperty(term_TopSymbol(def_Predicate(list_Car(l))), ISDEF); + + prfs_SetDefinitions(Search, list_Nconc(prfs_Definitions(Search), deflist)); + + if (flag_GetFlagValue(FlagStore, flag_PAPPLYDEFS)) { + if (!list_Empty(deflist)) { + fputs("\nFound definitions :\n", stdout); + for (l = prfs_Definitions(Search); !list_Empty(l); l = list_Cdr(l)) { + def_Print(list_Car(l)); + fputs("\n---\n", stdout); + } + } + } +} + +LIST def_FlattenWithOneDefinition(PROOFSEARCH Search, DEF Def) +/************************************************************** + INPUT: A proofsearch object and one definition. + RETURNS: The list of new definitions. + EFFECT: For every occurrence of the defined predicate among the other + definitions an expansion is attempted. + A new definition is only created if the result of the expansion is + again a definition. + The proofsearch object is not changed. +***************************************************************/ +{ + LIST newdefinitions; + FLAGSTORE FlagStore; + PRECEDENCE Precedence; + + newdefinitions = list_Nil(); + FlagStore = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + if (def_ToProve(Def) == NULL) { + LIST definitions, l; + + definitions = prfs_Definitions(Search); + + for (l = definitions; !list_Empty(l); l=list_Cdr(l)) { + DEF d; + + d = (DEF) list_Car(l); + if (d != Def) { + /* Expansion possible */ + if (term_ContainsSymbol(def_Expansion(d), term_TopSymbol(def_Predicate(Def)))) { + /* Resulting term is still a definition */ + if (!term_ContainsSymbol(def_Expansion(Def), term_TopSymbol(def_Predicate(d)))) { + TERM newexpansion; + BOOL complete; + DEF newdef; + newexpansion = def_ApplyDefToTermOnce(Def, def_Expansion(d), + FlagStore, Precedence, + &complete); + + newdef = def_CreateFromTerm(newexpansion, + term_Copy(def_Predicate(d)), + term_Copy(def_ToProve(d)), def_Label(d)); + newdefinitions = list_Cons(newdef, newdefinitions); + } + } + } + + } + } + return newdefinitions; +} + + +void def_FlattenWithOneDefinitionDestructive(PROOFSEARCH Search, DEF Def) +/************************************************************** + INPUT: A proofsearch object and one definition. + RETURNS: None. + EFFECT: If the definition is always applicable, every occurrence of the + defined predicate among the other definitions is expanded in place. + If the resulting term is no longer a definition, it is deleted from + the proofsearch object. + Def is deleted. + CAUTION: This function changes the list entries in the list of definitions + in the proofsearch object, so do not call it from a loop over + all definitions. +***************************************************************/ +{ + FLAGSTORE FlagStore; + PRECEDENCE Precedence; + + FlagStore = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + if (def_ToProve(Def) == NULL) { + LIST definitions, l; + + definitions = prfs_Definitions(Search); + for (l = definitions; !list_Empty(l); l = list_Cdr(l)) { + DEF d; + + d = (DEF) list_Car(l); + if (d != Def) { + /* Expansion possible */ + if (term_ContainsSymbol(def_Expansion(d), term_TopSymbol(def_Predicate(Def)))) { + /* Resulting term is still a definition */ + if (!term_ContainsSymbol(def_Expansion(Def), term_TopSymbol(def_Predicate(d)))) { + TERM newexpansion; + BOOL complete; + + newexpansion = def_ApplyDefToTermOnce(Def, def_Expansion(d), FlagStore, Precedence, &complete); + term_Delete(def_Expansion(d)); + def_RplacExp(d, newexpansion); + } + else { + symbol_RemoveProperty(term_TopSymbol(def_Predicate(d)), ISDEF); + def_Delete(d); + list_Rplaca(l, NULL); + } + } + } + else { + /* Remove given definition */ + list_Rplaca(l, NULL); + } + } + symbol_RemoveProperty(term_TopSymbol(def_Predicate(Def)), ISDEF); + def_Delete(Def); + definitions = list_PointerDeleteElement(definitions, NULL); + prfs_SetDefinitions(Search, definitions); + } +} + +void def_FlattenWithOneDefinitionSemiDestructive(PROOFSEARCH Search, DEF Def) +/************************************************************** + INPUT: A proofsearch object and one definition. + RETURNS: Nothing. + EFFECT: If the definition can be applied to another definition + in the search object, that definition is destructively changed. + If the resulting term is no longer a definition, it is deleted to + prevent cycles. + The applied definition Def is NOT deleted. + CAUTION: After calling this function some entries of the definitions list + in the proofsearch object may be NULL. +***************************************************************/ +{ + FLAGSTORE FlagStore; + PRECEDENCE Precedence; + + FlagStore = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + if (def_ToProve(Def) == NULL) { + LIST definitions, l; + + definitions = prfs_Definitions(Search); + for (l = definitions; !list_Empty(l); l=list_Cdr(l)) { + DEF d; + + d = (DEF) list_Car(l); + if (d != Def) { + /* Expansion possible */ + if (term_ContainsSymbol(def_Expansion(d), term_TopSymbol(def_Predicate(Def)))) { + /* Resulting term is still a definition */ + if (!term_ContainsSymbol(def_Expansion(Def), term_TopSymbol(def_Predicate(d)))) { + TERM newexpansion; + BOOL complete; + + newexpansion = def_ApplyDefToTermOnce(Def, def_Expansion(d), + FlagStore, Precedence, + &complete); + term_Delete(def_Expansion(d)); + def_RplacExp(d, newexpansion); + } + else { + symbol_RemoveProperty(term_TopSymbol(def_Predicate(d)), ISDEF); + def_Delete(d); + list_Rplaca(l, NULL); + } + } + } + } + } +} + +void def_FlattenDefinitionsDestructive(PROOFSEARCH Search) +/************************************************************** + INPUT: A proofsearch object. + RETURNS: None. + EFFECT: For every definition that is always applicable try to + expand the predicate in other + definitions if possible. +***************************************************************/ +{ + LIST l; + + for (l = prfs_Definitions(Search); !list_Empty(l); l=list_Cdr(l)) { + DEF d; + + d = (DEF) list_Car(l); + fol_PrettyPrintDFG(def_Predicate(d)); + if (d != NULL) + def_FlattenWithOneDefinitionSemiDestructive(Search, d); + } + prfs_SetDefinitions(Search, list_PointerDeleteElement(prfs_Definitions(Search), NULL)); +} + +LIST def_GetTermsForProof(TERM Term, TERM SubTerm, int Polarity) +/************************************************************** + INPUT: Two formulas, <Term> and <SubTerm> which must be subformula + of <Term>,an int which is the polarity of <SubTerm> in its + superterm and a list of variables <Variables>. + RETURN: A list of formulas that are used to prove the guard of Atom. + COMMENT: Helpfunction of def_FindProofFor Guard. + CAUTION: Father links must be set. Free variables may exist in terms of + return list. + Terms are copied. +***************************************************************/ +{ + TERM SuperTerm, AddToList; + SYMBOL Top; + LIST Scan1, NewList; + + term_AddFatherLinks(Term); + +#ifdef CHECK + if (!fol_CheckFormula(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_GetTermsForProof: Illegal input Term."); + misc_FinishErrorReport(); + } +#endif + + if (Term == SubTerm) + return list_Nil(); + + SuperTerm = term_Superterm(SubTerm); + Top = term_TopSymbol(SuperTerm); + NewList = list_Nil(); + AddToList = term_Null(); + + if (symbol_Equal(Top, fol_Not())) + return def_GetTermsForProof(Term, SuperTerm, -1*Polarity); + + if (symbol_Equal(Top, fol_Or()) && Polarity == 1) { + /* Get and store AddToList */ + for (Scan1 = term_ArgumentList(SuperTerm); !list_Empty(Scan1); Scan1 = list_Cdr(Scan1)) { + if (!term_HasPointerSubterm(list_Car(Scan1), SubTerm)) + NewList = list_Cons(term_Create(fol_Not(),list_List(term_Copy(list_Car(Scan1)))), NewList); + /* NewList's elements have the form not(term) */ + } + if (list_Length(NewList) == 1) { + AddToList = list_Car(NewList); + list_Delete(NewList); + } + else { + AddToList = term_Create(fol_And(), NewList); + } + return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, Polarity)); + } + if (symbol_Equal(Top, fol_And()) && Polarity == -1) { + /* Get and store AddToList */ + if (list_Length(term_ArgumentList(SuperTerm)) == 2) { + if (!term_HasPointerSubterm(term_FirstArgument(SuperTerm), SubTerm)) { + AddToList = term_Copy(term_FirstArgument(SuperTerm)); + } + else { + AddToList = term_Copy(term_SecondArgument(SuperTerm)); + } + } + else if (list_Length(term_ArgumentList(SuperTerm)) > 2) { + for (Scan1 = term_ArgumentList(SuperTerm); !list_Empty(Scan1); Scan1 = list_Cdr(Scan1)) { + if (!term_HasPointerSubterm(list_Car(Scan1), SubTerm)) + NewList = list_Cons(term_Copy(list_Car(Scan1)), NewList); + } + AddToList = term_Create(fol_And(), NewList); + } + else { /* Only one argument */ + AddToList = term_Copy(term_FirstArgument(SuperTerm)); + } + return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, Polarity)); + } + if (symbol_Equal(Top, fol_Implies())) { + if (term_HasPointerSubterm(term_SecondArgument(SuperTerm), SubTerm) && Polarity == 1) { + AddToList = term_Copy(term_FirstArgument(SuperTerm)); + return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, Polarity)); + } + if (term_HasPointerSubterm(term_FirstArgument(SuperTerm), SubTerm) && Polarity == -1) { + AddToList = term_Copy(term_SecondArgument(SuperTerm)); + AddToList = term_Create(fol_Not(), list_List(AddToList)); + return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, -1*Polarity)); + } + } + if (symbol_Equal(Top, fol_Implied())) { /* symmetric to fol_Implies */ + if (term_HasPointerSubterm(term_SecondArgument(SuperTerm), SubTerm) && Polarity == -1) { + AddToList = term_Copy(term_FirstArgument(SuperTerm)); + AddToList = term_Create(fol_Not(), list_List(AddToList)); + return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, -1*Polarity)); + } + if (term_HasPointerSubterm(term_FirstArgument(SuperTerm), SubTerm) && Polarity == 1) { + AddToList = term_Copy(term_SecondArgument(SuperTerm)); + return list_Cons(AddToList, def_GetTermsForProof(Term, SuperTerm, Polarity)); + } + } + if (fol_IsQuantifier(Top)) + return def_GetTermsForProof(Term, SuperTerm, Polarity); + + /* In all other cases, SubTerm is the top level term in which Atom occurs disjunctively */ + + return list_Nil(); +} + +BOOL def_FindProofForGuard(TERM Term, TERM Atom, TERM Guard, FLAGSTORE FlagStore, PRECEDENCE Precedence) +/************************************************************************** + INPUT: A formula Term, an atom Atom, a term Guard a flag store and a + precedence. + RETURNS: True iff a proof can be found for Guard in Term. +***************************************************************************/ +{ + BOOL LocallyTrue; + TERM ToProve, Conjecture; + LIST ArgList, FreeVars; + + ArgList = list_Nil(); + FreeVars = list_Nil(); + ToProve = term_Null(); + Conjecture = term_Copy(Term); + +#ifdef CHECK + if (!fol_CheckFormula(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_FindProofForGuard: No correct formula term."); + misc_FinishErrorReport(); + } + if (!term_HasPointerSubterm(Term, Atom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_FindProofForGuard: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + ArgList = def_GetTermsForProof(Term, Atom, 1); + + if (!list_Empty(ArgList)) { + ToProve = term_Create(fol_And(), ArgList); + FreeVars = list_Nconc(fol_FreeVariables(ToProve), fol_FreeVariables(Guard)); + FreeVars = term_DeleteDuplicatesFromList(FreeVars); + term_CopyTermsInList(FreeVars); + + ArgList = list_List(term_Copy(Guard)); + ArgList = list_Cons(ToProve, ArgList); + ToProve = term_Create(fol_Implies(), ArgList); + ToProve = fol_CreateQuantifier(fol_All(), FreeVars, list_List(ToProve)); + + /* Now ToProve has the form <forall[]: A implies Guard> */ + /* puts("\n*ToProve: "); fol_PrettyPrintDFG(ToProve); */ + +#ifdef CHECK + if (!fol_CheckFormula(ToProve)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_FindProofForGuard: No correct formula ToProve."); + misc_FinishErrorReport(); + } +#endif + + LocallyTrue = cnf_HaveProof(list_Nil(), ToProve, FlagStore, Precedence); + term_Delete(ToProve); + term_Delete(Conjecture); + if (LocallyTrue) + return TRUE; + } + else { /* empty list */ + term_DeleteTermList(ArgList); + term_Delete(Conjecture); + } + + return FALSE; +} + +LIST def_ApplyDefinitionToTermList(LIST Defs, LIST Terms, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************************** + INPUT: A list of definitions <Defs> and a list of pairs (Label.Formula), + the maximal number <Applics> of expansions, a flag store and a + precedence. + RETURNS: The possibly destructively changed list <Terms>. + EFFECT: In all formulas of Terms any definition of Defs is applied exactly + once if possible. + The terms are changed destructively if the expanded def_predicate + is not an equality. +**************************************************************************/ +{ + TERM ActTerm; /* Actual term in Terms */ + TERM DefPredicate; /* Actual definition predicate out of Defs */ + TERM Expansion; /* Expansion term of the definition */ + TERM Target; /* Target predicate to be replaced */ + LIST TargetList, Scan1, Scan2, Scan3; + BOOL Apply; + int Applics; + + Apply = TRUE; + TargetList = list_Nil(); + Applics = flag_GetFlagValue(Flags, flag_APPLYDEFS); + + while (Apply && Applics != 0) { + Apply = FALSE; + + for (Scan1=Defs; !list_Empty(Scan1) && Applics != 0; Scan1=list_Cdr(Scan1)) { + DefPredicate = term_Copy(def_Predicate(list_Car(Scan1))); + + /* puts("\n----\nDefPred:"); fol_PrettyPrintDFG(DefPredicate);*/ + + for (Scan2=Terms; !list_Empty(Scan2) && Applics != 0; Scan2=list_Cdr(Scan2)) { + ActTerm = list_PairSecond(list_Car(Scan2)); + TargetList = term_FindAllAtoms(ActTerm, term_TopSymbol(DefPredicate)); + term_AddFatherLinks(ActTerm); + + /* puts("\nActTerm:"); fol_PrettyPrintDFG(ActTerm);*/ + + for (Scan3=TargetList; !list_Empty(Scan3) && Applics != 0; Scan3=list_Cdr(Scan3)) { + Target = list_Car(Scan3); + cont_StartBinding(); + + /* puts("\nTarget:"); fol_PrettyPrintDFG(Target);*/ + + if (unify_Match(cont_LeftContext(), DefPredicate, Target)) { + cont_BackTrack(); + Expansion = term_Copy(def_Expansion(list_Car(Scan1))); + fol_NormalizeVarsStartingAt(ActTerm, term_MaxVar(Expansion)); + unify_Match(cont_LeftContext(), DefPredicate, Target); + + if (fol_ApplyContextToTerm(cont_LeftContext(), Expansion)) { /* Matcher applied on Expansion */ + if (!def_HasGuard(list_Car(Scan1))) { + Applics--; + Apply = TRUE; + /* puts("\n*no Guard!");*/ + term_RplacTop(Target, term_TopSymbol(Expansion)); + term_DeleteTermList(term_ArgumentList(Target)); + term_RplacArgumentList(Target, term_ArgumentList(Expansion)); + term_RplacArgumentList(Expansion, list_Nil()); + term_AddFatherLinks(ActTerm); +#ifdef CHECK + if (!fol_CheckFormula(ActTerm)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_ApplyDefinitionToTermList:"); + misc_ErrorReport(" No correct formula ActTerm."); + misc_FinishErrorReport(); + } +#endif + if (flag_GetFlagValue(Flags, flag_PAPPLYDEFS)) { + puts("\nApplied definition for"); + fol_PrettyPrintDFG(def_Predicate(list_Car(Scan1))); + puts("\nNew formula:"); + fol_PrettyPrintDFG(ActTerm); + } + } + else { /* check guard */ + TERM Guard; + Guard = term_Copy(def_ToProve(list_Car(Scan1))); + if (fol_ApplyContextToTerm(cont_LeftContext(), Guard)) { + cont_BackTrack(); + if (def_FindProofForGuard(ActTerm, Target,Guard, + Flags, Precedence)) { + Applics--; + Apply = TRUE; + term_RplacTop(Target, term_TopSymbol(Expansion)); + term_DeleteTermList(term_ArgumentList(Target)); + term_RplacArgumentList(Target, term_ArgumentList(Expansion)); + term_RplacArgumentList(Expansion, list_Nil()); + term_AddFatherLinks(ActTerm); +#ifdef CHECK + if (!fol_CheckFormula(ActTerm)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In def_ApplyDefinitionToTermList:"); + misc_ErrorReport(" No correct formula ActTerm"); + misc_FinishErrorReport(); + } +#endif + if (flag_GetFlagValue(Flags, flag_PAPPLYDEFS)) { + puts("\nApplied definition for"); + fol_PrettyPrintDFG(def_Predicate(list_Car(Scan1))); + puts("\nNew formula:"); + fol_PrettyPrintDFG(ActTerm); + } + } + } + term_Delete(Guard); + } + } + term_Delete(Expansion); + } + cont_BackTrack(); + } + list_Delete(TargetList); + } + term_Delete(DefPredicate); + } + } + return Terms; +} diff --git a/test/spass/defs.h b/test/spass/defs.h new file mode 100644 index 0000000000000000000000000000000000000000..e3cdd2dcd9e19a6fca9dd550de98c924e4c035ee --- /dev/null +++ b/test/spass/defs.h @@ -0,0 +1,205 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * Definitions * */ +/* * * */ +/* * $Module: DEFS * */ +/* * * */ +/* * Copyright (C) 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _DEFS_ +#define _DEFS_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + + +#include "clause.h" +#include "term.h" +#include "list.h" +#include "search.h" + +/**************************************************************/ +/* Structures */ +/**************************************************************/ +typedef enum { PREDOCCURONCE = 1, /* whether predicate occurs only once */ + ISEQUALITY = 2 /* whether predicate is equality */ +} DEF_ATTRIBUTES; + +typedef struct DEF_HELP { + TERM expansion; /* The definition of the predicate term*/ + TERM predicate; /* The predicate which is defined*/ + TERM toprove; + LIST parentclauses; /* List of clause numbers plus list of literal indices */ + const char *label; /* The label of the predicate term*/ + BOOL conjecture; + NAT attributes; /* The attributes of the predicate*/ +} *DEF, DEF_NODE; + +/**************************************************************/ +/* Inline functions */ +/**************************************************************/ +static __inline__ TERM def_Expansion(DEF D) +{ + return D->expansion; +} + +static __inline__ void def_RplacExp(DEF D, TERM E) +{ + D->expansion = E; +} + +static __inline__ TERM def_Predicate(DEF D) +{ + return D->predicate; +} + +static __inline__ void def_RplacPred(DEF D, TERM Pred) +{ + D->predicate = Pred; +} + +static __inline__ TERM def_ToProve(DEF D) +{ + return D->toprove; +} + +static __inline__ void def_RplacToProve(DEF D, TERM ToProve) +{ + D->toprove = ToProve; +} + +static __inline__ LIST def_ClauseNumberList(DEF D) +{ + return list_PairFirst(D->parentclauses); +} + +static __inline__ void def_RplacClauseNumberList(DEF D, LIST L) +{ + list_Rplaca(D->parentclauses, L); +} + +static __inline__ LIST def_ClauseLitsList(DEF D) +{ + return list_PairSecond(D->parentclauses); +} + +static __inline__ void def_RplacClauseLitsList(DEF D, LIST L) +{ + list_Rplacd(D->parentclauses, L); +} + +static __inline__ const char* def_Label(DEF D) +{ + return D->label; +} + +static __inline__ void def_RplacLabel(DEF D, const char* L) +{ + D->label = L; +} + +static __inline__ BOOL def_Conjecture(DEF D) +{ + return D->conjecture; +} + +static __inline__ void def_SetConjecture(DEF D) +{ + D->conjecture = TRUE; +} + +static __inline__ void def_AddAttribute(DEF D, DEF_ATTRIBUTES Attribute) +{ + D->attributes = D->attributes | Attribute; +} + +static __inline__ NAT def_HasAttribute(DEF D, DEF_ATTRIBUTES Attribute) +{ + return (D->attributes & Attribute); +} + +static __inline__ void def_RemoveAttribute(DEF D, DEF_ATTRIBUTES Attribute) +{ + if (D->attributes & Attribute) + D->attributes = D->attributes - Attribute; +} + +static __inline__ BOOL def_HasGuard(DEF D) +{ + return (def_ToProve(D)!=term_Null()); +} + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +DEF def_CreateFromClauses(TERM, TERM, LIST, LIST, BOOL); +DEF def_CreateFromTerm(TERM, TERM, TERM, const char*); + +LIST def_ExtractDefsFromTerm(TERM, const char*); +void def_ExtractDefsFromTermlist(PROOFSEARCH, LIST, LIST); +void def_ExtractDefsFromClauselist(PROOFSEARCH, LIST); + +TERM def_ApplyDefToTermOnce(DEF, TERM, FLAGSTORE, PRECEDENCE, BOOL*); +TERM def_ApplyDefToTermExhaustive(PROOFSEARCH, TERM); +LIST def_ApplyDefToTermlist(DEF, LIST, FLAGSTORE, PRECEDENCE, BOOL*, BOOL); +LIST def_ApplyDefinitionToTermList(LIST, LIST, FLAGSTORE, PRECEDENCE); +/* +LIST def_GetTermsForProof(TERM, TERM, int); +BOOL def_FindProofForGuard(TERM, TERM, TERM, FLAGSTORE); +*/ + +LIST def_ApplyDefToClauseOnce(DEF, CLAUSE, FLAGSTORE, PRECEDENCE); +LIST def_ApplyDefToClauseExhaustive(PROOFSEARCH, CLAUSE); +LIST def_ApplyDefToClauselist(PROOFSEARCH, DEF, LIST, BOOL); + +LIST def_FlattenWithOneDefinition(PROOFSEARCH, DEF); +void def_FlattenWithOneDefinitionSemiDestructive(PROOFSEARCH, DEF); +void def_FlattenWithOneDefinitionDestructive(PROOFSEARCH, DEF); +void def_FlattenDefinitionsDestructive(PROOFSEARCH); + +void def_Delete(DEF); +void def_Print(DEF); + +int def_PredicateOccurrences(TERM, SYMBOL); +#endif diff --git a/test/spass/dfg.h b/test/spass/dfg.h new file mode 100644 index 0000000000000000000000000000000000000000..83d38ae715ce72ce77d090fe25df8ff1ab8b81c9 --- /dev/null +++ b/test/spass/dfg.h @@ -0,0 +1,86 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INTERFACE FOR THE DFG PARSER * */ +/* * * */ +/* * $Module: DFG * */ +/* * * */ +/* * Copyright (C) 1997, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _DFG_ +#define _DFG_ + +#include <stdio.h> +#include "list.h" +#include "flags.h" +#include "clause.h" + +typedef enum { DFG_SATISFIABLE, DFG_UNSATISFIABLE, DFG_UNKNOWNSTATE } DFG_STATE; + +/* Parser functions */ +LIST dfg_DFGParser(FILE*, FLAGSTORE, PRECEDENCE, LIST*, LIST*, LIST*, LIST*); +LIST dfg_ProofParser(FILE*, FLAGSTORE, PRECEDENCE); +LIST dfg_TermParser(FILE*, FLAGSTORE, PRECEDENCE); + + +/* Functions for accessing description information */ +const char* dfg_ProblemName(void); +const char* dfg_ProblemAuthor(void); +const char* dfg_ProblemVersion(void); +const char* dfg_ProblemLogic(void); +DFG_STATE dfg_ProblemStatus(void); +const char* dfg_ProblemStatusString(void); +const char* dfg_ProblemDescription(void); +const char* dfg_ProblemDate(void); +NAT dfg_DescriptionLength(void); + +/* Misc functions */ +void dfg_Free(void); /* Must be called after each parser call */ +void dfg_DeleteFormulaPairList(LIST); +void dfg_StripLabelsFromList(LIST); +void dfg_FPrintDescription(FILE*); + +void dfg_DeleteProofList(LIST); + +CLAUSE dfg_CreateClauseFromTerm(TERM, BOOL, FLAGSTORE, PRECEDENCE); +TERM dfg_CreateQuantifier(SYMBOL, LIST, TERM); + +#endif diff --git a/test/spass/dfgparser.c b/test/spass/dfgparser.c new file mode 100644 index 0000000000000000000000000000000000000000..3691271b53b6548d9cb773130c6dadaf2ea40cf0 --- /dev/null +++ b/test/spass/dfgparser.c @@ -0,0 +1,3728 @@ +/* A Bison parser, made from dfgparser.y, by GNU bison 1.75. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* If NAME_PREFIX is specified substitute the variables and functions + names. */ +#define yyparse dfg_parse +#define yylex dfg_lex +#define yyerror dfg_error +#define yylval dfg_lval +#define yychar dfg_char +#define yydebug dfg_debug +#define yynerrs dfg_nerrs + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + DFG_AND = 258, + DFG_AUTHOR = 259, + DFG_AXIOMS = 260, + DFG_BEGPROB = 261, + DFG_BY = 262, + DFG_CLAUSE = 263, + DFG_CLOSEBRACE = 264, + DFG_CLSLIST = 265, + DFG_CNF = 266, + DFG_CONJECS = 267, + DFG_DATE = 268, + DFG_DECLLIST = 269, + DFG_DESC = 270, + DFG_DESCLIST = 271, + DFG_DNF = 272, + DFG_DOMPRED = 273, + DFG_ENDLIST = 274, + DFG_ENDPROB = 275, + DFG_EQUAL = 276, + DFG_EQUIV = 277, + DFG_EXISTS = 278, + DFG_FALSE = 279, + DFG_FORMLIST = 280, + DFG_FORMULA = 281, + DFG_FORALL = 282, + DFG_FREELY = 283, + DFG_FUNC = 284, + DFG_GENERATED = 285, + DFG_GENSET = 286, + DFG_HYPOTH = 287, + DFG_IMPLIED = 288, + DFG_IMPLIES = 289, + DFG_LOGIC = 290, + DFG_NAME = 291, + DFG_NOT = 292, + DFG_OPENBRACE = 293, + DFG_OPERAT = 294, + DFG_OR = 295, + DFG_PREC = 296, + DFG_PRED = 297, + DFG_PRDICAT = 298, + DFG_PRFLIST = 299, + DFG_QUANTIF = 300, + DFG_SATIS = 301, + DFG_SETFLAG = 302, + DFG_SETTINGS = 303, + DFG_SYMLIST = 304, + DFG_SORT = 305, + DFG_SORTS = 306, + DFG_STATUS = 307, + DFG_STEP = 308, + DFG_SUBSORT = 309, + DFG_TERMLIST = 310, + DFG_TRUE = 311, + DFG_UNKNOWN = 312, + DFG_UNSATIS = 313, + DFG_VERSION = 314, + DFG_NUM = 315, + DFG_MINUS1 = 316, + DFG_ID = 317, + DFG_TEXT = 318 + }; +#endif +#define DFG_AND 258 +#define DFG_AUTHOR 259 +#define DFG_AXIOMS 260 +#define DFG_BEGPROB 261 +#define DFG_BY 262 +#define DFG_CLAUSE 263 +#define DFG_CLOSEBRACE 264 +#define DFG_CLSLIST 265 +#define DFG_CNF 266 +#define DFG_CONJECS 267 +#define DFG_DATE 268 +#define DFG_DECLLIST 269 +#define DFG_DESC 270 +#define DFG_DESCLIST 271 +#define DFG_DNF 272 +#define DFG_DOMPRED 273 +#define DFG_ENDLIST 274 +#define DFG_ENDPROB 275 +#define DFG_EQUAL 276 +#define DFG_EQUIV 277 +#define DFG_EXISTS 278 +#define DFG_FALSE 279 +#define DFG_FORMLIST 280 +#define DFG_FORMULA 281 +#define DFG_FORALL 282 +#define DFG_FREELY 283 +#define DFG_FUNC 284 +#define DFG_GENERATED 285 +#define DFG_GENSET 286 +#define DFG_HYPOTH 287 +#define DFG_IMPLIED 288 +#define DFG_IMPLIES 289 +#define DFG_LOGIC 290 +#define DFG_NAME 291 +#define DFG_NOT 292 +#define DFG_OPENBRACE 293 +#define DFG_OPERAT 294 +#define DFG_OR 295 +#define DFG_PREC 296 +#define DFG_PRED 297 +#define DFG_PRDICAT 298 +#define DFG_PRFLIST 299 +#define DFG_QUANTIF 300 +#define DFG_SATIS 301 +#define DFG_SETFLAG 302 +#define DFG_SETTINGS 303 +#define DFG_SYMLIST 304 +#define DFG_SORT 305 +#define DFG_SORTS 306 +#define DFG_STATUS 307 +#define DFG_STEP 308 +#define DFG_SUBSORT 309 +#define DFG_TERMLIST 310 +#define DFG_TRUE 311 +#define DFG_UNKNOWN 312 +#define DFG_UNSATIS 313 +#define DFG_VERSION 314 +#define DFG_NUM 315 +#define DFG_MINUS1 316 +#define DFG_ID 317 +#define DFG_TEXT 318 + + + + +/* Copy the first part of user declarations. */ +#line 48 "dfgparser.y" + + +#include <ctype.h> +#include "dfg.h" +#include "symbol.h" +#include "term.h" +#include "foldfg.h" +#include "stringsx.h" + +/* Used for the texts from description section. */ +typedef struct { + char* name; + char* author; + char* version; + char* logic; + DFG_STATE status; + char* description; + char* date; +} DFG_DESCRIPTIONTYPE; + +static DFG_DESCRIPTIONTYPE dfg_DESC; +static LIST dfg_AXIOMLIST; +static LIST dfg_CONJECLIST; +static LIST dfg_SORTDECLLIST; +/* symbol precedence explicitly defined by user */ +static LIST dfg_USERPRECEDENCE; +static LIST dfg_AXCLAUSES; +static LIST dfg_CONCLAUSES; +static LIST dfg_PROOFLIST; /* list_of_proofs */ +static LIST dfg_TERMLIST; /* list_of_terms */ +static BOOL dfg_IGNORE; /* tokens are ignored while TRUE */ +static FLAGSTORE dfg_FLAGS; +static PRECEDENCE dfg_PRECEDENCE; + +/* used also in the scanner */ +NAT dfg_LINENUMBER; +BOOL dfg_IGNORETEXT; + +void yyerror(const char*); +int yylex(void); /* Defined in dfgscanner.l */ + +static void dfg_SymbolDecl(int, char*, int); +static SYMBOL dfg_Symbol(char*, NAT); +static void dfg_SubSort(char*, char*); +static void dfg_SymbolGenerated(SYMBOL, BOOL, LIST); + +static __inline__ TERM dfg_TermCreate(char* Name, LIST Arguments) +/* Look up the symbol, check its arity and create the term */ +{ + SYMBOL s; + NAT arity; + arity = list_Length(Arguments); + s = dfg_Symbol(Name, arity); /* Frees the string */ + if (!symbol_IsVariable(s) && !symbol_IsFunction(s)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: is not a function.\n", dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + return term_Create(s, Arguments); +} + +static __inline__ TERM dfg_AtomCreate(char* Name, LIST Arguments) +/* Look up the symbol, check its arity and create the atom term */ +{ + SYMBOL s; + s = dfg_Symbol(Name, list_Length(Arguments)); /* Frees the string */ + if (symbol_IsVariable(s) || !symbol_IsPredicate(s)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: Symbol is not a predicate.\n", dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + return term_Create(s, Arguments); +} + +static __inline__ void dfg_DeleteStringList(LIST List) +{ + list_DeleteWithElement(List, (void (*)(POINTER)) string_StringFree); +} + +/**************************************************************/ +/* Functions that handle symbols with unspecified arity */ +/**************************************************************/ + +/* The symbol list holds all symbols whose arity wasn't */ +/* specified in the symbol declaration section. */ +/* If the arity of a symbol was not specified in this section */ +/* it is first set to 0. If the symbol occurs with always the */ +/* same arity 'A' the arity of this symbol is set to 'A'. */ +static LIST dfg_SYMBOLLIST; + +static void dfg_SymAdd(SYMBOL); +static void dfg_SymCheck(SYMBOL, NAT); +static void dfg_SymCleanUp(void); + +/**************************************************************/ +/* Functions that handle variable names */ +/**************************************************************/ + +/* List of quantified variables in the current input formula. */ +/* This list is used to find symbols that by mistake weren't */ +/* declared in the symbol declaration section */ +/* --> free variables */ +/* This is a list of lists, since each time a quantifier is */ +/* reached, a new list is added to the global list. */ +static LIST dfg_VARLIST; +static BOOL dfg_VARDECL; + +static void dfg_VarStart(void); +static void dfg_VarStop(void); +static void dfg_VarBacktrack(void); +static void dfg_VarCheck(void); +static SYMBOL dfg_VarLookup(char*); + +#define YYERROR_VERBOSE + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#ifndef YYSTYPE +#line 165 "dfgparser.y" +typedef union { + int number; + char* string; + SYMBOL symbol; + SPROPERTY property; + TERM term; + LIST list; + DFG_STATE state; + BOOL bool; +} yystype; +/* Line 193 of /opt/gnu//share/bison/yacc.c. */ +#line 336 "dfgparser.c" +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +#ifndef YYLTYPE +typedef struct yyltype +{ + int first_line; + int first_column; + int last_line; + int last_column; +} yyltype; +# define YYLTYPE yyltype +# define YYLTYPE_IS_TRIVIAL 1 +#endif + +/* Copy the second part of user declarations. */ + + +/* Line 213 of /opt/gnu//share/bison/yacc.c. */ +#line 357 "dfgparser.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAX) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 4 +#define YYLAST 506 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 71 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 100 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 196 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 477 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 318 + +#define YYTRANSLATE(X) \ + ((unsigned)(X) <= YYMAXUTOK ? yytranslate[X] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 64, 65, 2, 2, 69, 2, 66, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 70, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 67, 2, 68, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned short yyprhs[] = +{ + 0, 0, 3, 14, 26, 32, 38, 44, 50, 51, + 57, 58, 64, 65, 71, 73, 75, 77, 84, 85, + 95, 96, 102, 104, 108, 110, 116, 117, 123, 125, + 129, 131, 137, 138, 144, 146, 150, 151, 157, 159, + 163, 165, 171, 172, 178, 180, 184, 186, 192, 194, + 196, 197, 203, 204, 207, 209, 217, 220, 228, 229, + 230, 242, 252, 253, 255, 257, 261, 263, 267, 276, + 278, 280, 281, 284, 285, 293, 294, 297, 299, 304, + 311, 316, 317, 318, 329, 330, 332, 334, 338, 340, + 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, + 362, 364, 368, 370, 375, 376, 379, 390, 391, 403, + 404, 412, 413, 415, 417, 418, 419, 430, 435, 437, + 441, 443, 448, 450, 454, 456, 458, 460, 467, 472, + 473, 481, 482, 484, 486, 495, 500, 502, 507, 509, + 513, 514, 517, 518, 528, 529, 545, 547, 551, 552, + 557, 561, 567, 568, 572, 574, 576, 578, 580, 582, + 584, 586, 588, 590, 591, 595, 603, 605, 607, 608, + 611, 612, 619, 620, 624, 625, 628, 634, 635, 645, + 647, 651, 652, 656, 661, 666, 673, 675, 679, 681, + 688, 689, 692, 694, 697, 703, 705 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const short yyrhs[] = +{ + 72, 0, -1, 6, 64, 121, 65, 66, 73, 82, + 159, 20, 66, -1, 16, 66, 74, 75, 78, 79, + 76, 77, 80, 19, 66, -1, 36, 64, 63, 65, + 66, -1, 4, 64, 63, 65, 66, -1, 52, 64, + 81, 65, 66, -1, 15, 64, 63, 65, 66, -1, + -1, 59, 64, 63, 65, 66, -1, -1, 35, 64, + 63, 65, 66, -1, -1, 13, 64, 63, 65, 66, + -1, 46, -1, 58, -1, 57, -1, 83, 99, 110, + 124, 143, 155, -1, -1, 49, 66, 84, 87, 90, + 92, 95, 19, 66, -1, -1, 29, 67, 85, 68, + 66, -1, 86, -1, 85, 69, 86, -1, 121, -1, + 64, 121, 69, 98, 65, -1, -1, 43, 67, 88, + 68, 66, -1, 89, -1, 88, 69, 89, -1, 121, + -1, 64, 121, 69, 98, 65, -1, -1, 51, 67, + 91, 68, 66, -1, 121, -1, 91, 69, 121, -1, + -1, 39, 67, 93, 68, 66, -1, 94, -1, 93, + 69, 94, -1, 121, -1, 64, 121, 69, 98, 65, + -1, -1, 45, 67, 96, 68, 66, -1, 97, -1, + 96, 69, 97, -1, 121, -1, 64, 121, 69, 98, + 65, -1, 61, -1, 60, -1, -1, 14, 66, 100, + 19, 66, -1, -1, 100, 101, -1, 104, -1, 54, + 64, 121, 69, 121, 65, 66, -1, 136, 66, -1, + 42, 64, 121, 69, 107, 65, 66, -1, -1, -1, + 27, 64, 67, 102, 122, 103, 68, 69, 136, 65, + 66, -1, 50, 121, 105, 30, 7, 67, 106, 68, + 66, -1, -1, 28, -1, 121, -1, 106, 69, 121, + -1, 121, -1, 107, 69, 121, -1, 25, 64, 109, + 65, 66, 111, 19, 66, -1, 5, -1, 12, -1, + -1, 110, 108, -1, -1, 111, 26, 64, 116, 112, + 65, 66, -1, -1, 69, 121, -1, 136, -1, 37, + 64, 113, 65, -1, 118, 64, 113, 69, 113, 65, + -1, 119, 64, 117, 65, -1, -1, -1, 120, 64, + 67, 114, 122, 115, 68, 69, 113, 65, -1, -1, + 113, -1, 113, -1, 117, 69, 113, -1, 22, -1, + 33, -1, 34, -1, 3, -1, 40, -1, 23, -1, + 27, -1, 62, -1, 60, -1, 47, -1, 18, -1, + 41, -1, 123, -1, 122, 69, 123, -1, 121, -1, + 121, 64, 121, 65, -1, -1, 124, 125, -1, 10, + 64, 109, 69, 11, 65, 66, 127, 19, 66, -1, + -1, 10, 64, 109, 69, 17, 65, 66, 126, 137, + 19, 66, -1, -1, 127, 8, 64, 128, 112, 65, + 66, -1, -1, 129, -1, 132, -1, -1, -1, 27, + 64, 67, 130, 122, 131, 68, 69, 132, 65, -1, + 40, 64, 133, 65, -1, 134, -1, 133, 69, 134, + -1, 136, -1, 37, 64, 136, 65, -1, 136, -1, + 135, 69, 136, -1, 121, -1, 56, -1, 24, -1, + 21, 64, 141, 69, 141, 65, -1, 121, 64, 142, + 65, -1, -1, 137, 8, 64, 138, 112, 65, 66, + -1, -1, 139, -1, 140, -1, 23, 64, 67, 135, + 68, 69, 140, 65, -1, 3, 64, 133, 65, -1, + 121, -1, 121, 64, 142, 65, -1, 141, -1, 142, + 69, 141, -1, -1, 143, 144, -1, -1, 44, 64, + 121, 65, 66, 145, 146, 19, 66, -1, -1, 146, + 53, 64, 150, 69, 154, 69, 121, 69, 67, 147, + 68, 148, 65, 66, -1, 150, -1, 147, 69, 150, + -1, -1, 69, 67, 149, 68, -1, 150, 70, 150, + -1, 149, 69, 150, 70, 150, -1, -1, 152, 151, + 153, -1, 121, -1, 37, -1, 22, -1, 33, -1, + 34, -1, 3, -1, 40, -1, 27, -1, 23, -1, + -1, 64, 117, 65, -1, 64, 67, 122, 68, 69, + 113, 65, -1, 129, -1, 139, -1, -1, 155, 156, + -1, -1, 55, 66, 157, 158, 19, 66, -1, -1, + 158, 141, 66, -1, -1, 159, 160, -1, 31, 66, + 168, 19, 66, -1, -1, 48, 64, 121, 161, 65, + 66, 162, 19, 66, -1, 63, -1, 38, 163, 9, + -1, -1, 163, 164, 66, -1, 41, 64, 165, 65, + -1, 18, 64, 170, 65, -1, 47, 64, 62, 69, + 98, 65, -1, 166, -1, 165, 69, 166, -1, 121, + -1, 64, 121, 69, 60, 167, 65, -1, -1, 69, + 62, -1, 169, -1, 168, 169, -1, 32, 67, 170, + 68, 66, -1, 121, -1, 170, 69, 121, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short yyrline[] = +{ + 0, 206, 206, 218, 229, 233, 237, 241, 245, 246, + 250, 251, 255, 256, 260, 261, 262, 269, 281, 282, + 291, 292, 295, 296, 299, 300, 304, 305, 308, 309, + 312, 313, 316, 317, 320, 321, 324, 325, 328, 329, + 332, 333, 336, 337, 340, 341, 344, 345, 348, 349, + 356, 357, 362, 363, 366, 367, 369, 370, 372, 373, + 372, 382, 386, 387, 390, 391, 394, 395, 402, 412, + 413, 416, 417, 420, 421, 435, 436, 439, 440, 442, + 444, 446, 447, 446, 454, 455, 458, 460, 464, 465, + 466, 469, 470, 473, 474, 477, 483, 485, 487, 489, + 493, 495, 499, 510, 534, 535, 538, 548, 547, 554, + 555, 569, 570, 573, 574, 575, 574, 582, 586, 588, + 592, 593, 597, 598, 601, 603, 605, 607, 609, 616, + 617, 620, 621, 624, 625, 628, 635, 637, 641, 643, + 651, 652, 656, 655, 669, 670, 691, 693, 698, 699, + 702, 710, 721, 720, 732, 733, 734, 735, 736, 737, + 738, 739, 740, 743, 744, 745, 748, 749, 757, 758, + 761, 761, 768, 769, 776, 777, 780, 781, 781, 789, + 792, 795, 796, 799, 800, 820, 832, 833, 836, 848, + 865, 866, 883, 884, 887, 891, 892 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "DFG_AND", "DFG_AUTHOR", "DFG_AXIOMS", + "DFG_BEGPROB", "DFG_BY", "DFG_CLAUSE", "DFG_CLOSEBRACE", "DFG_CLSLIST", + "DFG_CNF", "DFG_CONJECS", "DFG_DATE", "DFG_DECLLIST", "DFG_DESC", + "DFG_DESCLIST", "DFG_DNF", "DFG_DOMPRED", "DFG_ENDLIST", "DFG_ENDPROB", + "DFG_EQUAL", "DFG_EQUIV", "DFG_EXISTS", "DFG_FALSE", "DFG_FORMLIST", + "DFG_FORMULA", "DFG_FORALL", "DFG_FREELY", "DFG_FUNC", "DFG_GENERATED", + "DFG_GENSET", "DFG_HYPOTH", "DFG_IMPLIED", "DFG_IMPLIES", "DFG_LOGIC", + "DFG_NAME", "DFG_NOT", "DFG_OPENBRACE", "DFG_OPERAT", "DFG_OR", + "DFG_PREC", "DFG_PRED", "DFG_PRDICAT", "DFG_PRFLIST", "DFG_QUANTIF", + "DFG_SATIS", "DFG_SETFLAG", "DFG_SETTINGS", "DFG_SYMLIST", "DFG_SORT", + "DFG_SORTS", "DFG_STATUS", "DFG_STEP", "DFG_SUBSORT", "DFG_TERMLIST", + "DFG_TRUE", "DFG_UNKNOWN", "DFG_UNSATIS", "DFG_VERSION", "DFG_NUM", + "DFG_MINUS1", "DFG_ID", "DFG_TEXT", "'('", "')'", "'.'", "'['", "']'", + "','", "':'", "$accept", "problem", "description", "name", "author", + "status", "desctext", "versionopt", "logicopt", "dateopt", "log_state", + "logicalpart", "symbollistopt", "functionsopt", "functionlist", "func", + "predicatesopt", "predicatelist", "pred", "sortsopt", "sortlist", + "operatorsopt", "operatorlist", "op", "quantifiersopt", + "quantifierlist", "quant", "number", "declarationlistopt", + "decllistopt", "decl", "@1", "@2", "gendecl", "freelyopt", "funclist", + "sortdecl", "formulalist", "origin", "formulalistsopt", + "formulalistopt", "labelopt", "formula", "@3", "@4", "formulaopt", + "arglist", "binsymbol", "nsymbol", "quantsymbol", "id", "qtermlist", + "qterm", "clauselistsopt", "clauselist", "@5", "cnfclausesopt", + "cnfclauseopt", "cnfclause", "@6", "@7", "cnfclausebody", "litlist", + "lit", "atomlist", "atom", "dnfclausesopt", "dnfclauseopt", "dnfclause", + "dnfclausebody", "term", "termlist", "prooflistsopt", "prooflist", "@8", + "prooflistopt", "parentlist", "assoclistopt", "assoclist", + "id_or_formula", "@9", "anysymbol", "optargs", "clause", + "listOfTermsopt", "listOfTerms", "@10", "terms", "settinglistsopt", + "settinglist", "@11", "flags", "spassflags", "spassflag", "preclist", + "precitem", "statopt", "gsettings", "gsetting", "labellist", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 40, 41, 46, 91, 93, 44, + 58 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 71, 72, 73, 74, 75, 76, 77, 78, 78, + 79, 79, 80, 80, 81, 81, 81, 82, 83, 83, + 84, 84, 85, 85, 86, 86, 87, 87, 88, 88, + 89, 89, 90, 90, 91, 91, 92, 92, 93, 93, + 94, 94, 95, 95, 96, 96, 97, 97, 98, 98, + 99, 99, 100, 100, 101, 101, 101, 101, 102, 103, + 101, 104, 105, 105, 106, 106, 107, 107, 108, 109, + 109, 110, 110, 111, 111, 112, 112, 113, 113, 113, + 113, 114, 115, 113, 116, 116, 117, 117, 118, 118, + 118, 119, 119, 120, 120, 121, 121, 121, 121, 121, + 122, 122, 123, 123, 124, 124, 125, 126, 125, 127, + 127, 128, 128, 129, 130, 131, 129, 132, 133, 133, + 134, 134, 135, 135, 136, 136, 136, 136, 136, 137, + 137, 138, 138, 139, 139, 140, 141, 141, 142, 142, + 143, 143, 145, 144, 146, 146, 147, 147, 148, 148, + 149, 149, 151, 150, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 153, 153, 153, 154, 154, 155, 155, + 157, 156, 158, 158, 159, 159, 160, 161, 160, 162, + 162, 163, 163, 164, 164, 164, 165, 165, 166, 166, + 167, 167, 168, 168, 169, 170, 170 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 10, 11, 5, 5, 5, 5, 0, 5, + 0, 5, 0, 5, 1, 1, 1, 6, 0, 9, + 0, 5, 1, 3, 1, 5, 0, 5, 1, 3, + 1, 5, 0, 5, 1, 3, 0, 5, 1, 3, + 1, 5, 0, 5, 1, 3, 1, 5, 1, 1, + 0, 5, 0, 2, 1, 7, 2, 7, 0, 0, + 11, 9, 0, 1, 1, 3, 1, 3, 8, 1, + 1, 0, 2, 0, 7, 0, 2, 1, 4, 6, + 4, 0, 0, 10, 0, 1, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 4, 0, 2, 10, 0, 11, 0, + 7, 0, 1, 1, 0, 0, 10, 4, 1, 3, + 1, 4, 1, 3, 1, 1, 1, 6, 4, 0, + 7, 0, 1, 1, 8, 4, 1, 4, 1, 3, + 0, 2, 0, 9, 0, 15, 1, 3, 0, 4, + 3, 5, 0, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 3, 7, 1, 1, 0, 2, + 0, 6, 0, 3, 0, 2, 5, 0, 9, 1, + 3, 0, 3, 4, 4, 6, 1, 3, 1, 6, + 0, 2, 1, 2, 5, 1, 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 0, 0, 0, 0, 1, 98, 99, 97, 96, 95, + 0, 0, 0, 0, 18, 0, 0, 174, 50, 0, + 0, 20, 0, 0, 71, 0, 0, 8, 0, 26, + 0, 0, 0, 175, 52, 104, 0, 0, 0, 10, + 0, 0, 32, 2, 0, 0, 0, 0, 72, 140, + 0, 0, 0, 0, 0, 0, 0, 22, 24, 0, + 0, 36, 0, 0, 192, 177, 0, 0, 126, 0, + 0, 0, 0, 125, 53, 54, 124, 0, 0, 0, + 105, 168, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 28, 30, 0, 0, 42, 0, 0, + 193, 0, 51, 0, 0, 0, 62, 0, 0, 56, + 69, 70, 0, 0, 0, 141, 17, 5, 0, 0, + 0, 0, 12, 0, 21, 23, 0, 0, 0, 0, + 34, 0, 0, 0, 195, 0, 176, 0, 136, 0, + 58, 0, 63, 0, 0, 138, 0, 0, 0, 0, + 0, 169, 9, 0, 14, 16, 15, 0, 0, 0, + 0, 49, 48, 0, 0, 27, 29, 0, 0, 0, + 0, 38, 40, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 128, 0, 73, 0, 0, 170, + 11, 0, 0, 0, 0, 25, 0, 33, 35, 0, + 0, 0, 0, 0, 44, 46, 19, 194, 196, 181, + 179, 0, 0, 0, 102, 59, 100, 0, 66, 0, + 0, 139, 0, 0, 0, 0, 172, 6, 0, 0, + 3, 31, 0, 37, 39, 0, 0, 0, 0, 0, + 137, 127, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 142, 0, 7, 0, 0, 0, 43, + 45, 180, 0, 0, 0, 0, 178, 0, 101, 0, + 57, 67, 0, 64, 55, 68, 84, 109, 107, 144, + 0, 0, 13, 41, 0, 0, 0, 0, 182, 103, + 0, 0, 0, 91, 88, 93, 94, 89, 90, 0, + 92, 85, 75, 0, 0, 0, 77, 0, 129, 0, + 171, 173, 47, 0, 0, 188, 0, 186, 0, 0, + 61, 65, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 184, 0, 183, 0, 0, 0, 0, + 76, 0, 0, 86, 0, 81, 111, 106, 0, 0, + 143, 0, 0, 187, 0, 60, 78, 74, 0, 80, + 0, 0, 0, 0, 75, 112, 113, 131, 108, 159, + 156, 162, 161, 157, 158, 155, 160, 154, 0, 152, + 190, 185, 0, 87, 82, 0, 0, 0, 0, 0, + 75, 132, 133, 0, 163, 0, 0, 79, 0, 114, + 0, 0, 118, 120, 0, 0, 0, 0, 166, 167, + 0, 0, 153, 191, 189, 0, 0, 0, 117, 0, + 110, 0, 0, 0, 0, 0, 0, 0, 115, 0, + 119, 135, 0, 122, 130, 0, 0, 164, 0, 0, + 121, 0, 0, 0, 0, 83, 0, 0, 123, 0, + 0, 0, 0, 0, 146, 0, 0, 134, 148, 0, + 165, 116, 0, 0, 147, 0, 0, 0, 0, 145, + 149, 0, 0, 0, 150, 0, 151 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const short yydefgoto[] = +{ + -1, 2, 14, 20, 27, 87, 122, 39, 54, 160, + 157, 17, 18, 29, 56, 57, 42, 92, 93, 61, + 129, 97, 170, 171, 133, 203, 204, 163, 24, 46, + 74, 180, 244, 75, 143, 272, 217, 48, 112, 35, + 222, 324, 343, 361, 398, 302, 344, 303, 304, 305, + 76, 215, 216, 49, 80, 308, 307, 364, 365, 416, + 439, 366, 401, 402, 432, 306, 330, 390, 391, 392, + 145, 146, 81, 115, 279, 309, 453, 463, 467, 378, + 394, 379, 412, 410, 116, 151, 226, 254, 22, 33, + 101, 211, 238, 265, 316, 317, 396, 63, 64, 135 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -356 +static const short yypact[] = +{ + 9, -32, 35, 232, -356, -356, -356, -356, -356, -356, + -6, 13, 67, 20, 45, 53, 30, -356, 110, 46, + 118, 121, -12, 73, -356, 91, 84, 113, 112, 141, + 123, 128, 132, -356, -356, 175, 152, 161, 155, 191, + 2, 162, 180, -356, 204, 232, 214, 173, -356, 252, + 176, 206, 209, 213, 226, 232, 47, -356, -356, 80, + 218, 254, 224, -14, -356, -356, 230, 233, -356, 234, + 241, 232, 242, -356, -356, -356, 243, 237, 21, 244, + -356, 260, -356, 246, 245, 250, 251, 294, 247, 248, + 2, 232, 93, -356, -356, 232, 255, 272, 232, 253, + -356, 256, -356, 232, 257, 232, 290, 232, 232, -356, + -356, -356, 258, 21, 261, -356, 271, -356, 262, 264, + 14, 263, 317, 108, -356, -356, 265, 266, 80, 119, + -356, 85, 268, 312, -356, 124, -356, 270, 273, 269, + -356, 274, -356, 309, 275, -356, -52, 276, 277, 232, + 279, -356, -356, 281, -356, -356, -356, 284, 287, 288, + 321, -356, -356, 286, 108, -356, -356, 289, 232, 232, + 138, -356, -356, 156, 291, 293, 232, -17, 232, 232, + 232, 232, 346, 232, -356, 232, -356, 40, 296, -356, + -356, 297, 299, 302, 300, -356, 303, -356, -356, 285, + 301, 85, 232, 143, -356, -356, -356, -356, -356, -356, + -356, 337, 16, 304, 298, 306, -356, 32, -356, 311, + 305, -356, 56, 308, 314, 310, -356, -356, 315, 318, + -356, -356, 108, -356, -356, 313, 319, 156, -2, 320, + -356, -356, 232, 232, 316, 322, 232, 232, 323, 324, + 307, 325, 326, -356, 240, -356, 327, 329, 108, -356, + -356, -356, 331, 332, 334, 333, -356, 335, -356, 336, + -356, -356, 145, -356, -356, -356, 96, -356, -356, -356, + 338, 340, -356, -356, 342, 232, 163, 339, -356, -356, + 239, 343, 232, -356, -356, -356, -356, -356, -356, 344, + -356, -356, 341, 347, 348, 350, -356, 3, -356, -15, + -356, -356, -356, 42, 232, -356, 43, -356, 349, 351, + -356, -356, 96, 232, 352, 96, 96, 353, 355, 357, + 57, 358, 361, -356, 359, -356, 163, 108, 360, 362, + -356, 363, 364, -356, 44, -356, -13, -356, 366, 365, + -356, 168, 372, -356, 369, -356, -356, -356, 96, -356, + 96, 232, 371, 373, 341, -356, -356, 0, -356, -356, + -356, -356, -356, -356, -356, -356, -356, -356, 367, -356, + 370, -356, 375, -356, 306, 374, 228, 377, 379, 380, + 341, -356, -356, 50, 381, 376, 382, -356, 383, -356, + 384, 66, -356, -356, 386, 228, 387, 385, -356, -356, + 388, 7, -356, -356, -356, 389, 232, 239, -356, 228, + -356, 69, 239, 393, 232, 232, 90, 96, 306, 390, + -356, -356, 153, -356, -356, 391, 179, -356, 396, 395, + -356, 397, 239, 398, 401, -356, 402, 399, -356, 168, + 96, 409, 408, 185, -356, 410, 411, -356, 405, 168, + -356, -356, 400, 412, -356, 168, 413, 198, 345, -356, + -356, 168, 168, 394, -356, 168, -356 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const short yypgoto[] = +{ + -356, -356, -356, -356, -356, -356, -356, -356, -356, -356, + -356, -356, -356, -356, -356, 392, -356, -356, 259, -356, + -356, -356, -356, 202, -356, -356, 216, -152, -356, -356, + -356, -356, -356, -356, -356, -356, -356, -356, 267, -356, + -356, -340, -267, -356, -356, -356, 70, -356, -356, -356, + -3, -355, 235, -356, -356, -356, -356, -356, 87, -356, + -356, 33, 78, 68, -356, -45, -356, -356, 92, 39, + -101, 328, -356, -356, -356, -356, -356, -356, -356, -308, + -356, -356, -356, -356, -356, -356, -356, -356, -356, -356, + -356, -356, -356, -356, -356, 154, -356, -356, 425, 207 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, parse error. */ +#define YYTABLE_NINF -1 +static const unsigned short yytable[] = +{ + 10, 77, 139, 388, 331, 99, 384, 261, 30, 301, + 293, 328, 196, 184, 362, 1, 262, 185, 62, 31, + 5, 209, 329, 389, 387, 5, 110, 363, 67, 294, + 295, 68, 3, 111, 296, 4, 32, 58, 332, 263, + 297, 298, 65, 6, 299, 264, 210, 300, 6, 7, + 407, 223, 88, 388, 7, 339, 94, 224, 342, 11, + 154, 428, 8, 73, 9, 348, 55, 8, 106, 9, + 436, 155, 156, 389, 425, 249, 349, 362, 213, 12, + 257, 240, 250, 13, 221, 185, 15, 58, 126, 19, + 363, 382, 130, 383, 16, 134, 21, 245, 5, 293, + 138, 246, 141, 5, 144, 138, 284, 333, 335, 359, + 25, 176, 336, 360, 5, 89, 90, 67, 294, 295, + 68, 6, 26, 296, 23, 94, 6, 7, 172, 297, + 298, 418, 7, 299, 431, 419, 300, 6, 419, 34, + 8, 454, 9, 7, 91, 8, 188, 9, 37, 169, + 28, 464, 73, 281, 36, 437, 8, 468, 9, 360, + 438, 127, 128, 473, 474, 198, 199, 476, 161, 162, + 205, 369, 38, 208, 5, 138, 138, 214, 218, 40, + 220, 5, 138, 455, 41, 354, 5, 167, 168, 43, + 370, 371, 175, 176, 44, 372, 45, 6, 172, 235, + 47, 373, 374, 7, 6, 375, 200, 201, 376, 6, + 7, 236, 237, 291, 292, 7, 8, 50, 9, 52, + 202, 441, 442, 8, 51, 9, 53, 314, 8, 59, + 9, 60, 5, 66, 205, 67, 62, 78, 68, 267, + 214, 69, 82, 271, 273, 319, 5, 444, 243, 67, + 5, 138, 68, 458, 459, 6, 70, 5, 5, 280, + 67, 7, 79, 68, 71, 400, 470, 471, 72, 6, + 73, 83, 84, 6, 8, 7, 9, 85, 86, 7, + 6, 6, 134, 315, 73, 95, 7, 7, 8, 321, + 9, 98, 8, 96, 9, 73, 102, 103, 104, 8, + 8, 9, 9, 109, 114, 105, 107, 108, 113, 121, + 118, 334, 117, 119, 124, 120, 123, 132, 142, 136, + 340, 137, 131, 147, 140, 149, 150, 158, 152, 153, + 159, 174, 165, 315, 164, 173, 177, 178, 179, 182, + 194, 403, 186, 181, 183, 189, 187, 190, 377, 191, + 192, 195, 193, 219, 232, 197, 239, 206, 214, 207, + 403, 225, 242, 227, 228, 229, 230, 233, 231, 241, + 248, 276, 429, 251, 403, 243, 253, 433, 247, 252, + 148, 255, 258, 256, 269, 259, 266, 166, 270, 274, + 275, 277, 278, 282, 283, 285, 286, 448, 287, 288, + 289, 318, 388, 234, 310, 290, 311, 312, 322, 320, + 323, 325, 326, 214, 327, 472, 338, 341, 337, 346, + 345, 435, 214, 347, 350, 351, 355, 356, 352, 357, + 367, 368, 380, 358, 381, 385, 393, 386, 413, 395, + 397, 399, 404, 405, 406, 411, 377, 414, 417, 363, + 423, 415, 420, 260, 422, 440, 377, 424, 427, 434, + 443, 445, 377, 446, 475, 449, 447, 465, 377, 377, + 450, 451, 377, 457, 462, 460, 461, 466, 268, 469, + 408, 426, 125, 421, 456, 409, 452, 430, 100, 0, + 353, 0, 313, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 212 +}; + +static const short yycheck[] = +{ + 3, 46, 103, 3, 19, 19, 361, 9, 20, 276, + 3, 8, 164, 65, 27, 6, 18, 69, 32, 31, + 18, 38, 19, 23, 364, 18, 5, 40, 21, 22, + 23, 24, 64, 12, 27, 0, 48, 40, 53, 41, + 33, 34, 45, 41, 37, 47, 63, 40, 41, 47, + 390, 11, 55, 3, 47, 322, 59, 17, 325, 65, + 46, 416, 60, 56, 62, 8, 64, 60, 71, 62, + 425, 57, 58, 23, 67, 19, 19, 27, 179, 66, + 232, 65, 26, 16, 185, 69, 66, 90, 91, 36, + 40, 358, 95, 360, 49, 98, 66, 65, 18, 3, + 103, 69, 105, 18, 107, 108, 258, 65, 65, 65, + 64, 69, 69, 69, 18, 68, 69, 21, 22, 23, + 24, 41, 4, 27, 14, 128, 41, 47, 131, 33, + 34, 65, 47, 37, 65, 69, 40, 41, 69, 66, + 60, 449, 62, 47, 64, 60, 149, 62, 64, 64, + 29, 459, 56, 254, 63, 65, 60, 465, 62, 69, + 427, 68, 69, 471, 472, 168, 169, 475, 60, 61, + 173, 3, 59, 176, 18, 178, 179, 180, 181, 67, + 183, 18, 185, 450, 43, 337, 18, 68, 69, 66, + 22, 23, 68, 69, 66, 27, 64, 41, 201, 202, + 25, 33, 34, 47, 41, 37, 68, 69, 40, 41, + 47, 68, 69, 68, 69, 47, 60, 65, 62, 64, + 64, 68, 69, 60, 63, 62, 35, 64, 60, 67, + 62, 51, 18, 19, 237, 21, 32, 64, 24, 242, + 243, 27, 66, 246, 247, 290, 18, 68, 69, 21, + 18, 254, 24, 68, 69, 41, 42, 18, 18, 19, + 21, 47, 10, 24, 50, 37, 68, 69, 54, 41, + 56, 65, 63, 41, 60, 47, 62, 64, 52, 47, + 41, 41, 285, 286, 56, 67, 47, 47, 60, 292, + 62, 67, 60, 39, 62, 56, 66, 64, 64, 60, + 60, 62, 62, 66, 44, 64, 64, 64, 64, 15, + 65, 314, 66, 63, 66, 64, 69, 45, 28, 66, + 323, 65, 67, 65, 67, 64, 55, 64, 66, 65, + 13, 19, 66, 336, 69, 67, 66, 64, 69, 30, + 19, 386, 66, 69, 69, 66, 69, 66, 351, 65, + 63, 65, 64, 7, 69, 66, 19, 66, 361, 66, + 405, 65, 64, 66, 65, 63, 66, 66, 65, 65, + 65, 64, 417, 65, 419, 69, 66, 422, 67, 65, + 113, 66, 69, 65, 68, 66, 66, 128, 66, 66, + 66, 66, 66, 66, 65, 64, 64, 442, 64, 66, + 65, 62, 3, 201, 66, 69, 66, 65, 64, 66, + 69, 64, 64, 416, 64, 70, 65, 65, 69, 64, + 67, 424, 425, 66, 66, 64, 66, 65, 69, 66, + 64, 66, 60, 69, 65, 64, 69, 64, 62, 69, + 65, 67, 65, 64, 64, 64, 449, 65, 64, 40, + 65, 68, 66, 237, 67, 65, 459, 69, 69, 66, + 69, 65, 465, 68, 70, 67, 69, 67, 471, 472, + 69, 69, 475, 65, 69, 65, 65, 65, 243, 66, + 393, 411, 90, 405, 451, 393, 447, 419, 63, -1, + 336, -1, 285, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 178 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 6, 72, 64, 0, 18, 41, 47, 60, 62, + 121, 65, 66, 16, 73, 66, 49, 82, 83, 36, + 74, 66, 159, 14, 99, 64, 4, 75, 29, 84, + 20, 31, 48, 160, 66, 110, 63, 64, 59, 78, + 67, 43, 87, 66, 66, 64, 100, 25, 108, 124, + 65, 63, 64, 35, 79, 64, 85, 86, 121, 67, + 51, 90, 32, 168, 169, 121, 19, 21, 24, 27, + 42, 50, 54, 56, 101, 104, 121, 136, 64, 10, + 125, 143, 66, 65, 63, 64, 52, 76, 121, 68, + 69, 64, 88, 89, 121, 67, 39, 92, 67, 19, + 169, 161, 66, 64, 64, 64, 121, 64, 64, 66, + 5, 12, 109, 64, 44, 144, 155, 66, 65, 63, + 64, 15, 77, 69, 66, 86, 121, 68, 69, 91, + 121, 67, 45, 95, 121, 170, 66, 65, 121, 141, + 67, 121, 28, 105, 121, 141, 142, 65, 109, 64, + 55, 156, 66, 65, 46, 57, 58, 81, 64, 13, + 80, 60, 61, 98, 69, 66, 89, 68, 69, 64, + 93, 94, 121, 67, 19, 68, 69, 66, 64, 69, + 102, 69, 30, 69, 65, 69, 66, 69, 121, 66, + 66, 65, 63, 64, 19, 65, 98, 66, 121, 121, + 68, 69, 64, 96, 97, 121, 66, 66, 121, 38, + 63, 162, 142, 141, 121, 122, 123, 107, 121, 7, + 121, 141, 111, 11, 17, 65, 157, 66, 65, 63, + 66, 65, 69, 66, 94, 121, 68, 69, 163, 19, + 65, 65, 64, 69, 103, 65, 69, 67, 65, 19, + 26, 65, 65, 66, 158, 66, 65, 98, 69, 66, + 97, 9, 18, 41, 47, 164, 66, 121, 123, 68, + 66, 121, 106, 121, 66, 66, 64, 66, 66, 145, + 19, 141, 66, 65, 98, 64, 64, 64, 66, 65, + 69, 68, 69, 3, 22, 23, 27, 33, 34, 37, + 40, 113, 116, 118, 119, 120, 136, 127, 126, 146, + 66, 66, 65, 170, 64, 121, 165, 166, 62, 136, + 66, 121, 64, 69, 112, 64, 64, 64, 8, 19, + 137, 19, 53, 65, 121, 65, 69, 69, 65, 113, + 121, 65, 113, 113, 117, 67, 64, 66, 8, 19, + 66, 64, 69, 166, 98, 66, 65, 66, 69, 65, + 69, 114, 27, 40, 128, 129, 132, 64, 66, 3, + 22, 23, 27, 33, 34, 37, 40, 121, 150, 152, + 60, 65, 113, 113, 122, 64, 64, 112, 3, 23, + 138, 139, 140, 69, 151, 69, 167, 65, 115, 67, + 37, 133, 134, 136, 65, 64, 64, 112, 129, 139, + 154, 64, 153, 62, 65, 68, 130, 64, 65, 69, + 66, 133, 67, 65, 69, 67, 117, 69, 122, 136, + 134, 65, 135, 136, 66, 121, 122, 65, 113, 131, + 65, 68, 69, 69, 68, 65, 68, 69, 136, 67, + 69, 69, 140, 147, 150, 113, 132, 65, 68, 69, + 65, 65, 69, 148, 150, 67, 65, 149, 150, 66, + 68, 69, 70, 150, 150, 70, 150 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up"); \ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.first_line = Rhs[1].first_line; \ + Current.first_column = Rhs[1].first_column; \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#define YYLEX yylex () + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +#endif /* !YYDEBUG */ + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*-----------------------------. +| Print this symbol on YYOUT. | +`-----------------------------*/ + +static void +#if defined (__STDC__) || defined (__cplusplus) +yysymprint (FILE* yyout, int yytype, YYSTYPE yyvalue) +#else +yysymprint (yyout, yytype, yyvalue) + FILE* yyout; + int yytype; + YYSTYPE yyvalue; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvalue; + + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyout, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyout, yytoknum[yytype], yyvalue); +# endif + } + else + YYFPRINTF (yyout, "nterm %s (", yytname[yytype]); + + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyout, ")"); +} +#endif /* YYDEBUG. */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +#if defined (__STDC__) || defined (__cplusplus) +yydestruct (int yytype, YYSTYPE yyvalue) +#else +yydestruct (yytype, yyvalue) + int yytype; + YYSTYPE yyvalue; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvalue; + + switch (yytype) + { + default: + break; + } +} + + + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +# define YYPARSE_PARAM_DECL +# else +# define YYPARSE_PARAM_ARG YYPARSE_PARAM +# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +# endif +#else /* !YYPARSE_PARAM */ +# define YYPARSE_PARAM_ARG +# define YYPARSE_PARAM_DECL +#endif /* !YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +# ifdef YYPARSE_PARAM +int yyparse (void *); +# else +int yyparse (void); +# endif +#endif + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of parse errors so far. */ +int yynerrs; + + +int +yyparse (YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yychar1 = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + goto yyoverflowlab; + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with. */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more. */ + + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yychar1 = YYTRANSLATE (yychar); + + /* We have to keep this `#if YYDEBUG', since we use variables + which are defined only if `YYDEBUG' is set. */ + YYDPRINTF ((stderr, "Next token is ")); + YYDSYMPRINT ((stderr, yychar1, yylval)); + YYDPRINTF ((stderr, "\n")); + } + + /* If the proper action on seeing token YYCHAR1 is to reduce or to + detect an error, take that action. */ + yyn += yychar1; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yychar1) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %d (%s), ", + yychar, yytname[yychar1])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables which + are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + int yyi; + + YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", + yyn - 1, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyn]; yyrhs[yyi] >= 0; yyi++) + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + switch (yyn) + { + case 2: +#line 210 "dfgparser.y" + { string_StringFree(yyvsp[-7].string); + YYACCEPT; /* Stop immediately */ } + break; + + case 4: +#line 230 "dfgparser.y" + { dfg_DESC.name = yyvsp[-2].string; } + break; + + case 5: +#line 234 "dfgparser.y" + { dfg_DESC.author = yyvsp[-2].string; } + break; + + case 6: +#line 238 "dfgparser.y" + { dfg_DESC.status = yyvsp[-2].state; } + break; + + case 7: +#line 242 "dfgparser.y" + { dfg_DESC.description = yyvsp[-2].string; } + break; + + case 9: +#line 247 "dfgparser.y" + { dfg_DESC.version = yyvsp[-2].string; } + break; + + case 11: +#line 252 "dfgparser.y" + { dfg_DESC.logic = yyvsp[-2].string; } + break; + + case 13: +#line 257 "dfgparser.y" + { dfg_DESC.date = yyvsp[-2].string; } + break; + + case 14: +#line 260 "dfgparser.y" + { yyval.state = DFG_SATISFIABLE; } + break; + + case 15: +#line 261 "dfgparser.y" + { yyval.state = DFG_UNSATISFIABLE; } + break; + + case 16: +#line 262 "dfgparser.y" + { yyval.state = DFG_UNKNOWNSTATE; } + break; + + case 24: +#line 299 "dfgparser.y" + { dfg_SymbolDecl(DFG_FUNC, yyvsp[0].string, -2); } + break; + + case 25: +#line 301 "dfgparser.y" + { dfg_SymbolDecl(DFG_FUNC, yyvsp[-3].string, yyvsp[-1].number); } + break; + + case 30: +#line 312 "dfgparser.y" + { dfg_SymbolDecl(DFG_PRDICAT, yyvsp[0].string, -2); } + break; + + case 31: +#line 313 "dfgparser.y" + { dfg_SymbolDecl(DFG_PRDICAT, yyvsp[-3].string, yyvsp[-1].number); } + break; + + case 34: +#line 320 "dfgparser.y" + { dfg_SymbolDecl(DFG_PRDICAT, yyvsp[0].string, 1); } + break; + + case 35: +#line 321 "dfgparser.y" + { dfg_SymbolDecl(DFG_PRDICAT, yyvsp[0].string, 1); } + break; + + case 40: +#line 332 "dfgparser.y" + { dfg_SymbolDecl(DFG_OPERAT, yyvsp[0].string, -2); } + break; + + case 41: +#line 333 "dfgparser.y" + { dfg_SymbolDecl(DFG_OPERAT, yyvsp[-3].string, yyvsp[-1].number); } + break; + + case 46: +#line 344 "dfgparser.y" + { dfg_SymbolDecl(DFG_QUANTIF, yyvsp[0].string, -2); } + break; + + case 47: +#line 345 "dfgparser.y" + { dfg_SymbolDecl(DFG_QUANTIF, yyvsp[-3].string, yyvsp[-1].number); } + break; + + case 48: +#line 348 "dfgparser.y" + { yyval.number = -1; } + break; + + case 49: +#line 349 "dfgparser.y" + { yyval.number = yyvsp[0].number; } + break; + + case 55: +#line 368 "dfgparser.y" + { dfg_SubSort(yyvsp[-4].string,yyvsp[-2].string); } + break; + + case 56: +#line 369 "dfgparser.y" + { dfg_SORTDECLLIST = list_Nconc(dfg_SORTDECLLIST,list_List(list_PairCreate(NULL,yyvsp[-1].term))); } + break; + + case 57: +#line 371 "dfgparser.y" + { string_StringFree(yyvsp[-4].string); } + break; + + case 58: +#line 372 "dfgparser.y" + { dfg_VarStart(); } + break; + + case 59: +#line 373 "dfgparser.y" + { dfg_VarStop(); } + break; + + case 60: +#line 374 "dfgparser.y" + { TERM term; + dfg_VarBacktrack(); + dfg_VarCheck(); + term = dfg_CreateQuantifier(fol_All(),yyvsp[-6].list,yyvsp[-2].term); + dfg_SORTDECLLIST = list_Nconc(dfg_SORTDECLLIST,list_List(list_PairCreate(NULL,term))); + } + break; + + case 61: +#line 383 "dfgparser.y" + { dfg_SymbolGenerated(dfg_Symbol(yyvsp[-7].string,1), yyvsp[-6].bool, yyvsp[-2].list); } + break; + + case 62: +#line 386 "dfgparser.y" + { yyval.bool = FALSE; } + break; + + case 63: +#line 387 "dfgparser.y" + { yyval.bool = TRUE; } + break; + + case 64: +#line 390 "dfgparser.y" + { yyval.list = list_List(yyvsp[0].string); } + break; + + case 65: +#line 391 "dfgparser.y" + { yyval.list = list_Cons(yyvsp[0].string, yyvsp[-2].list); } + break; + + case 66: +#line 394 "dfgparser.y" + { string_StringFree(yyvsp[0].string); } + break; + + case 67: +#line 395 "dfgparser.y" + { string_StringFree(yyvsp[0].string); } + break; + + case 68: +#line 404 "dfgparser.y" + { list_NReverse(yyvsp[-2].list); + if (yyvsp[-5].bool) /* Axioms */ + dfg_AXIOMLIST = list_Nconc(dfg_AXIOMLIST, yyvsp[-2].list); + else + dfg_CONJECLIST = list_Nconc(dfg_CONJECLIST, yyvsp[-2].list); + } + break; + + case 69: +#line 412 "dfgparser.y" + { yyval.bool = TRUE; } + break; + + case 70: +#line 413 "dfgparser.y" + { yyval.bool = FALSE; } + break; + + case 73: +#line 420 "dfgparser.y" + { yyval.list = list_Nil(); } + break; + + case 74: +#line 422 "dfgparser.y" + { LIST pair; + if (yyvsp[-3].term == NULL) { /* No term */ + if (yyvsp[-2].string != NULL) + string_StringFree(yyvsp[-2].string); + yyval.list = yyvsp[-6].list; + } else { + pair = list_PairCreate(yyvsp[-2].string, yyvsp[-3].term); + yyval.list = list_Cons(pair, yyvsp[-6].list); + } + dfg_VarCheck(); + } + break; + + case 75: +#line 435 "dfgparser.y" + { yyval.string = NULL; } + break; + + case 76: +#line 436 "dfgparser.y" + { yyval.string = yyvsp[0].string; } + break; + + case 77: +#line 439 "dfgparser.y" + { yyval.term = yyvsp[0].term; } + break; + + case 78: +#line 441 "dfgparser.y" + { yyval.term = dfg_IGNORE ? NULL : term_Create(fol_Not(),list_List(yyvsp[-1].term)); } + break; + + case 79: +#line 443 "dfgparser.y" + { yyval.term = dfg_IGNORE ? NULL : term_Create(yyvsp[-5].symbol, list_Cons(yyvsp[-3].term, list_List(yyvsp[-1].term))); } + break; + + case 80: +#line 445 "dfgparser.y" + { yyval.term = dfg_IGNORE ? NULL : term_Create(yyvsp[-3].symbol, yyvsp[-1].list); } + break; + + case 81: +#line 446 "dfgparser.y" + { dfg_VarStart(); } + break; + + case 82: +#line 447 "dfgparser.y" + { dfg_VarStop(); } + break; + + case 83: +#line 449 "dfgparser.y" + { dfg_VarBacktrack(); + yyval.term = dfg_IGNORE ? NULL : dfg_CreateQuantifier(yyvsp[-9].symbol,yyvsp[-5].list,yyvsp[-1].term); + } + break; + + case 84: +#line 454 "dfgparser.y" + { yyval.term = NULL; } + break; + + case 85: +#line 455 "dfgparser.y" + { yyval.term = yyvsp[0].term; } + break; + + case 86: +#line 459 "dfgparser.y" + { yyval.list = dfg_IGNORE ? list_Nil() : list_List(yyvsp[0].term); } + break; + + case 87: +#line 461 "dfgparser.y" + { yyval.list = dfg_IGNORE ? yyvsp[-2].list : list_Nconc(yyvsp[-2].list, list_List(yyvsp[0].term)); } + break; + + case 88: +#line 464 "dfgparser.y" + { yyval.symbol = fol_Equiv(); } + break; + + case 89: +#line 465 "dfgparser.y" + { yyval.symbol = fol_Implied(); } + break; + + case 90: +#line 466 "dfgparser.y" + { yyval.symbol = fol_Implies(); } + break; + + case 91: +#line 469 "dfgparser.y" + { yyval.symbol = fol_And(); } + break; + + case 92: +#line 470 "dfgparser.y" + { yyval.symbol = fol_Or(); } + break; + + case 93: +#line 473 "dfgparser.y" + { yyval.symbol = fol_Exist(); } + break; + + case 94: +#line 474 "dfgparser.y" + { yyval.symbol = fol_All(); } + break; + + case 95: +#line 477 "dfgparser.y" + { if (dfg_IGNORE) { + string_StringFree(yyvsp[0].string); + yyval.string = NULL; + } else + yyval.string = yyvsp[0].string; + } + break; + + case 96: +#line 484 "dfgparser.y" + { yyval.string = dfg_IGNORE ? NULL : string_IntToString(yyvsp[0].number); } + break; + + case 97: +#line 486 "dfgparser.y" + { yyval.string = dfg_IGNORE ? NULL : string_StringCopy("set_flag"); } + break; + + case 98: +#line 488 "dfgparser.y" + { yyval.string = dfg_IGNORE ? NULL : string_StringCopy("set_DomPred"); } + break; + + case 99: +#line 490 "dfgparser.y" + { yyval.string = dfg_IGNORE ? NULL : string_StringCopy("set_precedence"); } + break; + + case 100: +#line 494 "dfgparser.y" + { yyval.list = dfg_IGNORE ? list_Nil() : list_List(yyvsp[0].term); } + break; + + case 101: +#line 496 "dfgparser.y" + { yyval.list = dfg_IGNORE ? yyvsp[-2].list : list_Nconc(yyvsp[-2].list, list_List(yyvsp[0].term)); } + break; + + case 102: +#line 500 "dfgparser.y" + { if (!dfg_IGNORE) { + SYMBOL s = dfg_Symbol(yyvsp[0].string,0); + if (!symbol_IsVariable(s)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: Symbol is not a variable.\n",dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + yyval.term = term_Create(s, list_Nil()); + } + } + break; + + case 103: +#line 511 "dfgparser.y" + { if (!dfg_IGNORE) { + SYMBOL p, v; + p = dfg_Symbol(yyvsp[-3].string, 1); + if (!symbol_IsPredicate(p)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: Symbol is not a predicate.\n",dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + v = dfg_Symbol(yyvsp[-1].string, 0); + if (!symbol_IsVariable(v)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: Symbol is not a variable.\n",dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + yyval.term = term_Create(p, list_List(term_Create(v,list_Nil()))); + } + } + break; + + case 106: +#line 541 "dfgparser.y" + { list_NReverse(yyvsp[-2].list); + if (yyvsp[-7].bool) /* Axioms */ + dfg_AXCLAUSES = list_Nconc(dfg_AXCLAUSES, yyvsp[-2].list); + else + dfg_CONCLAUSES = list_Nconc(dfg_CONCLAUSES, yyvsp[-2].list); + } + break; + + case 107: +#line 548 "dfgparser.y" + { stack_Push((POINTER)dfg_IGNORE); dfg_IGNORE = TRUE; } + break; + + case 108: +#line 551 "dfgparser.y" + { dfg_IGNORE = (BOOL)stack_PopResult(); } + break; + + case 109: +#line 554 "dfgparser.y" + { yyval.list = list_Nil(); } + break; + + case 110: +#line 556 "dfgparser.y" + { LIST pair; + if (yyvsp[-3].term == NULL) { /* No clause */ + if (yyvsp[-2].string != NULL) + string_StringFree(yyvsp[-2].string); + yyval.list = yyvsp[-6].list; + } else { + pair = list_PairCreate(yyvsp[-2].string, yyvsp[-3].term); + yyval.list = list_Cons(pair, yyvsp[-6].list); + } + dfg_VarCheck(); + } + break; + + case 111: +#line 569 "dfgparser.y" + { yyval.term = NULL; } + break; + + case 112: +#line 570 "dfgparser.y" + { yyval.term = yyvsp[0].term; } + break; + + case 113: +#line 573 "dfgparser.y" + { yyval.term = yyvsp[0].term; } + break; + + case 114: +#line 574 "dfgparser.y" + { dfg_VarStart(); } + break; + + case 115: +#line 575 "dfgparser.y" + { dfg_VarStop(); } + break; + + case 116: +#line 577 "dfgparser.y" + { dfg_VarBacktrack(); + yyval.term = dfg_IGNORE ? NULL : dfg_CreateQuantifier(fol_All(),yyvsp[-5].list,yyvsp[-1].term); + } + break; + + case 117: +#line 583 "dfgparser.y" + { yyval.term = dfg_IGNORE ? NULL : term_Create(fol_Or(), yyvsp[-1].list); } + break; + + case 118: +#line 587 "dfgparser.y" + { yyval.list = dfg_IGNORE ? list_Nil() : list_List(yyvsp[0].term); } + break; + + case 119: +#line 589 "dfgparser.y" + { yyval.list = dfg_IGNORE ? yyvsp[-2].list : list_Nconc(yyvsp[-2].list, list_List(yyvsp[0].term)); } + break; + + case 120: +#line 592 "dfgparser.y" + { yyval.term = yyvsp[0].term; } + break; + + case 121: +#line 594 "dfgparser.y" + { yyval.term = dfg_IGNORE ? yyvsp[-1].term : term_Create(fol_Not(),list_List(yyvsp[-1].term)); } + break; + + case 122: +#line 597 "dfgparser.y" + { yyval.list = list_List(yyvsp[0].term); } + break; + + case 123: +#line 598 "dfgparser.y" + { yyval.list = list_Nconc(yyvsp[-2].list, list_List(yyvsp[0].term)); } + break; + + case 124: +#line 602 "dfgparser.y" + { yyval.term = dfg_IGNORE ? NULL : dfg_AtomCreate(yyvsp[0].string,list_Nil()); } + break; + + case 125: +#line 604 "dfgparser.y" + { yyval.term = dfg_IGNORE ? NULL : term_Create(fol_True(),list_Nil()); } + break; + + case 126: +#line 606 "dfgparser.y" + { yyval.term = dfg_IGNORE ? NULL : term_Create(fol_False(),list_Nil()); } + break; + + case 127: +#line 608 "dfgparser.y" + { yyval.term = dfg_IGNORE ? NULL : term_Create(fol_Equality(),list_Cons(yyvsp[-3].term,list_List(yyvsp[-1].term))); } + break; + + case 128: +#line 610 "dfgparser.y" + { yyval.term = dfg_IGNORE ? NULL : dfg_AtomCreate(yyvsp[-3].string, yyvsp[-1].list); } + break; + + case 136: +#line 636 "dfgparser.y" + { yyval.term = dfg_IGNORE ? NULL : dfg_TermCreate(yyvsp[0].string,list_Nil()); } + break; + + case 137: +#line 638 "dfgparser.y" + { yyval.term = dfg_IGNORE ? NULL : dfg_TermCreate(yyvsp[-3].string, yyvsp[-1].list); } + break; + + case 138: +#line 642 "dfgparser.y" + { yyval.list = dfg_IGNORE ? list_Nil() : list_List(yyvsp[0].term); } + break; + + case 139: +#line 644 "dfgparser.y" + { yyval.list = dfg_IGNORE ? yyvsp[-2].list : list_Nconc(yyvsp[-2].list,list_List(yyvsp[0].term)); } + break; + + case 142: +#line 656 "dfgparser.y" + { if (!string_Equal(yyvsp[-2].string,"SPASS")) { + stack_Push((POINTER)dfg_IGNORE); + dfg_IGNORE = TRUE; + } + } + break; + + case 143: +#line 663 "dfgparser.y" + { if (!string_Equal(yyvsp[-6].string,"SPASS")) + dfg_IGNORE = (BOOL)stack_PopResult(); + string_StringFree(yyvsp[-6].string); + } + break; + + case 145: +#line 672 "dfgparser.y" + { if (!dfg_IGNORE && yyvsp[-11].string!=NULL && yyvsp[-9].term!=NULL && !list_Empty(yyvsp[-4].list)) { + LIST tupel; + RULE Rule = clause_GetOriginFromString(yyvsp[-7].string); + string_StringFree(yyvsp[-7].string); + /* Build a tuple (label,clause,parentlist,split level,origin) */ + tupel = list_Cons((POINTER)yyvsp[-2].number,list_List((POINTER)Rule)); + tupel = list_Cons(yyvsp[-11].string,list_Cons(yyvsp[-9].term,list_Cons(yyvsp[-4].list,tupel))); + dfg_PROOFLIST = list_Cons(tupel, dfg_PROOFLIST); + } else { + /* ignore DNF clauses and clauses with incomplete data */ + if (yyvsp[-11].string != NULL) string_StringFree(yyvsp[-11].string); + if (yyvsp[-9].term != NULL) term_Delete(yyvsp[-9].term); + if (yyvsp[-7].string != NULL) string_StringFree(yyvsp[-7].string); + dfg_DeleteStringList(yyvsp[-4].list); + } + dfg_VarCheck(); + } + break; + + case 146: +#line 692 "dfgparser.y" + { yyval.list = (dfg_IGNORE||yyvsp[0].string==NULL) ? list_Nil() : list_List(yyvsp[0].string); } + break; + + case 147: +#line 694 "dfgparser.y" + { yyval.list = (dfg_IGNORE||yyvsp[0].string==NULL) ? yyvsp[-2].list : list_Nconc(yyvsp[-2].list, list_List(yyvsp[0].string)); } + break; + + case 148: +#line 698 "dfgparser.y" + { yyval.number = 0; } + break; + + case 149: +#line 699 "dfgparser.y" + { yyval.number = yyvsp[-1].number; } + break; + + case 150: +#line 703 "dfgparser.y" + { if (!dfg_IGNORE && yyvsp[-2].string!=NULL && yyvsp[0].string!=NULL && string_Equal(yyvsp[-2].string,"splitlevel")) + string_StringToInt(yyvsp[0].string, TRUE, &yyval.number); + else + yyval.number = 0; + if (yyvsp[-2].string != NULL) string_StringFree(yyvsp[-2].string); + if (yyvsp[0].string != NULL) string_StringFree(yyvsp[0].string); + } + break; + + case 151: +#line 711 "dfgparser.y" + { if (!dfg_IGNORE && yyvsp[-2].string!=NULL && yyvsp[0].string!=NULL && string_Equal(yyvsp[-2].string,"splitlevel")) + string_StringToInt(yyvsp[0].string, TRUE, &yyval.number); + else + yyval.number = yyvsp[-4].number; + if (yyvsp[-2].string != NULL) string_StringFree(yyvsp[-2].string); + if (yyvsp[0].string != NULL) string_StringFree(yyvsp[0].string); + } + break; + + case 152: +#line 721 "dfgparser.y" + { stack_Push((POINTER) dfg_IGNORE); dfg_IGNORE = TRUE; } + break; + + case 153: +#line 723 "dfgparser.y" + { dfg_IGNORE = (BOOL) stack_PopResult(); + if (yyvsp[0].bool) { + if (yyvsp[-2].string != NULL) string_StringFree(yyvsp[-2].string); + yyval.string = NULL; + } else + yyval.string = yyvsp[-2].string; + } + break; + + case 154: +#line 732 "dfgparser.y" + { yyval.string = yyvsp[0].string; } + break; + + case 155: +#line 733 "dfgparser.y" + { yyval.string = NULL; } + break; + + case 156: +#line 734 "dfgparser.y" + { yyval.string = NULL; } + break; + + case 157: +#line 735 "dfgparser.y" + { yyval.string = NULL; } + break; + + case 158: +#line 736 "dfgparser.y" + { yyval.string = NULL; } + break; + + case 159: +#line 737 "dfgparser.y" + { yyval.string = NULL; } + break; + + case 160: +#line 738 "dfgparser.y" + { yyval.string = NULL; } + break; + + case 161: +#line 739 "dfgparser.y" + { yyval.string = NULL; } + break; + + case 162: +#line 740 "dfgparser.y" + { yyval.string = NULL; } + break; + + case 163: +#line 743 "dfgparser.y" + { yyval.bool = FALSE; } + break; + + case 164: +#line 744 "dfgparser.y" + { yyval.bool = TRUE; } + break; + + case 165: +#line 745 "dfgparser.y" + { yyval.bool = TRUE; } + break; + + case 166: +#line 748 "dfgparser.y" + { yyval.term = yyvsp[0].term; } + break; + + case 167: +#line 749 "dfgparser.y" + { yyval.term = NULL; } + break; + + case 170: +#line 761 "dfgparser.y" + { dfg_VarStart(); } + break; + + case 171: +#line 762 "dfgparser.y" + { + dfg_VarStop(); + dfg_VarBacktrack(); + dfg_VarCheck(); } + break; + + case 173: +#line 769 "dfgparser.y" + { dfg_TERMLIST = list_Nconc(dfg_TERMLIST, list_List(yyvsp[-1].term)); } + break; + + case 177: +#line 781 "dfgparser.y" + { if (string_Equal(yyvsp[0].string,"SPASS")) + dfg_IGNORETEXT = FALSE; + string_StringFree(yyvsp[0].string); + } + break; + + case 178: +#line 786 "dfgparser.y" + { dfg_IGNORETEXT = TRUE; } + break; + + case 179: +#line 789 "dfgparser.y" + { /* no SPASS flags */ + string_StringFree(yyvsp[0].string); + } + break; + + case 184: +#line 801 "dfgparser.y" + { SYMBOL s; + for ( ; !list_Empty(yyvsp[-1].list); yyvsp[-1].list = list_Pop(yyvsp[-1].list)) { + s = symbol_Lookup(list_Car(yyvsp[-1].list)); + if (s == 0) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Undefined symbol %s", list_Car(yyvsp[-1].list)); + misc_UserErrorReport(" in DomPred list.\n"); + misc_FinishUserErrorReport(); + } + if (!symbol_IsPredicate(s)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Symbol %s isn't a predicate", list_Car(yyvsp[-1].list)); + misc_UserErrorReport(" in DomPred list.\n"); + misc_FinishUserErrorReport(); + } + string_StringFree(list_Car(yyvsp[-1].list)); + symbol_AddProperty(s, DOMPRED); + } + } + break; + + case 185: +#line 821 "dfgparser.y" + { int flag = flag_Id(yyvsp[-3].string); + if (flag == -1) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Found unknown flag %s", yyvsp[-3].string); + misc_FinishUserErrorReport(); + } + string_StringFree(yyvsp[-3].string); + flag_SetFlagValue(dfg_FLAGS, flag, yyvsp[-1].number); + } + break; + + case 188: +#line 837 "dfgparser.y" + { SYMBOL s = symbol_Lookup(yyvsp[0].string); + if (s == 0) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Undefined symbol %s ", yyvsp[0].string); + misc_UserErrorReport(" in precedence list.\n"); + misc_FinishUserErrorReport(); + } + string_StringFree(yyvsp[0].string); + symbol_SetIncreasedOrdering(dfg_PRECEDENCE, s); + dfg_USERPRECEDENCE = list_Cons((POINTER)s, dfg_USERPRECEDENCE); + } + break; + + case 189: +#line 849 "dfgparser.y" + { SYMBOL s = symbol_Lookup(yyvsp[-4].string); + if (s == 0) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Undefined symbol %s", yyvsp[-4].string); + misc_UserErrorReport("in precedence list.\n"); + misc_FinishUserErrorReport(); + } + string_StringFree(yyvsp[-4].string); + symbol_SetIncreasedOrdering(dfg_PRECEDENCE, s); + dfg_USERPRECEDENCE = list_Cons((POINTER)s, dfg_USERPRECEDENCE); + symbol_SetWeight(s, yyvsp[-2].number); + if (yyvsp[-1].property != 0) + symbol_AddProperty(s, yyvsp[-1].property); + } + break; + + case 190: +#line 865 "dfgparser.y" + { yyval.property = 0; /* left */ } + break; + + case 191: +#line 867 "dfgparser.y" + { if (yyvsp[0].string[1] != '\0' || + (yyvsp[0].string[0]!='l' && yyvsp[0].string[0]!='m' && yyvsp[0].string[0]!='r')) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Invalid symbol status %s", yyvsp[0].string); + misc_UserErrorReport(" in precedence list."); + misc_FinishUserErrorReport(); + } + switch (yyvsp[0].string[0]) { + case 'm': yyval.property = ORDMUL; break; + case 'r': yyval.property = ORDRIGHT; break; + default: yyval.property = 0; + } + string_StringFree(yyvsp[0].string); + } + break; + + case 194: +#line 888 "dfgparser.y" + { dfg_DeleteStringList(yyvsp[-2].list); } + break; + + case 195: +#line 891 "dfgparser.y" + { yyval.list = list_List(yyvsp[0].string); } + break; + + case 196: +#line 892 "dfgparser.y" + { yyval.list = list_Nconc(yyvsp[-2].list, list_List(yyvsp[0].string)); } + break; + + + } + +/* Line 1016 of /opt/gnu//share/bison/yacc.c. */ +#line 2471 "dfgparser.c" + + yyvsp -= yylen; + yyssp -= yylen; + + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen (yytname[yytype]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("parse error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror ("parse error"); + } + goto yyerrlab1; + + +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action. | +`----------------------------------------------------*/ +yyerrlab1: + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* Return failure if at end of input. */ + if (yychar == YYEOF) + { + /* Pop the error token. */ + YYPOPSTACK; + /* Pop the rest of the stack. */ + while (yyssp > yyss) + { + YYDPRINTF ((stderr, "Error: popping ")); + YYDSYMPRINT ((stderr, + yystos[*yyssp], + *yyvsp)); + YYDPRINTF ((stderr, "\n")); + yydestruct (yystos[*yyssp], *yyvsp); + YYPOPSTACK; + } + YYABORT; + } + + YYDPRINTF ((stderr, "Discarding token %d (%s).\n", + yychar, yytname[yychar1])); + yydestruct (yychar1, yylval); + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + YYDPRINTF ((stderr, "Error: popping ")); + YYDSYMPRINT ((stderr, + yystos[*yyssp], *yyvsp)); + YYDPRINTF ((stderr, "\n")); + + yydestruct (yystos[yystate], *yyvsp); + yyvsp--; + yystate = *--yyssp; + + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "Error: state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + } + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; + + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 895 "dfgparser.y" + + +void yyerror(const char *s) +{ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %i: %s\n", dfg_LINENUMBER, s); + misc_FinishUserErrorReport(); +} + +static void dfg_Init(FILE* Input, FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: The input file stream for the parser, a flag store and + a precedence. + RETURNS: Nothing. + EFFECT: The parser and scanner are initialized. + The parser will use the flag store and the precedence + to memorize the settings from the input file. +***************************************************************/ +{ + extern FILE* dfg_in; /* declared in dfgscanner */ + + dfg_in = Input; + dfg_LINENUMBER = 1; + dfg_IGNORETEXT = TRUE; + dfg_AXIOMLIST = list_Nil(); + dfg_CONJECLIST = list_Nil(); + dfg_SORTDECLLIST = list_Nil(); + dfg_USERPRECEDENCE = list_Nil(); + dfg_AXCLAUSES = list_Nil(); + dfg_CONCLAUSES = list_Nil(); + dfg_PROOFLIST = list_Nil(); + dfg_TERMLIST = list_Nil(); + dfg_SYMBOLLIST = list_Nil(); + dfg_VARLIST = list_Nil(); + dfg_VARDECL = FALSE; + dfg_IGNORE = FALSE; + dfg_FLAGS = Flags; + dfg_PRECEDENCE = Precedence; + dfg_DESC.name = (char*) NULL; + dfg_DESC.author = (char*) NULL; + dfg_DESC.version = (char*) NULL; + dfg_DESC.logic = (char*) NULL; + dfg_DESC.status = DFG_UNKNOWNSTATE; + dfg_DESC.description = (char*) NULL; + dfg_DESC.date = (char*) NULL; +} + + +void dfg_Free(void) +/************************************************************** + INPUT: None. + RETURNS: Nothing. + EFFECT: Frees memory used by the problem description. +***************************************************************/ +{ + if (dfg_DESC.name != NULL) + string_StringFree(dfg_DESC.name); + if (dfg_DESC.author != NULL) + string_StringFree(dfg_DESC.author); + if (dfg_DESC.version != NULL) + string_StringFree(dfg_DESC.version); + if (dfg_DESC.logic != NULL) + string_StringFree(dfg_DESC.logic); + if (dfg_DESC.description != NULL) + string_StringFree(dfg_DESC.description); + if(dfg_DESC.date != NULL) + string_StringFree(dfg_DESC.date); +} + +const char* dfg_ProblemName(void) +/************************************************************** + INPUT: None. + RETURNS: The problem's name from the description section. +***************************************************************/ +{ + return dfg_DESC.name; +} + +const char* dfg_ProblemAuthor(void) +/************************************************************** + INPUT: None. + RETURNS: The problem's author from the description section. +***************************************************************/ +{ + return dfg_DESC.author; +} + +const char* dfg_ProblemVersion(void) +/************************************************************** + INPUT: None. + RETURNS: The problem's version from the description section. +***************************************************************/ +{ + return dfg_DESC.version; +} + +const char* dfg_ProblemLogic(void) +/************************************************************** + INPUT: None. + RETURNS: The problem's logic from the description section. +***************************************************************/ +{ + return dfg_DESC.logic; +} + +DFG_STATE dfg_ProblemStatus(void) +/************************************************************** + INPUT: None. + RETURNS: The problem's status from the description section. +***************************************************************/ +{ + return dfg_DESC.status; +} + +const char* dfg_ProblemStatusString(void) +/************************************************************** + INPUT: None. + RETURNS: The string representation of the problem's status. +***************************************************************/ +{ + const char* result = ""; + + switch (dfg_DESC.status) { + case DFG_SATISFIABLE: + result = "satisfiable"; break; + case DFG_UNSATISFIABLE: + result = "unsatisfiable"; break; + case DFG_UNKNOWNSTATE: + result = "unknown"; break; + default: + misc_StartErrorReport(); + misc_ErrorReport("\n In dfg_ProblemStatusString: Invalid status.\n"); + misc_FinishErrorReport(); + } + return result; +} + +const char* dfg_ProblemDescription(void) +/************************************************************** + INPUT: None. + RETURNS: The problem's description from the description section. +***************************************************************/ +{ + return dfg_DESC.description; +} + +const char* dfg_ProblemDate(void) +/************************************************************** + INPUT: None. + RETURNS: The problem's date from the description section. +***************************************************************/ +{ + return dfg_DESC.date; +} + +void dfg_FPrintDescription(FILE* File) +/************************************************************** + INPUT: A file stream. + RETURNS: Nothing. + EFFECT: The description section from the input file + is printed to 'File'. You must call the parser first + before calling this function. +***************************************************************/ +{ + fputs("list_of_descriptions.\n name(", File); + if (dfg_DESC.name != NULL) + fputs(dfg_DESC.name, File); + else + fputs("{* *}", File); + fputs(").\n author(", File); + if (dfg_DESC.author != NULL) + fputs(dfg_DESC.author, File); + else + fputs("{* *}", File); + fputs(").\n", File); + if (dfg_DESC.version != NULL) { + fputs(" version(", File); + fputs(dfg_DESC.version, File); + fputs(").\n", File); + } + if (dfg_DESC.logic != NULL) { + fputs(" logic(", File); + fputs(dfg_DESC.logic, File); + fputs(").\n", File); + } + fputs(" status(", File); + fputs(dfg_ProblemStatusString(), File); + fputs(").\n description(", File); + if (dfg_DESC.description != NULL) + fputs(dfg_DESC.description, File); + else + fputs("{* *}", File); + fputs(").\n", File); + if (dfg_DESC.date != NULL) { + fputs(" date(", File); + fputs(dfg_DESC.date, File); + fputs(").\n", File); + } + fputs("end_of_list.", File); +} + + +LIST dfg_DFGParser(FILE* File, FLAGSTORE Flags, PRECEDENCE Precedence, + LIST* Axioms, LIST* Conjectures, LIST* SortDecl, + LIST* UserDefinedPrecedence) +/************************************************************** + INPUT: The input file containing clauses or formulae in DFG syntax, + a flag store and a precedence used to memorize settings + from the file. + Axioms, Conjectures, SortDecl and UserDefinedPrecedence are + pointers to lists used as return values. + RETURNS: The list of clauses from File. + EFFECT: Reads formulae and clauses from the input file. + The axioms, conjectures, sort declarations and user-defined + precedences are appended to the respective lists, the lists + are not deleted! + All lists except the clause list contain pairs + (label, term), where <label> may be NULL, if no + label was specified for that term. + <UserDefinedPrecedence> contains symbols sorted by decreasing + precedence. This list will only be changed, if the precedence + is explicitly defined in the input file. This can be done + by the 'set_precedence' flag in the SPASS settings list in + the DFG input file. + CAUTION: The weight of the clauses is not correct and the literals + are not oriented! +***************************************************************/ +{ + LIST scan, tupel; + TERM clauseTerm; + NAT bottom; + + dfg_Init(File, Flags, Precedence); /* Initialize the parser and scanner */ + bottom = stack_Bottom(); + dfg_parse(); /* Invoke the parser */ +#ifdef CHECK + if (!stack_Empty(bottom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In dfg_DFGParser: Stack not empty!\n"); + misc_FinishErrorReport(); + } +#endif + dfg_SymCleanUp(); + + /* Remove clause labels and create clauses from the terms */ + for (scan = dfg_AXCLAUSES; !list_Empty(scan); scan = list_Cdr(scan)) { + tupel = list_Car(scan); + clauseTerm = list_PairSecond(tupel); + list_Rplaca(scan, dfg_CreateClauseFromTerm(clauseTerm,TRUE, Flags, Precedence)); + if (list_PairFirst(tupel) != NULL) /* Label is defined */ + string_StringFree(list_PairFirst(tupel)); /* Delete the label */ + list_PairFree(tupel); + } + /* Since dfg_CreateClauseFromTerm() returns NULL for trivial tautologies */ + /* we now delete those NULL pointers from the clause list. */ + dfg_AXCLAUSES = list_PointerDeleteElement(dfg_AXCLAUSES, NULL); + for (scan = dfg_CONCLAUSES; !list_Empty(scan); scan = list_Cdr(scan)) { + tupel = list_Car(scan); + clauseTerm = list_PairSecond(tupel); + list_Rplaca(scan, dfg_CreateClauseFromTerm(clauseTerm,FALSE, Flags, Precedence)); + if (list_PairFirst(tupel) != NULL) /* Label is defined */ + string_StringFree(list_PairFirst(tupel)); /* Delete the label */ + list_PairFree(tupel); + } + /* Since dfg_CreateClauseFromTerm() returns NULL for trivial tautologies */ + /* we now delete those NULL pointers from the clause list. */ + dfg_CONCLAUSES = list_PointerDeleteElement(dfg_CONCLAUSES, NULL); + + /* Delete the proof list */ + dfg_DeleteProofList(dfg_PROOFLIST); + + /* Delete the list_of_terms, since it'll be ignored */ + term_DeleteTermList(dfg_TERMLIST); + + scan = list_Nconc(dfg_AXCLAUSES, dfg_CONCLAUSES); + + *Axioms = list_Nconc(*Axioms, dfg_AXIOMLIST); + *Conjectures = list_Nconc(*Conjectures, dfg_CONJECLIST); + *SortDecl = list_Nconc(*SortDecl, dfg_SORTDECLLIST); + list_NReverse(dfg_USERPRECEDENCE); + *UserDefinedPrecedence = list_Nconc(*UserDefinedPrecedence, dfg_USERPRECEDENCE); + + return scan; +} + + +LIST dfg_ProofParser(FILE* File, FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: The input file containing clauses in DFG syntax, + a flag store and a precedence used to memorize settings + from the file. + RETURNS: A list of tuples (label,clause,justificationlist,splitlevel,origin) + representing a proof. + EFFECT: Reads inputs clauses with labels and the proof lists + from the input file. + The elements of the list are lists with five items. + 1. the label (a string) of a clause, + 2. the clause in TERM format, + 3. the list of justification labels (strings, too), + 4. the split level of the clause, + 5. the origin of the clause (RULE struct from clause.h). + Note that the justification list is empty for input + clauses. +***************************************************************/ +{ + LIST scan, tupel; + TERM term; + NAT bottom; + + dfg_Init(File, Flags, Precedence); /* Initialize the parser and scanner */ + bottom = stack_Bottom(); + dfg_parse(); /* Invoke the parser */ +#ifdef CHECK + if (!stack_Empty(bottom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In dfg_ProofParser: Stack not empty!\n"); + misc_FinishErrorReport(); + } +#endif + + dfg_SymCleanUp(); + + /* Build the union of axiom and conjecture clauses */ + dfg_AXCLAUSES = list_Nconc(dfg_AXCLAUSES, dfg_CONCLAUSES); + dfg_CONCLAUSES = list_Nil(); + for (scan = dfg_AXCLAUSES; !list_Empty(scan); scan = list_Cdr(scan)) { + tupel = list_Car(scan); + term = list_PairSecond(tupel); + if (list_PairFirst(tupel) == NULL) { + /* Ignore input clauses without label */ + term_Delete(term); + list_PairFree(tupel); + list_Rplaca(scan, NULL); + } else + /* Expand the pair to a tuple */ + /* (label,clause,justificationlist, split level, origin) */ + /* For input clauses the justificationlist is empty. */ + /* Input clauses have split level 0. */ + list_Rplacd(tupel, list_Cons(term,list_Cons(list_Nil(),list_Cons(0, list_List((POINTER)INPUT))))); + } + /* Now delete the list items without labels */ + dfg_AXCLAUSES = list_PointerDeleteElement(dfg_AXCLAUSES, NULL); + + /* Delete the formula lists */ + dfg_DeleteFormulaPairList(dfg_AXIOMLIST); + dfg_DeleteFormulaPairList(dfg_CONJECLIST); + /* Delete the list of sort declarations */ + dfg_DeleteFormulaPairList(dfg_SORTDECLLIST); + /* Delete the list_of_terms, since it'll be ignored */ + term_DeleteTermList(dfg_TERMLIST); + + /* Finally append the proof list to the list of input clauses with labels */ + dfg_PROOFLIST = list_NReverse(dfg_PROOFLIST); + dfg_AXCLAUSES = list_Nconc(dfg_AXCLAUSES, dfg_PROOFLIST); + + return dfg_AXCLAUSES; +} + + +LIST dfg_TermParser(FILE* File, FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: The input file containing a list of terms in DFG syntax, + a flag store and a precedence used to memorize settings + from the file. + RETURNS: The list of terms from <File>. + EFFECT: Reads terms from the list_of_terms from the input file. +***************************************************************/ +{ + NAT bottom; + + dfg_Init(File, Flags, Precedence); /* Initialize the parser and scanner */ + bottom = stack_Bottom(); + dfg_parse(); /* Invoke the parser */ +#ifdef CHECK + if (!stack_Empty(bottom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In dfg_TermParser: Stack not empty!\n"); + misc_FinishErrorReport(); + } +#endif + + dfg_SymCleanUp(); + + /* Delete the clause lists */ + dfg_DeleteFormulaPairList(dfg_AXCLAUSES); + dfg_DeleteFormulaPairList(dfg_CONCLAUSES); + /* Delete the formula lists */ + dfg_DeleteFormulaPairList(dfg_AXIOMLIST); + dfg_DeleteFormulaPairList(dfg_CONJECLIST); + /* Delete the proof list */ + dfg_DeleteProofList(dfg_PROOFLIST); + /* Delete the list of sort declarations */ + dfg_DeleteFormulaPairList(dfg_SORTDECLLIST); + + return dfg_TERMLIST; +} + + +void dfg_DeleteFormulaPairList(LIST FormulaPairs) +/************************************************************** + INPUT: A list of pairs (label, formula). + RETURNS: Nothing. + EFFECT: The list and the pairs with their strings and terms + are completely deleted. +***************************************************************/ +{ + LIST pair; + + for ( ; !list_Empty(FormulaPairs); FormulaPairs = list_Pop(FormulaPairs)) { + pair = list_Car(FormulaPairs); /* (label, term) */ + term_Delete(list_PairSecond(pair)); + if (list_PairFirst(pair) != NULL) + string_StringFree(list_PairFirst(pair)); /* Free the label */ + list_PairFree(pair); + } +} + +void dfg_StripLabelsFromList(LIST FormulaPairs) +/************************************************************** + INPUT: A list of pairs (label, formula). + RETURNS: Nothing. + EFFECT: The pairs are replaced by the respective formula + and the pairs with their label strings are deleted. +***************************************************************/ +{ + LIST pair, scan; + + for (scan = FormulaPairs; !list_Empty(scan); scan = list_Cdr(scan)) { + pair = list_Car(scan); /* (label, term) */ + list_Rplaca(scan, list_PairSecond(pair)); + if (list_PairFirst(pair) != NULL) + string_StringFree(list_PairFirst(pair)); /* Free the label */ + list_PairFree(pair); + } +} + +void dfg_DeleteProofList(LIST Proof) +/************************************************************** + INPUT: A list of tuples (label, term, justificationlist, split level). + RETURNS: Nothing. + EFFECT: All memory used by the proof list is freed. + The labels must NOT be NULL entries! +***************************************************************/ +{ + /* Delete the proof list */ + for ( ; !list_Empty(Proof); Proof = list_Pop(Proof)) { + LIST tupel = list_Car(Proof); + string_StringFree(list_First(tupel)); + term_Delete(list_Second(tupel)); + dfg_DeleteStringList(list_Third(tupel)); + list_Delete(tupel); + } +} + +/**************************************************************/ +/* Static Functions */ +/**************************************************************/ + +static void dfg_SymbolDecl(int SymbolType, char* Name, int Arity) +/************************************************************** + INPUT: The type of a symbol, the name, and the arity. + RETURNS: Nothing. + EFFECT: This function handles the declaration of symbols. + If <Arity> is -2, it means that the arity of the symbol + was not specified, if it is -1 the symbol is declared + with arbitrary arity. User defined symbols with arbitrary + arity are not allowed. + The <Name> is deleted. +***************************************************************/ +{ + NAT arity, length; + SYMBOL symbol; + + switch (Arity) { + case -2: /* not specified */ + arity = 0; + break; + case -1: + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %u: symbols with arbitrary arity are not allowed.\n", + dfg_LINENUMBER); + misc_FinishUserErrorReport(); + default: + arity = Arity; +} + + /* Pay attention to the maximum symbol name length */ + length = strlen(Name); + if (length >= symbol__SYMBOLMAXLEN) + Name[symbol__SYMBOLMAXLEN-1] = '\0'; + + /* Check if this symbol was declared earlier */ + symbol = symbol_Lookup(Name); + if (symbol != 0) { + /* Symbol was declared before */ + /* Check if the old and new symbol type are equal */ + if ((SymbolType == DFG_FUNC && !symbol_IsFunction(symbol)) || + (SymbolType == DFG_PRDICAT && !symbol_IsPredicate(symbol)) || + ((SymbolType == DFG_OPERAT || SymbolType == DFG_QUANTIF) && + !symbol_IsJunctor(symbol))) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %u: symbol %s was already declared as ", + dfg_LINENUMBER, Name); + switch (symbol_Type(symbol)) { + case symbol_CONSTANT: + case symbol_FUNCTION: + misc_UserErrorReport("function.\n"); break; + case symbol_PREDICATE: + misc_UserErrorReport("predicate.\n"); break; + case symbol_JUNCTOR: + misc_UserErrorReport("junctor.\n"); break; + default: + misc_UserErrorReport("unknown type.\n"); + } + misc_FinishUserErrorReport(); + } + /* Now check the old and new arity if specified */ + if (Arity != -2 && Arity != symbol_Arity(symbol)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %u: symbol %s was already declared with arity %d\n", + dfg_LINENUMBER, Name, symbol_Arity(symbol)); + misc_FinishUserErrorReport(); + } + } else { + /* Symbol was not declared before */ + switch (SymbolType) { + case DFG_FUNC: + symbol = symbol_CreateFunction(Name, arity, symbol_STATLEX,dfg_PRECEDENCE); + break; + case DFG_PRDICAT: + symbol = symbol_CreatePredicate(Name, arity,symbol_STATLEX,dfg_PRECEDENCE); + break; + default: + symbol = symbol_CreateJunctor(Name, arity, symbol_STATLEX, dfg_PRECEDENCE); + } + if (Arity == -2) + /* Arity wasn't specified so check the arity for each occurrence */ + dfg_SymAdd(symbol); + } + + if (length >= symbol__SYMBOLMAXLEN) { + /* To avoid a memory error restore the old string length */ + Name[symbol__SYMBOLMAXLEN-1] = ' '; /* Something != '\0' */ + } + string_StringFree(Name); /* Name was copied */ +} + + +static SYMBOL dfg_Symbol(char* Name, NAT Arity) +/************************************************************** + INPUT: The name of a symbol and the actual arity of the symbol. + RETURNS: The corresponding SYMBOL. + EFFECT: This function checks if the <Name> was declared as + symbol or variable. If not, an error message is printed + to stderr. + The <Name> is deleted. +***************************************************************/ +{ + SYMBOL symbol; + char old; + NAT length; + + old = ' '; /* Just to avoid a compiler warning */ + /* Pay attention to the maximum symbol name length */ + length = strlen(Name); + if (length >= symbol__SYMBOLMAXLEN) { + old = Name[symbol__SYMBOLMAXLEN-1]; + Name[symbol__SYMBOLMAXLEN-1] = '\0'; + } + + symbol = symbol_Lookup(Name); + if (length >= symbol__SYMBOLMAXLEN) { + /* To avoid a memory error restore the old string */ + Name[symbol__SYMBOLMAXLEN-1] = old; + } + if (symbol != 0) { + string_StringFree(Name); + dfg_SymCheck(symbol, Arity); /* Check the arity */ + } else { + /* Variable */ + if (Arity > 0) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: Undefined symbol %s.\n",dfg_LINENUMBER,Name); + misc_FinishUserErrorReport(); + } + symbol = dfg_VarLookup(Name); + } + return symbol; +} + + +TERM dfg_CreateQuantifier(SYMBOL Symbol, LIST VarTermList, TERM Term) +/************************************************************** + INPUT: A quantifier symbol, a list possibly containing sorts, + and a term. + RETURNS: The created quantifier term.. +***************************************************************/ +{ + LIST varlist, sortlist, scan; + TERM helpterm; + + /* First collect the variable symbols in varlist and the sorts in sortlist */ + varlist = sortlist = list_Nil(); + for ( ; !list_Empty(VarTermList); VarTermList = list_Pop(VarTermList)) { + helpterm = list_Car(VarTermList); + if (term_IsVariable(helpterm)) { + varlist = list_Nconc(varlist, list_List((POINTER)term_TopSymbol(helpterm))); + term_Delete(helpterm); + } else { + SYMBOL var = term_TopSymbol(term_FirstArgument(helpterm)); + varlist = list_Nconc(varlist, list_List((POINTER)var)); + sortlist = list_Nconc(sortlist, list_List(helpterm)); + } + } + + varlist = list_PointerDeleteDuplicates(varlist); + /* Now create terms from the variables */ + for (scan = varlist; !list_Empty(scan); scan = list_Cdr(scan)) + list_Rplaca(scan, term_Create((SYMBOL)list_Car(scan), list_Nil())); + + if (!list_Empty(sortlist)) { + if (symbol_Equal(fol_All(), Symbol)) { + /* The conjunction of all sortterms implies the Term */ + if (symbol_Equal(fol_Or(), term_TopSymbol(Term))) { + /* Special treatment if <Term> is a term with "or" like */ + /* in clauses: add all sort terms negated to the args */ + /* of the "or" */ + for (scan = sortlist; !list_Empty(scan); scan = list_Cdr(scan)) + /* Negate the sort terms */ + list_Rplaca(scan, term_Create(fol_Not(), list_List(list_Car(scan)))); + sortlist = list_Nconc(sortlist, term_ArgumentList(Term)); + term_RplacArgumentList(Term, sortlist); + } else { + /* No "or" term, so build the implication term */ + if (list_Empty(list_Cdr(sortlist))) { + /* Only one sort term */ + list_Rplacd(sortlist, list_List(Term)); + Term = term_Create(fol_Implies(), sortlist); + } else { + /* More than one sort term */ + helpterm = term_Create(fol_And(), sortlist); + Term = term_Create(fol_Implies(), list_Cons(helpterm, list_List(Term))); + } + } + } else if (symbol_Equal(fol_Exist(), Symbol)) { + /* Quantify the conjunction of all sort terms and <Term> */ + if (symbol_Equal(fol_And(), term_TopSymbol(Term))) { + /* Special treatment if <Term> has an "and" as top symbol: */ + /* just add the sort terms to the args of the "and". */ + sortlist = list_Nconc(sortlist, term_ArgumentList(Term)); + term_RplacArgumentList(Term, sortlist); + } else { + sortlist = list_Nconc(sortlist, list_List(Term)); + Term = term_Create(fol_And(), sortlist); + } + } + } + helpterm = fol_CreateQuantifier(Symbol, varlist, list_List(Term)); + return helpterm; +} + + +CLAUSE dfg_CreateClauseFromTerm(TERM Clause, BOOL IsAxiom, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause term, a boolean value, a flag store and a precedence. + RETURNS: The clause term converted to a CLAUSE or NULL if the + clause is a trivial tautology (the clause contains + the literal "true" or "not(false)" ). + EFFECT: This function converts a clause stored as term into an + EARL clause structure. + If 'IsAxiom' is TRUE the clause is treated as axiom + clause else as conjecture clause. + The function deletes the literals "false" and "not(true)" + if they occur in <Clause>. + The contents of the flag store and the precedence are changed + because the parser read flag and precedence settings from + + MEMORY: The clause term is deleted. +***************************************************************/ +{ + LIST literals, scan; + TERM literal; + CLAUSE result; + + if (term_TopSymbol(Clause) == fol_All()) { + /* Remove and free the quantifier and the OR term */ + literals = term_ArgumentList(term_SecondArgument(Clause)); + term_RplacArgumentList(term_SecondArgument(Clause), list_Nil()); + } else { + /* Remove and free the OR term */ + literals = term_ArgumentList(Clause); + term_RplacArgumentList(Clause, list_Nil()); + } + term_Delete(Clause); + + for (scan = literals; !list_Empty(scan); scan = list_Cdr(scan)) { + literal = (TERM) list_Car(scan); + if (symbol_IsPredicate(term_TopSymbol(literal))) { /* Positive literal */ + if (fol_IsTrue(literal)) { + /* Clause is a tautology */ + list_PointerDeleteElement(literals, NULL); + /* Remove possible NULL elements to avoid a crash in term_Delete */ + term_DeleteTermList(literals); + return (CLAUSE) NULL; + } else if (fol_IsFalse(literal)) { + /* Ignore this literal */ + term_Delete(literal); + list_Rplaca(scan, NULL); /* Mark the actual list element */ + } + } else { + /* Found a negative literal */ + TERM atom = term_FirstArgument(literal); + if (fol_IsFalse(atom)) { + /* Clause is a tautology */ + list_PointerDeleteElement(literals, NULL); + /* Remove possible NULL elements to avoid a crash in term_Delete */ + term_DeleteTermList(literals); + return (CLAUSE) NULL; + } else if (fol_IsTrue(atom)) { + /* Ignore this literal */ + term_Delete(literal); + list_Rplaca(literals, NULL); /* Mark the actual list element */ + } + } + } + + literals = list_PointerDeleteElement(literals, NULL); + /* Remove the special literals treated above from the list */ + result = clause_CreateFromLiterals(literals, FALSE, !IsAxiom, FALSE, Flags, Precedence); + /* Don't create sorts! */ + list_Delete(literals); + + return result; +} + + +static void dfg_SubSort(char* Name1, char* Name2) +/************************************************************** + INPUT: Two sort symbol names. + RETURNS: Nothing. + EFFECT: This functions adds the formula + forall([U], implies(Name1(U), Name2(U))) + to the list of axiom formulas. Both <Name1> and <Name2> + are deleted. +***************************************************************/ +{ + SYMBOL s1, s2; + TERM varterm, t1, t2, term; + + s1 = dfg_Symbol(Name1, 1); /* Should be unary predicates */ + s2 = dfg_Symbol(Name2, 1); + if (!symbol_IsPredicate(s1)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: Symbol is not a sort predicate.\n", dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + if (!symbol_IsPredicate(s2)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: Symbol is not a sort predicate.\n", dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + + varterm = term_Create(symbol_CreateStandardVariable(), list_Nil()); + symbol_ResetStandardVarCounter(); + + t1 = term_Create(s1, list_List(varterm)); + t2 = term_Create(s2, list_List(term_Copy(varterm))); + term = term_Create(fol_Implies(), list_Cons(t1, list_List(t2))); + term = fol_CreateQuantifier(fol_All(), list_List(term_Copy(varterm)), + list_List(term)); + dfg_SORTDECLLIST = list_Nconc(dfg_SORTDECLLIST, list_List(list_PairCreate(NULL,term))); +} + + +static void dfg_SymbolGenerated(SYMBOL SortPredicate, BOOL FreelyGenerated, + LIST GeneratedBy) +/************************************************************** + INPUT: A sort predicate, a boolean flag, and a list of function + symbol names. + RETURNS: Nothing. + EFFECT: This function stores the information that the <SortPredicate> + is generated by the function symbols from the <GeneratedBy> + list. The list contains only symbol names! + The <SortPredicate> AND the symbols from the list get + the property GENERATED. Additionally the symbols get + the property FREELY, if the flag <FreelyGenerated> is TRUE. +***************************************************************/ +{ + SYMBOL symbol; + LIST scan; + + if (!symbol_IsPredicate(SortPredicate)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: Symbol is not a sort predicate.\n", dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + /* First reset the old information */ + symbol_RemoveProperty(SortPredicate, GENERATED); + symbol_RemoveProperty(SortPredicate, FREELY); + list_Delete(symbol_GeneratedBy(SortPredicate)); + /* Now set the new information */ + symbol_AddProperty(SortPredicate, GENERATED); + if (FreelyGenerated) + symbol_AddProperty(SortPredicate, FREELY); + for (scan = GeneratedBy; !list_Empty(scan); scan = list_Cdr(scan)) { + symbol = symbol_Lookup(list_Car(scan)); + if (symbol == 0) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: undefined symbol %s.\n", dfg_LINENUMBER, + (char*)list_Car(scan)); + misc_FinishUserErrorReport(); + } else if (!symbol_IsFunction(symbol)) { /* must be function or constant */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: Symbol is not a function.\n", dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + string_StringFree(list_Car(scan)); + list_Rplaca(scan, (POINTER)symbol); /* change the name list to a symbol list */ + /* Set GENERATED properties for generating symbols */ + symbol_AddProperty(symbol, GENERATED); + if (FreelyGenerated) + symbol_AddProperty(symbol, FREELY); + } + symbol_SetGeneratedBy(SortPredicate, GeneratedBy); +} + + +/**************************************************************/ +/* Functions for the Symbol Table */ +/**************************************************************/ + +typedef struct { + SYMBOL symbol; + BOOL valid; + int arity; +} DFG_SYMENTRY, *DFG_SYM; + +static __inline__ DFG_SYM dfg_SymCreate(void) +{ + return (DFG_SYM) memory_Malloc(sizeof(DFG_SYMENTRY)); +} + +static __inline__ void dfg_SymFree(DFG_SYM Entry) +{ + memory_Free(Entry, sizeof(DFG_SYMENTRY)); +} + + +static void dfg_SymAdd(SYMBOL Symbol) +/************************************************************** + INPUT: A symbol. + RETURNS: Nothing. + EFFECT: This function adds 'Symbol' to the symbol list. + The arity of these symbols will be checked every time + the symbol occurs. +***************************************************************/ +{ + DFG_SYM newEntry = dfg_SymCreate(); + newEntry->symbol = Symbol; + newEntry->valid = FALSE; + newEntry->arity = 0; + dfg_SYMBOLLIST = list_Cons(newEntry, dfg_SYMBOLLIST); +} + + +static void dfg_SymCheck(SYMBOL Symbol, NAT Arity) +/************************************************************** + INPUT: A symbol and the current arity of this symbol. + RETURNS: Nothing. + EFFECT: This function compares the previous arity of 'Symbol' + with the actual 'Arity'. If these values differ + the symbol's arity is set to arbitrary. + The arity of symbols whose arity was specified in + the symbol declaration section is checked and a warning + is printed to stderr in case of differences. +***************************************************************/ +{ + LIST scan = dfg_SYMBOLLIST; + while (!list_Empty(scan)) { + DFG_SYM actEntry = (DFG_SYM) list_Car(scan); + if (actEntry->symbol == Symbol) { + if (actEntry->valid) { + if (actEntry->arity != Arity) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %u:", dfg_LINENUMBER); + misc_UserErrorReport(" The actual arity %u", Arity); + misc_UserErrorReport(" of symbol %s differs", symbol_Name(Symbol)); + misc_UserErrorReport(" from the previous arity %u.\n", actEntry->arity); + misc_FinishUserErrorReport(); + } + } else { + /* Not valid => first time */ + actEntry->arity = Arity; + actEntry->valid = TRUE; + } + return; + } + scan = list_Cdr(scan); + } + + /* Symbol isn't in SymbolList, so its arity was specified. */ + /* Check if the specified arity corresponds with the actual arity */ + if (symbol_Arity(Symbol) != Arity) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %u: Symbol %s was declared with arity %u.\n", + dfg_LINENUMBER, symbol_Name(Symbol), symbol_Arity(Symbol)); + misc_FinishUserErrorReport(); + } +} + + +static void dfg_SymCleanUp(void) +/************************************************************** + INPUT: None. + RETURNS: Nothing. + EFFECT: This function corrects all symbols whose arity wasn't + specified in the symbol declaration section but seem + to occur with always the same arity. + The memory for the symbol list is freed. +***************************************************************/ +{ + while (!list_Empty(dfg_SYMBOLLIST)) { + DFG_SYM actEntry = (DFG_SYM) list_Car(dfg_SYMBOLLIST); + SYMBOL actSymbol = actEntry->symbol; + + if (actEntry->arity != symbol_Arity(actSymbol)) + symbol_SetArity(actSymbol, actEntry->arity); + + dfg_SymFree(actEntry); + dfg_SYMBOLLIST = list_Pop(dfg_SYMBOLLIST); + } +} + + +/**************************************************************/ +/* Functions for the Variable Table */ +/**************************************************************/ + +typedef struct { + char* name; + SYMBOL symbol; +} DFG_VARENTRY, *DFG_VAR; + +static __inline__ char* dfg_VarName(DFG_VAR Entry) +{ + return Entry->name; +} + +static __inline__ SYMBOL dfg_VarSymbol(DFG_VAR Entry) +{ + return Entry->symbol; +} + +static __inline__ DFG_VAR dfg_VarCreate(void) +{ + return (DFG_VAR) memory_Malloc(sizeof(DFG_VARENTRY)); +} + +static void dfg_VarFree(DFG_VAR Entry) +{ + string_StringFree(Entry->name); + memory_Free(Entry, sizeof(DFG_VARENTRY)); +} + +static void dfg_VarStart(void) +{ + dfg_VARLIST = list_Push(list_Nil(), dfg_VARLIST); + dfg_VARDECL = TRUE; +} + +static void dfg_VarStop(void) +{ + dfg_VARDECL = FALSE; +} + +static void dfg_VarBacktrack(void) +{ + list_DeleteWithElement(list_Top(dfg_VARLIST), (void (*)(POINTER)) dfg_VarFree); + dfg_VARLIST = list_Pop(dfg_VARLIST); +} + +static void dfg_VarCheck(void) +/* Should be called after a complete clause or formula was parsed */ +{ + if (!list_Empty(dfg_VARLIST)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In dfg_VarCheck: List of variables should be empty!\n"); + misc_FinishErrorReport(); + } + symbol_ResetStandardVarCounter(); +} + +static SYMBOL dfg_VarLookup(char* Name) +/************************************************************** + INPUT: A variable name. + RETURNS: The corresponding variable symbol. + EFFECT: If the variable name was quantified before, the + corresponding symbol is returned and the <Name> is freed. + If the variable name was not quantified, and <dfg_VARDECL> + is TRUE, a new variable is created, else an error + message is printed and the program exits. +***************************************************************/ +{ + LIST scan, scan2; + SYMBOL symbol = symbol_Null(); + + scan = dfg_VARLIST; + scan2 = list_Nil(); + while (!list_Empty(scan) && list_Empty(scan2)) { + scan2 = list_Car(scan); + while (!list_Empty(scan2) && + (!string_Equal(dfg_VarName(list_Car(scan2)), Name))) + scan2 = list_Cdr(scan2); + scan = list_Cdr(scan); + } + + if (!list_Empty(scan2)) { + /* Found variable */ + string_StringFree(Name); + symbol = dfg_VarSymbol(list_Car(scan2)); + } else { + /* Variable not found */ + if (dfg_VARDECL) { + DFG_VAR newEntry = dfg_VarCreate(); + newEntry->name = Name; + newEntry->symbol = symbol_CreateStandardVariable(); + /* Add <newentry> to the first list in dfg_VARLIST */ + list_Rplaca(dfg_VARLIST, list_Cons(newEntry,list_Car(dfg_VARLIST))); + symbol = dfg_VarSymbol(newEntry); + } else { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %u: Free Variable %s.\n", dfg_LINENUMBER, Name); + misc_FinishUserErrorReport(); + } + } + return symbol; +} + diff --git a/test/spass/dfgparser.h b/test/spass/dfgparser.h new file mode 100644 index 0000000000000000000000000000000000000000..252f1409c891ecbec04131ad072dbfe7ac887c29 --- /dev/null +++ b/test/spass/dfgparser.h @@ -0,0 +1,184 @@ +/* A Bison parser, made from dfgparser.y, by GNU bison 1.75. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef BISON_DFGPARSER_H +# define BISON_DFGPARSER_H + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + DFG_AND = 258, + DFG_AUTHOR = 259, + DFG_AXIOMS = 260, + DFG_BEGPROB = 261, + DFG_BY = 262, + DFG_CLAUSE = 263, + DFG_CLOSEBRACE = 264, + DFG_CLSLIST = 265, + DFG_CNF = 266, + DFG_CONJECS = 267, + DFG_DATE = 268, + DFG_DECLLIST = 269, + DFG_DESC = 270, + DFG_DESCLIST = 271, + DFG_DNF = 272, + DFG_DOMPRED = 273, + DFG_ENDLIST = 274, + DFG_ENDPROB = 275, + DFG_EQUAL = 276, + DFG_EQUIV = 277, + DFG_EXISTS = 278, + DFG_FALSE = 279, + DFG_FORMLIST = 280, + DFG_FORMULA = 281, + DFG_FORALL = 282, + DFG_FREELY = 283, + DFG_FUNC = 284, + DFG_GENERATED = 285, + DFG_GENSET = 286, + DFG_HYPOTH = 287, + DFG_IMPLIED = 288, + DFG_IMPLIES = 289, + DFG_LOGIC = 290, + DFG_NAME = 291, + DFG_NOT = 292, + DFG_OPENBRACE = 293, + DFG_OPERAT = 294, + DFG_OR = 295, + DFG_PREC = 296, + DFG_PRED = 297, + DFG_PRDICAT = 298, + DFG_PRFLIST = 299, + DFG_QUANTIF = 300, + DFG_SATIS = 301, + DFG_SETFLAG = 302, + DFG_SETTINGS = 303, + DFG_SYMLIST = 304, + DFG_SORT = 305, + DFG_SORTS = 306, + DFG_STATUS = 307, + DFG_STEP = 308, + DFG_SUBSORT = 309, + DFG_TERMLIST = 310, + DFG_TRUE = 311, + DFG_UNKNOWN = 312, + DFG_UNSATIS = 313, + DFG_VERSION = 314, + DFG_NUM = 315, + DFG_MINUS1 = 316, + DFG_ID = 317, + DFG_TEXT = 318 + }; +#endif +#define DFG_AND 258 +#define DFG_AUTHOR 259 +#define DFG_AXIOMS 260 +#define DFG_BEGPROB 261 +#define DFG_BY 262 +#define DFG_CLAUSE 263 +#define DFG_CLOSEBRACE 264 +#define DFG_CLSLIST 265 +#define DFG_CNF 266 +#define DFG_CONJECS 267 +#define DFG_DATE 268 +#define DFG_DECLLIST 269 +#define DFG_DESC 270 +#define DFG_DESCLIST 271 +#define DFG_DNF 272 +#define DFG_DOMPRED 273 +#define DFG_ENDLIST 274 +#define DFG_ENDPROB 275 +#define DFG_EQUAL 276 +#define DFG_EQUIV 277 +#define DFG_EXISTS 278 +#define DFG_FALSE 279 +#define DFG_FORMLIST 280 +#define DFG_FORMULA 281 +#define DFG_FORALL 282 +#define DFG_FREELY 283 +#define DFG_FUNC 284 +#define DFG_GENERATED 285 +#define DFG_GENSET 286 +#define DFG_HYPOTH 287 +#define DFG_IMPLIED 288 +#define DFG_IMPLIES 289 +#define DFG_LOGIC 290 +#define DFG_NAME 291 +#define DFG_NOT 292 +#define DFG_OPENBRACE 293 +#define DFG_OPERAT 294 +#define DFG_OR 295 +#define DFG_PREC 296 +#define DFG_PRED 297 +#define DFG_PRDICAT 298 +#define DFG_PRFLIST 299 +#define DFG_QUANTIF 300 +#define DFG_SATIS 301 +#define DFG_SETFLAG 302 +#define DFG_SETTINGS 303 +#define DFG_SYMLIST 304 +#define DFG_SORT 305 +#define DFG_SORTS 306 +#define DFG_STATUS 307 +#define DFG_STEP 308 +#define DFG_SUBSORT 309 +#define DFG_TERMLIST 310 +#define DFG_TRUE 311 +#define DFG_UNKNOWN 312 +#define DFG_UNSATIS 313 +#define DFG_VERSION 314 +#define DFG_NUM 315 +#define DFG_MINUS1 316 +#define DFG_ID 317 +#define DFG_TEXT 318 + + + + +#ifndef YYSTYPE +#line 165 "dfgparser.y" +typedef union { + int number; + char* string; + SYMBOL symbol; + SPROPERTY property; + TERM term; + LIST list; + DFG_STATE state; + BOOL bool; +} yystype; +/* Line 1281 of /opt/gnu//share/bison/yacc.c. */ +#line 177 "dfgparser.h" +# define YYSTYPE yystype +#endif + +extern YYSTYPE dfg_lval; + + +#endif /* not BISON_DFGPARSER_H */ + diff --git a/test/spass/dfgscanner.c b/test/spass/dfgscanner.c new file mode 100644 index 0000000000000000000000000000000000000000..a6eefa46aed07373aecbf65326da0ff93c2779ed --- /dev/null +++ b/test/spass/dfgscanner.c @@ -0,0 +1,5174 @@ +#define yy_create_buffer dfg__create_buffer +#define yy_delete_buffer dfg__delete_buffer +#define yy_scan_buffer dfg__scan_buffer +#define yy_scan_string dfg__scan_string +#define yy_scan_bytes dfg__scan_bytes +#define yy_flex_debug dfg__flex_debug +#define yy_init_buffer dfg__init_buffer +#define yy_flush_buffer dfg__flush_buffer +#define yy_load_buffer_state dfg__load_buffer_state +#define yy_switch_to_buffer dfg__switch_to_buffer +#define yyin dfg_in +#define yyleng dfg_leng +#define yylex dfg_lex +#define yyout dfg_out +#define yyrestart dfg_restart +#define yytext dfg_text + +#line 19 "dfgscanner.c" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header$ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> +#include <unistd.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define yywrap() 1 +#define YY_SKIP_YYWRAP +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext +static yyconst short yy_nxt[][41] = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0 + }, + + { + 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, + 14, 14, 14, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 14, 14, 24, 14, 25, 26, 27, + 28, 14, 29, 30, 31, 32, 14, 14, 14, 33, + 6 + + }, + + { + 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, + 14, 14, 14, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 14, 14, 24, 14, 25, 26, 27, + 28, 14, 29, 30, 31, 32, 14, 14, 14, 33, + 6 + }, + + { + 5, 34, 34, 34, 34, 34, 35, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34 + + }, + + { + 5, 34, 34, 34, 34, 34, 35, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34 + }, + + { + -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, + -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, + -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, + -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, + -5 + + }, + + { + 5, -6, -6, -6, -6, -6, -6, -6, -6, -6, + -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, + -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, + -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, + -6 + }, + + { + 5, -7, 36, -7, -7, -7, -7, -7, -7, -7, + -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, + -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, + -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, + -7 + + }, + + { + 5, -8, -8, -8, -8, -8, -8, -8, -8, -8, + -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, + -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, + -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, + -8 + }, + + { + 5, 37, 37, -9, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37 + + }, + + { + 5, -10, -10, -10, -10, -10, -10, -10, -10, -10, + -10, -10, -10, -10, -10, -10, -10, -10, -10, -10, + -10, -10, -10, -10, -10, -10, -10, -10, -10, -10, + -10, -10, -10, -10, -10, -10, -10, -10, -10, -10, + -10 + }, + + { + 5, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + 38 + + }, + + { + 5, -12, -12, -12, -12, -12, -12, -12, -12, 39, + -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12 + }, + + { + 5, -13, -13, -13, -13, -13, -13, -13, 40, 40, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -13, + -13 + + }, + + { + 5, -14, -14, -14, -14, -14, -14, -14, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -14, + -14 + }, + + { + 5, -15, -15, -15, -15, -15, -15, -15, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 42, 41, 41, + 41, 41, 41, 41, 43, 41, 41, 44, 41, -15, + -15 + + }, + + { + 5, -16, -16, -16, -16, -16, -16, -16, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 45, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 46, -16, + -16 + }, + + { + 5, -17, -17, -17, -17, -17, -17, -17, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 47, 41, 48, 49, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -17, + -17 + + }, + + { + 5, -18, -18, -18, -18, -18, -18, -18, 41, 41, + 41, 41, 41, 41, 50, 41, 41, 41, 51, 41, + 41, 41, 41, 41, 41, 41, 41, 52, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -18, + -18 + }, + + { + 5, -19, -19, -19, -19, -19, -19, -19, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 53, 41, 41, + 54, 41, 41, 41, 41, 41, 41, 55, 41, -19, + -19 + + }, + + { + 5, -20, -20, -20, -20, -20, -20, -20, 41, 41, + 41, 41, 41, 41, 56, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 57, 41, + 41, 58, 41, 41, 59, 41, 41, 41, 41, -20, + -20 + }, + + { + 5, -21, -21, -21, -21, -21, -21, -21, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 60, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -21, + -21 + + }, + + { + 5, -22, -22, -22, -22, -22, -22, -22, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 61, -22, + -22 + }, + + { + 5, -23, -23, -23, -23, -23, -23, -23, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 62, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -23, + -23 + + }, + + { + 5, -24, -24, -24, -24, -24, -24, -24, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 63, 41, 41, 41, 41, 41, 64, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -24, + -24 + }, + + { + 5, -25, -25, -25, -25, -25, -25, -25, 41, 41, + 41, 41, 41, 41, 65, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 66, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -25, + -25 + + }, + + { + 5, -26, -26, -26, -26, -26, -26, -26, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 67, + 41, 68, 41, 41, 41, 41, 41, 41, 41, -26, + -26 + }, + + { + 5, -27, -27, -27, -27, -27, -27, -27, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 69, 41, 41, 41, 41, 41, 41, 41, -27, + -27 + + }, + + { + 5, -28, -28, -28, -28, -28, -28, -28, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 70, 41, 41, 41, 41, -28, + -28 + }, + + { + 5, -29, -29, -29, -29, -29, -29, -29, 41, 41, + 41, 41, 41, 41, 71, 41, 41, 41, 72, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 73, 41, + 41, 41, 41, 74, 75, 41, 41, 41, 41, -29, + -29 + + }, + + { + 5, -30, -30, -30, -30, -30, -30, -30, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 76, 41, 41, 41, 41, 41, 41, 41, -30, + -30 + }, + + { + 5, -31, -31, -31, -31, -31, -31, -31, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 77, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -31, + -31 + + }, + + { + 5, -32, -32, -32, -32, -32, -32, -32, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 78, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -32, + -32 + }, + + { + 5, -33, -33, -33, -33, -33, 79, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33 + + }, + + { + 5, 80, 80, 80, 80, 80, -34, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80 + }, + + { + 5, 81, 81, 81, 81, 81, 82, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 83 + + }, + + { + 5, -36, 36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36 + }, + + { + 5, 37, 37, -37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37 + + }, + + { + 5, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38 + }, + + { + 5, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, + -39 + + }, + + { + 5, -40, -40, -40, -40, -40, -40, -40, 40, 40, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -40, + -40 + }, + + { + 5, -41, -41, -41, -41, -41, -41, -41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -41, + -41 + + }, + + { + 5, -42, -42, -42, -42, -42, -42, -42, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 84, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -42, + -42 + }, + + { + 5, -43, -43, -43, -43, -43, -43, -43, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 85, 41, 41, 41, 41, 41, -43, + -43 + + }, + + { + 5, -44, -44, -44, -44, -44, -44, -44, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 86, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -44, + -44 + }, + + { + 5, -45, -45, -45, -45, -45, -45, -45, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 87, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -45, + -45 + + }, + + { + 5, -46, -46, -46, -46, -46, -46, -46, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -46, + -46 + }, + + { + 5, -47, -47, -47, -47, -47, -47, -47, 41, 41, + 41, 41, 41, 41, 88, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -47, + -47 + + }, + + { + 5, -48, -48, -48, -48, -48, -48, -48, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 89, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -48, + -48 + }, + + { + 5, -49, -49, -49, -49, -49, -49, -49, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 90, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -49, + -49 + + }, + + { + 5, -50, -50, -50, -50, -50, -50, -50, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 91, 41, 41, 41, 41, 41, -50, + -50 + }, + + { + 5, -51, -51, -51, -51, -51, -51, -51, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 92, 41, 41, 41, 41, 41, 41, -51, + -51 + + }, + + { + 5, -52, -52, -52, -52, -52, -52, -52, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 93, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -52, + -52 + }, + + { + 5, -53, -53, -53, -53, -53, -53, -53, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 94, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -53, + -53 + + }, + + { + 5, -54, -54, -54, -54, -54, -54, -54, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 95, 41, 41, 41, 41, -54, + -54 + }, + + { + 5, -55, -55, -55, -55, -55, -55, -55, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 96, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -55, + -55 + + }, + + { + 5, -56, -56, -56, -56, -56, -56, -56, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 97, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -56, + -56 + }, + + { + 5, -57, -57, -57, -57, -57, -57, -57, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 98, 41, 41, 41, 41, 41, 41, 41, -57, + -57 + + }, + + { + 5, -58, -58, -58, -58, -58, -58, -58, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 99, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -58, + -58 + }, + + { + 5, -59, -59, -59, -59, -59, -59, -59, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 100, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -59, + -59 + + }, + + { + 5, -60, -60, -60, -60, -60, -60, -60, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 101, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -60, + -60 + }, + + { + 5, -61, -61, -61, -61, -61, -61, -61, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 102, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -61, + -61 + + }, + + { + 5, -62, -62, -62, -62, -62, -62, -62, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 103, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -62, + -62 + }, + + { + 5, -63, -63, -63, -63, -63, -63, -63, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 104, 41, 41, 41, 41, 41, 41, -63, + -63 + + }, + + { + 5, -64, -64, -64, -64, -64, -64, -64, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 105, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -64, + -64 + }, + + { + 5, -65, -65, -65, -65, -65, -65, -65, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 106, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -65, + -65 + + }, + + { + 5, -66, -66, -66, -66, -66, -66, -66, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 107, 41, 41, 41, 41, 41, -66, + -66 + }, + + { + 5, -67, -67, -67, -67, -67, -67, -67, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 108, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -67, + -67 + + }, + + { + 5, -68, -68, -68, -68, -68, -68, -68, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -68, + -68 + }, + + { + 5, -69, -69, -69, -69, -69, -69, -69, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 109, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -69, + -69 + + }, + + { + 5, -70, -70, -70, -70, -70, -70, -70, 41, 41, + 41, 41, 41, 41, 110, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -70, + -70 + }, + + { + 5, -71, -71, -71, -71, -71, -71, -71, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 111, 41, 41, 41, 41, 41, -71, + -71 + + }, + + { + 5, -72, -72, -72, -72, -72, -72, -72, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 112, 41, 41, 41, 41, 41, -72, + -72 + }, + + { + 5, -73, -73, -73, -73, -73, -73, -73, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 113, 41, 41, 41, 41, 41, 41, 41, -73, + -73 + + }, + + { + 5, -74, -74, -74, -74, -74, -74, -74, 41, 41, + 41, 41, 41, 41, 114, 41, 41, 41, 115, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -74, + -74 + }, + + { + 5, -75, -75, -75, -75, -75, -75, -75, 41, 41, + 41, 41, 41, 41, 41, 116, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -75, + -75 + + }, + + { + 5, -76, -76, -76, -76, -76, -76, -76, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 117, 41, 41, 41, 41, -76, + -76 + }, + + { + 5, -77, -77, -77, -77, -77, -77, -77, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 118, 41, 41, 41, 41, 41, + 41, 41, 119, 41, 41, 41, 41, 41, 41, -77, + -77 + + }, + + { + 5, -78, -78, -78, -78, -78, -78, -78, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 120, 41, 41, 41, 41, 41, 41, 41, -78, + -78 + }, + + { + 5, -79, -79, -79, -79, -79, -79, -79, -79, -79, + -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, + -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, + -79, -79, -79, -79, -79, -79, -79, -79, -79, -79, + -79 + + }, + + { + 5, 80, 80, 80, 80, 80, -80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80 + }, + + { + 5, 81, 81, 81, 81, 81, -81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + -81 + + }, + + { + 5, 81, 81, 81, 81, 81, 82, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 83 + }, + + { + 5, -83, -83, -83, -83, -83, -83, -83, -83, -83, + -83, -83, -83, -83, -83, -83, -83, -83, -83, -83, + -83, -83, -83, -83, -83, -83, -83, -83, -83, -83, + -83, -83, -83, -83, -83, -83, -83, -83, -83, -83, + -83 + + }, + + { + 5, -84, -84, -84, -84, -84, -84, -84, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -84, + -84 + }, + + { + 5, -85, -85, -85, -85, -85, -85, -85, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 121, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -85, + -85 + + }, + + { + 5, -86, -86, -86, -86, -86, -86, -86, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 122, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -86, + -86 + }, + + { + 5, -87, -87, -87, -87, -87, -87, -87, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 123, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -87, + -87 + + }, + + { + 5, -88, -88, -88, -88, -88, -88, -88, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 124, 41, 41, 41, 41, -88, + -88 + }, + + { + 5, -89, -89, -89, -89, -89, -89, -89, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -89, + -89 + + }, + + { + 5, -90, -90, -90, -90, -90, -90, -90, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 125, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -90, + -90 + }, + + { + 5, -91, -91, -91, -91, -91, -91, -91, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 126, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -91, + -91 + + }, + + { + 5, -92, -92, -92, -92, -92, -92, -92, 41, 41, + 41, 41, 41, 41, 41, 41, 127, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -92, + -92 + }, + + { + 5, -93, -93, -93, -93, -93, -93, -93, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -93, + -93 + + }, + + { + 5, -94, -94, -94, -94, -94, -94, -94, 41, 41, + 41, 41, 41, 128, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -94, + -94 + }, + + { + 5, -95, -95, -95, -95, -95, -95, -95, 41, 41, + 41, 41, 41, 41, 129, 41, 41, 41, 41, 41, + 41, 41, 130, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -95, + -95 + + }, + + { + 5, -96, -96, -96, -96, -96, -96, -96, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 131, 41, 41, 41, 41, 41, 41, -96, + -96 + }, + + { + 5, -97, -97, -97, -97, -97, -97, -97, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 132, 41, 41, 41, 41, 41, 41, -97, + -97 + + }, + + { + 5, -98, -98, -98, -98, -98, -98, -98, 41, 41, + 41, 41, 41, 41, 133, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 134, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -98, + -98 + }, + + { + 5, -99, -99, -99, -99, -99, -99, -99, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 135, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -99, + -99 + + }, + + { + 5, -100, -100, -100, -100, -100, -100, -100, 41, 41, + 41, 41, 41, 41, 41, 41, 136, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -100, + -100 + }, + + { + 5, -101, -101, -101, -101, -101, -101, -101, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 137, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -101, + -101 + + }, + + { + 5, -102, -102, -102, -102, -102, -102, -102, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 138, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -102, + -102 + }, + + { + 5, -103, -103, -103, -103, -103, -103, -103, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 139, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -103, + -103 + + }, + + { + 5, -104, -104, -104, -104, -104, -104, -104, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 140, 41, 41, 41, 41, 41, -104, + -104 + }, + + { + 5, -105, -105, -105, -105, -105, -105, -105, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 141, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -105, + -105 + + }, + + { + 5, -106, -106, -106, -106, -106, -106, -106, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 142, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -106, + -106 + }, + + { + 5, -107, -107, -107, -107, -107, -107, -107, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -107, + -107 + + }, + + { + 5, -108, -108, -108, -108, -108, -108, -108, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 143, 41, 41, 41, 41, 41, 41, 41, -108, + -108 + }, + + { + 5, -109, -109, -109, -109, -109, -109, -109, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 144, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -109, + -109 + + }, + + { + 5, -110, -110, -110, -110, -110, -110, -110, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 145, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -110, + -110 + }, + + { + 5, -111, -111, -111, -111, -111, -111, -111, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 146, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -111, + -111 + + }, + + { + 5, -112, -112, -112, -112, -112, -112, -112, 41, 41, + 41, 41, 41, 147, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -112, + -112 + }, + + { + 5, -113, -113, -113, -113, -113, -113, -113, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 148, 41, 41, 41, 41, 41, -113, + -113 + + }, + + { + 5, -114, -114, -114, -114, -114, -114, -114, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 149, 41, 41, 41, 41, 41, -114, + -114 + }, + + { + 5, -115, -115, -115, -115, -115, -115, -115, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 150, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -115, + -115 + + }, + + { + 5, -116, -116, -116, -116, -116, -116, -116, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 151, 41, 41, 41, 41, 41, 41, -116, + -116 + }, + + { + 5, -117, -117, -117, -117, -117, -117, -117, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 152, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -117, + -117 + + }, + + { + 5, -118, -118, -118, -118, -118, -118, -118, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 153, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -118, + -118 + }, + + { + 5, -119, -119, -119, -119, -119, -119, -119, 41, 41, + 41, 41, 41, 41, 154, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -119, + -119 + + }, + + { + 5, -120, -120, -120, -120, -120, -120, -120, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 155, 41, 41, 41, 41, 41, 41, -120, + -120 + }, + + { + 5, -121, -121, -121, -121, -121, -121, -121, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 156, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -121, + -121 + + }, + + { + 5, -122, -122, -122, -122, -122, -122, -122, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 157, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -122, + -122 + }, + + { + 5, -123, -123, -123, -123, -123, -123, -123, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 158, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -123, + -123 + + }, + + { + 5, -124, -124, -124, -124, -124, -124, -124, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 159, 41, 41, 41, 41, 41, 41, -124, + -124 + }, + + { + 5, -125, -125, -125, -125, -125, -125, -125, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 160, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -125, + -125 + + }, + + { + 5, -126, -126, -126, -126, -126, -126, -126, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -126, + -126 + }, + + { + 5, -127, -127, -127, -127, -127, -127, -127, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 161, 41, 41, 41, 41, 41, 41, 41, -127, + -127 + + }, + + { + 5, -128, -128, -128, -128, -128, -128, -128, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 162, 163, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -128, + -128 + }, + + { + 5, -129, -129, -129, -129, -129, -129, -129, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 164, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -129, + -129 + + }, + + { + 5, -130, -130, -130, -130, -130, -130, -130, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 165, 41, 41, 41, -130, + -130 + }, + + { + 5, -131, -131, -131, -131, -131, -131, -131, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 166, 41, 41, 41, 41, 41, -131, + -131 + + }, + + { + 5, -132, -132, -132, -132, -132, -132, -132, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 167, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -132, + -132 + }, + + { + 5, -133, -133, -133, -133, -133, -133, -133, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 168, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -133, + -133 + + }, + + { + 5, -134, -134, -134, -134, -134, -134, -134, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 169, 41, 41, 41, 41, -134, + -134 + }, + + { + 5, -135, -135, -135, -135, -135, -135, -135, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 170, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -135, + -135 + + }, + + { + 5, -136, -136, -136, -136, -136, -136, -136, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 171, 41, 41, 41, 41, 41, -136, + -136 + }, + + { + 5, -137, -137, -137, -137, -137, -137, -137, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 172, 41, 41, 41, 41, 41, 41, 41, -137, + -137 + + }, + + { + 5, -138, -138, -138, -138, -138, -138, -138, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 173, 41, 41, 41, 41, 41, -138, + -138 + }, + + { + 5, -139, -139, -139, -139, -139, -139, -139, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 174, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -139, + -139 + + }, + + { + 5, -140, -140, -140, -140, -140, -140, -140, 41, 41, + 41, 41, 41, 175, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -140, + -140 + }, + + { + 5, -141, -141, -141, -141, -141, -141, -141, 41, 41, + 41, 41, 41, 41, 41, 41, 176, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -141, + -141 + + }, + + { + 5, -142, -142, -142, -142, -142, -142, -142, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -142, + -142 + }, + + { + 5, -143, -143, -143, -143, -143, -143, -143, 41, 41, + 41, 41, 41, 41, 177, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -143, + -143 + + }, + + { + 5, -144, -144, -144, -144, -144, -144, -144, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 178, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -144, + -144 + }, + + { + 5, -145, -145, -145, -145, -145, -145, -145, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 179, 41, 41, 41, 41, 41, -145, + -145 + + }, + + { + 5, -146, -146, -146, -146, -146, -146, -146, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 180, 41, 41, 41, 41, 41, 41, -146, + -146 + }, + + { + 5, -147, -147, -147, -147, -147, -147, -147, 41, 41, + 41, 181, 41, 41, 41, 41, 41, 41, 41, 182, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 183, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -147, + -147 + + }, + + { + 5, -148, -148, -148, -148, -148, -148, -148, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 184, 41, 41, 41, 41, 41, 41, -148, + -148 + }, + + { + 5, -149, -149, -149, -149, -149, -149, -149, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 185, 41, 41, 41, 41, -149, + -149 + + }, + + { + 5, -150, -150, -150, -150, -150, -150, -150, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -150, + -150 + }, + + { + 5, -151, -151, -151, -151, -151, -151, -151, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 186, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -151, + -151 + + }, + + { + 5, -152, -152, -152, -152, -152, -152, -152, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -152, + -152 + }, + + { + 5, -153, -153, -153, -153, -153, -153, -153, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 187, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -153, + -153 + + }, + + { + 5, -154, -154, -154, -154, -154, -154, -154, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 188, 41, 41, 41, 41, 41, -154, + -154 + }, + + { + 5, -155, -155, -155, -155, -155, -155, -155, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 189, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -155, + -155 + + }, + + { + 5, -156, -156, -156, -156, -156, -156, -156, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 190, 41, 41, 41, 41, 41, 41, 41, -156, + -156 + }, + + { + 5, -157, -157, -157, -157, -157, -157, -157, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 191, 41, 41, 41, 41, 41, 41, -157, + -157 + + }, + + { + 5, -158, -158, -158, -158, -158, -158, -158, 41, 41, + 41, 41, 41, 192, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -158, + -158 + }, + + { + 5, -159, -159, -159, -159, -159, -159, -159, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 193, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -159, + -159 + + }, + + { + 5, -160, -160, -160, -160, -160, -160, -160, 41, 41, + 41, 41, 41, 41, 41, 41, 194, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -160, + -160 + }, + + { + 5, -161, -161, -161, -161, -161, -161, -161, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 195, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -161, + -161 + + }, + + { + 5, -162, -162, -162, -162, -162, -162, -162, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 196, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -162, + -162 + }, + + { + 5, -163, -163, -163, -163, -163, -163, -163, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 197, 41, 41, 41, 41, 41, 41, 41, -163, + -163 + + }, + + { + 5, -164, -164, -164, -164, -164, -164, -164, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -164, + -164 + }, + + { + 5, -165, -165, -165, -165, -165, -165, -165, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -165, + -165 + + }, + + { + 5, -166, -166, -166, -166, -166, -166, -166, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 198, 41, 41, 41, 41, 41, 41, -166, + -166 + }, + + { + 5, -167, -167, -167, -167, -167, -167, -167, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -167, + -167 + + }, + + { + 5, -168, -168, -168, -168, -168, -168, -168, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 199, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -168, + -168 + }, + + { + 5, -169, -169, -169, -169, -169, -169, -169, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 200, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -169, + -169 + + }, + + { + 5, -170, -170, -170, -170, -170, -170, -170, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 201, -170, + -170 + }, + + { + 5, -171, -171, -171, -171, -171, -171, -171, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 202, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -171, + -171 + + }, + + { + 5, -172, -172, -172, -172, -172, -172, -172, 41, 41, + 41, 41, 41, 41, 203, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -172, + -172 + }, + + { + 5, -173, -173, -173, -173, -173, -173, -173, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 204, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -173, + -173 + + }, + + { + 5, -174, -174, -174, -174, -174, -174, -174, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 205, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -174, + -174 + }, + + { + 5, -175, -175, -175, -175, -175, -175, -175, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 206, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -175, + -175 + + }, + + { + 5, -176, -176, -176, -176, -176, -176, -176, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -176, + -176 + }, + + { + 5, -177, -177, -177, -177, -177, -177, -177, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 207, 41, 41, 41, 41, 41, -177, + -177 + + }, + + { + 5, -178, -178, -178, -178, -178, -178, -178, 41, 41, + 41, 41, 41, 41, 41, 41, 208, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -178, + -178 + }, + + { + 5, -179, -179, -179, -179, -179, -179, -179, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 209, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -179, + -179 + + }, + + { + 5, -180, -180, -180, -180, -180, -180, -180, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 210, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -180, + -180 + }, + + { + 5, -181, -181, -181, -181, -181, -181, -181, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 211, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -181, + -181 + + }, + + { + 5, -182, -182, -182, -182, -182, -182, -182, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 212, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -182, + -182 + }, + + { + 5, -183, -183, -183, -183, -183, -183, -183, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 213, 41, 41, 41, 41, 41, 41, 41, -183, + -183 + + }, + + { + 5, -184, -184, -184, -184, -184, -184, -184, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -184, + -184 + }, + + { + 5, -185, -185, -185, -185, -185, -185, -185, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 214, 41, 41, 41, 41, 41, 41, -185, + -185 + + }, + + { + 5, -186, -186, -186, -186, -186, -186, -186, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 215, 41, 41, 41, 41, 41, 41, 41, -186, + -186 + }, + + { + 5, -187, -187, -187, -187, -187, -187, -187, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 216, 41, 41, -187, + -187 + + }, + + { + 5, -188, -188, -188, -188, -188, -188, -188, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 217, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -188, + -188 + }, + + { + 5, -189, -189, -189, -189, -189, -189, -189, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 218, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -189, + -189 + + }, + + { + 5, -190, -190, -190, -190, -190, -190, -190, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -190, + -190 + }, + + { + 5, -191, -191, -191, -191, -191, -191, -191, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -191, + -191 + + }, + + { + 5, -192, -192, -192, -192, -192, -192, -192, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 219, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -192, + -192 + }, + + { + 5, -193, -193, -193, -193, -193, -193, -193, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -193, + -193 + + }, + + { + 5, -194, -194, -194, -194, -194, -194, -194, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 220, 41, 41, 41, 41, 41, -194, + -194 + }, + + { + 5, -195, -195, -195, -195, -195, -195, -195, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 221, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -195, + -195 + + }, + + { + 5, -196, -196, -196, -196, -196, -196, -196, 41, 41, + 41, 41, 41, 222, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -196, + -196 + }, + + { + 5, -197, -197, -197, -197, -197, -197, -197, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 223, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -197, + -197 + + }, + + { + 5, -198, -198, -198, -198, -198, -198, -198, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -198, + -198 + }, + + { + 5, -199, -199, -199, -199, -199, -199, -199, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -199, + -199 + + }, + + { + 5, -200, -200, -200, -200, -200, -200, -200, 41, 41, + 41, 41, 41, 41, 224, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -200, + -200 + }, + + { + 5, -201, -201, -201, -201, -201, -201, -201, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -201, + -201 + + }, + + { + 5, -202, -202, -202, -202, -202, -202, -202, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 225, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -202, + -202 + }, + + { + 5, -203, -203, -203, -203, -203, -203, -203, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 226, 41, 41, 41, 41, 41, -203, + -203 + + }, + + { + 5, -204, -204, -204, -204, -204, -204, -204, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 227, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -204, + -204 + }, + + { + 5, -205, -205, -205, -205, -205, -205, -205, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 228, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 229, 41, 41, 41, 41, 41, 41, -205, + -205 + + }, + + { + 5, -206, -206, -206, -206, -206, -206, -206, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 230, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -206, + -206 + }, + + { + 5, -207, -207, -207, -207, -207, -207, -207, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 231, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -207, + -207 + + }, + + { + 5, -208, -208, -208, -208, -208, -208, -208, 41, 41, + 41, 41, 41, 41, 232, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -208, + -208 + }, + + { + 5, -209, -209, -209, -209, -209, -209, -209, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 233, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -209, + -209 + + }, + + { + 5, -210, -210, -210, -210, -210, -210, -210, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 234, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -210, + -210 + }, + + { + 5, -211, -211, -211, -211, -211, -211, -211, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 235, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -211, + -211 + + }, + + { + 5, -212, -212, -212, -212, -212, -212, -212, 41, 41, + 41, 41, 41, 41, 236, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -212, + -212 + }, + + { + 5, -213, -213, -213, -213, -213, -213, -213, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 237, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -213, + -213 + + }, + + { + 5, -214, -214, -214, -214, -214, -214, -214, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -214, + -214 + }, + + { + 5, -215, -215, -215, -215, -215, -215, -215, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 238, 41, 41, 41, 41, 41, -215, + -215 + + }, + + { + 5, -216, -216, -216, -216, -216, -216, -216, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 239, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -216, + -216 + }, + + { + 5, -217, -217, -217, -217, -217, -217, -217, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 240, 41, 41, 41, 41, 41, 41, -217, + -217 + + }, + + { + 5, -218, -218, -218, -218, -218, -218, -218, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 241, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -218, + -218 + }, + + { + 5, -219, -219, -219, -219, -219, -219, -219, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 242, 41, 41, 41, 41, 41, 41, 41, -219, + -219 + + }, + + { + 5, -220, -220, -220, -220, -220, -220, -220, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 243, 41, 41, 41, 41, -220, + -220 + }, + + { + 5, -221, -221, -221, -221, -221, -221, -221, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 244, 41, 41, 41, 41, 41, -221, + -221 + + }, + + { + 5, -222, -222, -222, -222, -222, -222, -222, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 245, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -222, + -222 + }, + + { + 5, -223, -223, -223, -223, -223, -223, -223, 41, 41, + 41, 41, 41, 41, 41, 246, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -223, + -223 + + }, + + { + 5, -224, -224, -224, -224, -224, -224, -224, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -224, + -224 + }, + + { + 5, -225, -225, -225, -225, -225, -225, -225, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 247, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -225, + -225 + + }, + + { + 5, -226, -226, -226, -226, -226, -226, -226, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 248, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -226, + -226 + }, + + { + 5, -227, -227, -227, -227, -227, -227, -227, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 249, 41, 41, 41, 41, 41, 41, -227, + -227 + + }, + + { + 5, -228, -228, -228, -228, -228, -228, -228, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -228, + -228 + }, + + { + 5, -229, -229, -229, -229, -229, -229, -229, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -229, + -229 + + }, + + { + 5, -230, -230, -230, -230, -230, -230, -230, 41, 41, + 41, 41, 41, 250, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -230, + -230 + }, + + { + 5, -231, -231, -231, -231, -231, -231, -231, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 251, 41, 41, 41, 41, 41, 41, 41, -231, + -231 + + }, + + { + 5, -232, -232, -232, -232, -232, -232, -232, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 252, 41, 41, 41, 41, 41, -232, + -232 + }, + + { + 5, -233, -233, -233, -233, -233, -233, -233, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 253, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -233, + -233 + + }, + + { + 5, -234, -234, -234, -234, -234, -234, -234, 41, 41, + 41, 41, 41, 41, 254, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -234, + -234 + }, + + { + 5, -235, -235, -235, -235, -235, -235, -235, 41, 41, + 41, 41, 255, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -235, + -235 + + }, + + { + 5, -236, -236, -236, -236, -236, -236, -236, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 256, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -236, + -236 + }, + + { + 5, -237, -237, -237, -237, -237, -237, -237, 41, 41, + 41, 41, 41, 41, 41, 41, 257, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -237, + -237 + + }, + + { + 5, -238, -238, -238, -238, -238, -238, -238, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -238, + -238 + }, + + { + 5, -239, -239, -239, -239, -239, -239, -239, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -239, + -239 + + }, + + { + 5, -240, -240, -240, -240, -240, -240, -240, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 258, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -240, + -240 + }, + + { + 5, -241, -241, -241, -241, -241, -241, -241, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -241, + -241 + + }, + + { + 5, -242, -242, -242, -242, -242, -242, -242, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 259, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -242, + -242 + }, + + { + 5, -243, -243, -243, -243, -243, -243, -243, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 260, 41, 41, 41, 41, 41, 41, 41, -243, + -243 + + }, + + { + 5, -244, -244, -244, -244, -244, -244, -244, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 261, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -244, + -244 + }, + + { + 5, -245, -245, -245, -245, -245, -245, -245, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 262, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -245, + -245 + + }, + + { + 5, -246, -246, -246, -246, -246, -246, -246, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 263, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -246, + -246 + }, + + { + 5, -247, -247, -247, -247, -247, -247, -247, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 264, 41, 41, 41, 41, 41, 41, -247, + -247 + + }, + + { + 5, -248, -248, -248, -248, -248, -248, -248, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 265, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -248, + -248 + }, + + { + 5, -249, -249, -249, -249, -249, -249, -249, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 266, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -249, + -249 + + }, + + { + 5, -250, -250, -250, -250, -250, -250, -250, 41, 41, + 41, 41, 41, 41, 41, 41, 267, 268, 41, 269, + 270, 41, 41, 41, 41, 41, 41, 41, 41, 271, + 41, 41, 272, 273, 41, 41, 41, 41, 41, -250, + -250 + }, + + { + 5, -251, -251, -251, -251, -251, -251, -251, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 274, 41, 41, 41, 41, 41, 41, -251, + -251 + + }, + + { + 5, -252, -252, -252, -252, -252, -252, -252, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 275, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -252, + -252 + }, + + { + 5, -253, -253, -253, -253, -253, -253, -253, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 276, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -253, + -253 + + }, + + { + 5, -254, -254, -254, -254, -254, -254, -254, 41, 41, + 41, 41, 41, 41, 41, 277, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -254, + -254 + }, + + { + 5, -255, -255, -255, -255, -255, -255, -255, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 278, 41, 41, 41, 41, 41, 41, 41, -255, + -255 + + }, + + { + 5, -256, -256, -256, -256, -256, -256, -256, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -256, + -256 + }, + + { + 5, -257, -257, -257, -257, -257, -257, -257, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 279, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -257, + -257 + + }, + + { + 5, -258, -258, -258, -258, -258, -258, -258, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 280, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -258, + -258 + }, + + { + 5, -259, -259, -259, -259, -259, -259, -259, 41, 41, + 41, 41, 41, 41, 41, 281, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -259, + -259 + + }, + + { + 5, -260, -260, -260, -260, -260, -260, -260, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 282, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -260, + -260 + }, + + { + 5, -261, -261, -261, -261, -261, -261, -261, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 283, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -261, + -261 + + }, + + { + 5, -262, -262, -262, -262, -262, -262, -262, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 284, 41, 41, 41, 41, 41, 41, -262, + -262 + }, + + { + 5, -263, -263, -263, -263, -263, -263, -263, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 285, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -263, + -263 + + }, + + { + 5, -264, -264, -264, -264, -264, -264, -264, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -264, + -264 + }, + + { + 5, -265, -265, -265, -265, -265, -265, -265, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -265, + -265 + + }, + + { + 5, -266, -266, -266, -266, -266, -266, -266, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 286, 41, 41, 41, 41, 41, 41, -266, + -266 + }, + + { + 5, -267, -267, -267, -267, -267, -267, -267, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 287, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -267, + -267 + + }, + + { + 5, -268, -268, -268, -268, -268, -268, -268, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 288, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -268, + -268 + }, + + { + 5, -269, -269, -269, -269, -269, -269, -269, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 289, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -269, + -269 + + }, + + { + 5, -270, -270, -270, -270, -270, -270, -270, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 290, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -270, + -270 + }, + + { + 5, -271, -271, -271, -271, -271, -271, -271, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 291, 41, 41, 41, 41, 41, 41, 41, -271, + -271 + + }, + + { + 5, -272, -272, -272, -272, -272, -272, -272, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 292, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 293, -272, + -272 + }, + + { + 5, -273, -273, -273, -273, -273, -273, -273, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 294, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -273, + -273 + + }, + + { + 5, -274, -274, -274, -274, -274, -274, -274, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -274, + -274 + }, + + { + 5, -275, -275, -275, -275, -275, -275, -275, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 295, 41, 41, 41, 41, 41, 41, -275, + -275 + + }, + + { + 5, -276, -276, -276, -276, -276, -276, -276, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 296, 41, 41, 41, 41, 41, 41, 41, -276, + -276 + }, + + { + 5, -277, -277, -277, -277, -277, -277, -277, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 297, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -277, + -277 + + }, + + { + 5, -278, -278, -278, -278, -278, -278, -278, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 298, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -278, + -278 + }, + + { + 5, -279, -279, -279, -279, -279, -279, -279, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 299, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -279, + -279 + + }, + + { + 5, -280, -280, -280, -280, -280, -280, -280, 41, 41, + 41, 41, 41, 41, 300, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -280, + -280 + }, + + { + 5, -281, -281, -281, -281, -281, -281, -281, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 301, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -281, + -281 + + }, + + { + 5, -282, -282, -282, -282, -282, -282, -282, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 302, 41, 41, 41, 41, 41, 41, -282, + -282 + }, + + { + 5, -283, -283, -283, -283, -283, -283, -283, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 303, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -283, + -283 + + }, + + { + 5, -284, -284, -284, -284, -284, -284, -284, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 304, 41, 41, 41, 41, 41, -284, + -284 + }, + + { + 5, -285, -285, -285, -285, -285, -285, -285, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 305, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -285, + -285 + + }, + + { + 5, -286, -286, -286, -286, -286, -286, -286, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -286, + -286 + }, + + { + 5, -287, -287, -287, -287, -287, -287, -287, 41, 41, + 41, 41, 41, 41, 306, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -287, + -287 + + }, + + { + 5, -288, -288, -288, -288, -288, -288, -288, 41, 41, + 41, 41, 41, 41, 41, 41, 307, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 308, 41, 41, 41, 41, 41, 41, -288, + -288 + }, + + { + 5, -289, -289, -289, -289, -289, -289, -289, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 309, 41, 41, 41, 41, 41, 41, 41, -289, + -289 + + }, + + { + 5, -290, -290, -290, -290, -290, -290, -290, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 310, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -290, + -290 + }, + + { + 5, -291, -291, -291, -291, -291, -291, -291, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 311, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -291, + -291 + + }, + + { + 5, -292, -292, -292, -292, -292, -292, -292, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 312, 41, 41, 41, 41, 41, -292, + -292 + }, + + { + 5, -293, -293, -293, -293, -293, -293, -293, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 313, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -293, + -293 + + }, + + { + 5, -294, -294, -294, -294, -294, -294, -294, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 314, 41, 41, 41, 41, 41, 41, 41, -294, + -294 + }, + + { + 5, -295, -295, -295, -295, -295, -295, -295, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -295, + -295 + + }, + + { + 5, -296, -296, -296, -296, -296, -296, -296, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 315, 41, 41, 41, 41, 41, 41, -296, + -296 + }, + + { + 5, -297, -297, -297, -297, -297, -297, -297, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 316, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -297, + -297 + + }, + + { + 5, -298, -298, -298, -298, -298, -298, -298, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 317, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -298, + -298 + }, + + { + 5, -299, -299, -299, -299, -299, -299, -299, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 318, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -299, + -299 + + }, + + { + 5, -300, -300, -300, -300, -300, -300, -300, 41, 41, + 41, 41, 41, 41, 41, 319, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -300, + -300 + }, + + { + 5, -301, -301, -301, -301, -301, -301, -301, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 320, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -301, + -301 + + }, + + { + 5, -302, -302, -302, -302, -302, -302, -302, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -302, + -302 + }, + + { + 5, -303, -303, -303, -303, -303, -303, -303, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -303, + -303 + + }, + + { + 5, -304, -304, -304, -304, -304, -304, -304, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -304, + -304 + }, + + { + 5, -305, -305, -305, -305, -305, -305, -305, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -305, + -305 + + }, + + { + 5, -306, -306, -306, -306, -306, -306, -306, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 321, 41, 41, 41, 41, -306, + -306 + }, + + { + 5, -307, -307, -307, -307, -307, -307, -307, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 322, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -307, + -307 + + }, + + { + 5, -308, -308, -308, -308, -308, -308, -308, 41, 41, + 41, 41, 41, 41, 41, 41, 323, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -308, + -308 + }, + + { + 5, -309, -309, -309, -309, -309, -309, -309, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 324, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -309, + -309 + + }, + + { + 5, -310, -310, -310, -310, -310, -310, -310, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 325, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -310, + -310 + }, + + { + 5, -311, -311, -311, -311, -311, -311, -311, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 326, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -311, + -311 + + }, + + { + 5, -312, -312, -312, -312, -312, -312, -312, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 327, 41, 41, 41, 41, 41, -312, + -312 + }, + + { + 5, -313, -313, -313, -313, -313, -313, -313, 41, 41, + 41, 41, 41, 41, 41, 328, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -313, + -313 + + }, + + { + 5, -314, -314, -314, -314, -314, -314, -314, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 329, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -314, + -314 + }, + + { + 5, -315, -315, -315, -315, -315, -315, -315, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -315, + -315 + + }, + + { + 5, -316, -316, -316, -316, -316, -316, -316, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -316, + -316 + }, + + { + 5, -317, -317, -317, -317, -317, -317, -317, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -317, + -317 + + }, + + { + 5, -318, -318, -318, -318, -318, -318, -318, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 330, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -318, + -318 + }, + + { + 5, -319, -319, -319, -319, -319, -319, -319, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 331, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -319, + -319 + + }, + + { + 5, -320, -320, -320, -320, -320, -320, -320, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 332, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -320, + -320 + }, + + { + 5, -321, -321, -321, -321, -321, -321, -321, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 333, 41, 41, 41, 41, 41, 41, -321, + -321 + + }, + + { + 5, -322, -322, -322, -322, -322, -322, -322, 41, 41, + 41, 41, 41, 41, 334, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -322, + -322 + }, + + { + 5, -323, -323, -323, -323, -323, -323, -323, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 335, 41, 41, 41, 41, 41, 41, 41, -323, + -323 + + }, + + { + 5, -324, -324, -324, -324, -324, -324, -324, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 336, 41, 41, 41, 41, -324, + -324 + }, + + { + 5, -325, -325, -325, -325, -325, -325, -325, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 337, 41, 41, 41, 41, 41, 41, 41, -325, + -325 + + }, + + { + 5, -326, -326, -326, -326, -326, -326, -326, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 338, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -326, + -326 + }, + + { + 5, -327, -327, -327, -327, -327, -327, -327, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 339, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -327, + -327 + + }, + + { + 5, -328, -328, -328, -328, -328, -328, -328, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 340, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -328, + -328 + }, + + { + 5, -329, -329, -329, -329, -329, -329, -329, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 341, 41, 41, 41, 41, 41, 41, -329, + -329 + + }, + + { + 5, -330, -330, -330, -330, -330, -330, -330, 41, 41, + 41, 41, 41, 41, 41, 41, 342, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -330, + -330 + }, + + { + 5, -331, -331, -331, -331, -331, -331, -331, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 343, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -331, + -331 + + }, + + { + 5, -332, -332, -332, -332, -332, -332, -332, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -332, + -332 + }, + + { + 5, -333, -333, -333, -333, -333, -333, -333, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 344, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -333, + -333 + + }, + + { + 5, -334, -334, -334, -334, -334, -334, -334, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 345, 41, 41, 41, 41, 41, 41, 41, -334, + -334 + }, + + { + 5, -335, -335, -335, -335, -335, -335, -335, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 346, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -335, + -335 + + }, + + { + 5, -336, -336, -336, -336, -336, -336, -336, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 347, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -336, + -336 + }, + + { + 5, -337, -337, -337, -337, -337, -337, -337, 41, 41, + 41, 41, 41, 41, 348, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -337, + -337 + + }, + + { + 5, -338, -338, -338, -338, -338, -338, -338, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -338, + -338 + }, + + { + 5, -339, -339, -339, -339, -339, -339, -339, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 349, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -339, + -339 + + }, + + { + 5, -340, -340, -340, -340, -340, -340, -340, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 350, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -340, + -340 + }, + + { + 5, -341, -341, -341, -341, -341, -341, -341, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -341, + -341 + + }, + + { + 5, -342, -342, -342, -342, -342, -342, -342, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 351, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -342, + -342 + }, + + { + 5, -343, -343, -343, -343, -343, -343, -343, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -343, + -343 + + }, + + { + 5, -344, -344, -344, -344, -344, -344, -344, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 352, 41, 41, 41, 41, 41, 41, -344, + -344 + }, + + { + 5, -345, -345, -345, -345, -345, -345, -345, 41, 41, + 41, 41, 41, 41, 353, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -345, + -345 + + }, + + { + 5, -346, -346, -346, -346, -346, -346, -346, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 354, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -346, + -346 + }, + + { + 5, -347, -347, -347, -347, -347, -347, -347, 41, 41, + 41, 41, 41, 41, 355, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -347, + -347 + + }, + + { + 5, -348, -348, -348, -348, -348, -348, -348, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 356, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -348, + -348 + }, + + { + 5, -349, -349, -349, -349, -349, -349, -349, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 357, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -349, + -349 + + }, + + { + 5, -350, -350, -350, -350, -350, -350, -350, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 358, 41, 41, 41, 41, 41, 41, -350, + -350 + }, + + { + 5, -351, -351, -351, -351, -351, -351, -351, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -351, + -351 + + }, + + { + 5, -352, -352, -352, -352, -352, -352, -352, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -352, + -352 + }, + + { + 5, -353, -353, -353, -353, -353, -353, -353, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 359, 41, 41, 41, 41, 41, -353, + -353 + + }, + + { + 5, -354, -354, -354, -354, -354, -354, -354, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 360, 41, 41, 41, 41, 41, -354, + -354 + }, + + { + 5, -355, -355, -355, -355, -355, -355, -355, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 361, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -355, + -355 + + }, + + { + 5, -356, -356, -356, -356, -356, -356, -356, 41, 41, + 41, 41, 41, 362, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -356, + -356 + }, + + { + 5, -357, -357, -357, -357, -357, -357, -357, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 363, 41, 41, 41, 41, 41, 41, -357, + -357 + + }, + + { + 5, -358, -358, -358, -358, -358, -358, -358, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -358, + -358 + }, + + { + 5, -359, -359, -359, -359, -359, -359, -359, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 364, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -359, + -359 + + }, + + { + 5, -360, -360, -360, -360, -360, -360, -360, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 365, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -360, + -360 + }, + + { + 5, -361, -361, -361, -361, -361, -361, -361, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -361, + -361 + + }, + + { + 5, -362, -362, -362, -362, -362, -362, -362, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 366, 41, 41, 41, 41, 41, 41, -362, + -362 + }, + + { + 5, -363, -363, -363, -363, -363, -363, -363, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -363, + -363 + + }, + + { + 5, -364, -364, -364, -364, -364, -364, -364, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 367, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -364, + -364 + }, + + { + 5, -365, -365, -365, -365, -365, -365, -365, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 368, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -365, + -365 + + }, + + { + 5, -366, -366, -366, -366, -366, -366, -366, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 369, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -366, + -366 + }, + + { + 5, -367, -367, -367, -367, -367, -367, -367, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 370, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -367, + -367 + + }, + + { + 5, -368, -368, -368, -368, -368, -368, -368, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 371, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -368, + -368 + }, + + { + 5, -369, -369, -369, -369, -369, -369, -369, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 372, 41, 41, 41, 41, 41, -369, + -369 + + }, + + { + 5, -370, -370, -370, -370, -370, -370, -370, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 373, 41, 41, 41, 41, 41, 41, -370, + -370 + }, + + { + 5, -371, -371, -371, -371, -371, -371, -371, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 374, 41, 41, 41, 41, 41, 41, -371, + -371 + + }, + + { + 5, -372, -372, -372, -372, -372, -372, -372, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 375, 41, 41, 41, 41, 41, -372, + -372 + }, + + { + 5, -373, -373, -373, -373, -373, -373, -373, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -373, + -373 + + }, + + { + 5, -374, -374, -374, -374, -374, -374, -374, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -374, + -374 + }, + + { + 5, -375, -375, -375, -375, -375, -375, -375, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 376, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -375, + -375 + + }, + + { + 5, -376, -376, -376, -376, -376, -376, -376, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 377, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -376, + -376 + }, + + { + 5, -377, -377, -377, -377, -377, -377, -377, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 378, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -377, + -377 + + }, + + { + 5, -378, -378, -378, -378, -378, -378, -378, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 379, 41, 41, 41, 41, 41, 41, -378, + -378 + }, + + { + 5, -379, -379, -379, -379, -379, -379, -379, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, + 41, 41, 41, 41, 41, 41, 41, 41, 41, -379, + -379 + + }, + + } ; + + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yytext_ptr -= yy_more_len; \ + yyleng = (int) (yy_cp - yytext_ptr); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 69 +#define YY_END_OF_BUFFER 70 +static yyconst short int yy_accept[380] = + { 0, + 0, 0, 0, 0, 70, 68, 65, 66, 57, 67, + 68, 67, 63, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 68, 60, 61, 65, 57, 59, 56, 63, + 64, 64, 64, 64, 64, 5, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 39, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 58, 60, + 61, 61, 62, 1, 64, 64, 64, 64, 7, 64, + 64, 64, 11, 64, 64, 64, 64, 64, 64, 64, + + 64, 64, 64, 64, 64, 64, 37, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 9, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 36, 64, 64, 64, 64, 64, 47, 64, 50, + 64, 52, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 14, 15, 64, 17, 64, 64, 64, + 64, 64, 64, 64, 64, 35, 64, 64, 64, 64, + 64, 64, 64, 48, 64, 64, 64, 64, 64, 2, + 3, 64, 6, 64, 64, 64, 64, 16, 18, 64, + + 20, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 49, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 19, 64, 64, 64, 24, 25, 64, + 64, 64, 64, 64, 64, 64, 64, 51, 53, 64, + 55, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 45, 64, 64, 64, 64, + 64, 64, 64, 21, 22, 64, 64, 64, 64, 64, + 64, 64, 64, 38, 40, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 23, 64, 64, 64, 64, + 64, 64, 64, 64, 41, 64, 64, 64, 64, 64, + + 64, 8, 10, 12, 13, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 42, 43, 44, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 4, 64, 64, 64, 64, 64, 31, 64, 64, + 34, 64, 54, 64, 64, 64, 64, 64, 64, 64, + 46, 26, 64, 64, 64, 64, 64, 33, 64, 64, + 29, 64, 32, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 27, 28, 64, 64, 64, 64, 30 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 4, 1, 1, 5, + 5, 6, 1, 5, 7, 5, 1, 8, 9, 8, + 8, 8, 8, 8, 8, 8, 8, 5, 1, 1, + 1, 1, 1, 1, 10, 10, 10, 11, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 5, 1, 5, 1, 13, 1, 14, 15, 16, 17, + + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 10, 39, 1, 40, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +static int yy_more_flag = 0; +static int yy_more_len = 0; +#define yymore() (yy_more_flag = 1) +#define YY_MORE_ADJ yy_more_len +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "dfgscanner.l" +#define INITIAL 0 +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SCANNER FOR DFG SYNTAX * */ +/* * * */ +/* * $Module: DFG * */ +/* * * */ +/* * Copyright (C) 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ +/* $RCSfile$ */ +#line 49 "dfgscanner.l" + +#include <ctype.h> /* for isprint */ +#include <errno.h> +#include "misc.h" +#include "memory.h" +#include "symbol.h" +#include "term.h" +#include "dfg.h" +#include "dfgparser.h" + +/* defined in dfgparser.y */ +extern NAT dfg_LINENUMBER; +extern BOOL dfg_IGNORETEXT; + +static NAT dfg_CountNewlines(char*); + +static __inline__ char* dfg_StringCopy(void) +{ + char *copy; + copy = (char*) memory_Malloc(yyleng+1); + strcpy(copy, yytext); + return copy; +} + +/* Force the scanner to read the input character by character */ +#define YY_ALWAYS_INTERACTIVE 1 +/* Omit unused function yyunput */ +#define YY_NO_UNPUT 1 +/* Start conditions */ +#define TXT 1 + +#line 3709 "dfgscanner.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 84 "dfgscanner.l" + + +#line 3863 "dfgscanner.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_more_len = 0; + if ( yy_more_flag ) + { + yy_more_len = yy_c_buf_p - yytext_ptr; + yy_more_flag = 0; + } + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + while ( (yy_current_state = yy_nxt[yy_current_state][yy_ec[YY_SC_TO_UI(*yy_cp)]]) > 0 ) + ++yy_cp; + + yy_current_state = -yy_current_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +YY_RULE_SETUP +#line 86 "dfgscanner.l" +return DFG_AND; + YY_BREAK +case 2: +YY_RULE_SETUP +#line 87 "dfgscanner.l" +return DFG_AUTHOR; + YY_BREAK +case 3: +YY_RULE_SETUP +#line 88 "dfgscanner.l" +return DFG_AXIOMS; + YY_BREAK +case 4: +YY_RULE_SETUP +#line 89 "dfgscanner.l" +return DFG_BEGPROB; + YY_BREAK +case 5: +YY_RULE_SETUP +#line 90 "dfgscanner.l" +return DFG_BY; + YY_BREAK +case 6: +YY_RULE_SETUP +#line 91 "dfgscanner.l" +return DFG_CLAUSE; + YY_BREAK +case 7: +YY_RULE_SETUP +#line 92 "dfgscanner.l" +return DFG_CNF; + YY_BREAK +case 8: +YY_RULE_SETUP +#line 93 "dfgscanner.l" +return DFG_CONJECS; + YY_BREAK +case 9: +YY_RULE_SETUP +#line 94 "dfgscanner.l" +return DFG_DATE; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 95 "dfgscanner.l" +return DFG_DESC; + YY_BREAK +case 11: +YY_RULE_SETUP +#line 96 "dfgscanner.l" +return DFG_DNF; + YY_BREAK +case 12: +YY_RULE_SETUP +#line 97 "dfgscanner.l" +return DFG_ENDLIST; + YY_BREAK +case 13: +YY_RULE_SETUP +#line 98 "dfgscanner.l" +return DFG_ENDPROB; + YY_BREAK +case 14: +YY_RULE_SETUP +#line 99 "dfgscanner.l" +return DFG_EQUAL; + YY_BREAK +case 15: +YY_RULE_SETUP +#line 100 "dfgscanner.l" +return DFG_EQUIV; + YY_BREAK +case 16: +YY_RULE_SETUP +#line 101 "dfgscanner.l" +return DFG_EXISTS; + YY_BREAK +case 17: +YY_RULE_SETUP +#line 102 "dfgscanner.l" +return DFG_FALSE; + YY_BREAK +case 18: +YY_RULE_SETUP +#line 103 "dfgscanner.l" +return DFG_FORALL; + YY_BREAK +case 19: +YY_RULE_SETUP +#line 104 "dfgscanner.l" +return DFG_FORMULA; + YY_BREAK +case 20: +YY_RULE_SETUP +#line 105 "dfgscanner.l" +return DFG_FREELY; + YY_BREAK +case 21: +YY_RULE_SETUP +#line 106 "dfgscanner.l" +return DFG_FUNC; + YY_BREAK +case 22: +YY_RULE_SETUP +#line 107 "dfgscanner.l" +return DFG_GENERATED; + YY_BREAK +case 23: +YY_RULE_SETUP +#line 108 "dfgscanner.l" +return DFG_HYPOTH; + YY_BREAK +case 24: +YY_RULE_SETUP +#line 109 "dfgscanner.l" +return DFG_IMPLIED; + YY_BREAK +case 25: +YY_RULE_SETUP +#line 110 "dfgscanner.l" +return DFG_IMPLIES; + YY_BREAK +case 26: +YY_RULE_SETUP +#line 111 "dfgscanner.l" +return DFG_CLSLIST; + YY_BREAK +case 27: +YY_RULE_SETUP +#line 112 "dfgscanner.l" +return DFG_DECLLIST; + YY_BREAK +case 28: +YY_RULE_SETUP +#line 113 "dfgscanner.l" +return DFG_DESCLIST; + YY_BREAK +case 29: +YY_RULE_SETUP +#line 114 "dfgscanner.l" +return DFG_FORMLIST; + YY_BREAK +case 30: +YY_RULE_SETUP +#line 115 "dfgscanner.l" +return DFG_GENSET; + YY_BREAK +case 31: +YY_RULE_SETUP +#line 116 "dfgscanner.l" +return DFG_PRFLIST; + YY_BREAK +case 32: +YY_RULE_SETUP +#line 117 "dfgscanner.l" +return DFG_SETTINGS; + YY_BREAK +case 33: +YY_RULE_SETUP +#line 118 "dfgscanner.l" +return DFG_SYMLIST; + YY_BREAK +case 34: +YY_RULE_SETUP +#line 119 "dfgscanner.l" +return DFG_TERMLIST; + YY_BREAK +case 35: +YY_RULE_SETUP +#line 120 "dfgscanner.l" +return DFG_LOGIC; + YY_BREAK +case 36: +YY_RULE_SETUP +#line 121 "dfgscanner.l" +return DFG_NAME; + YY_BREAK +case 37: +YY_RULE_SETUP +#line 122 "dfgscanner.l" +return DFG_NOT; + YY_BREAK +case 38: +YY_RULE_SETUP +#line 123 "dfgscanner.l" +return DFG_OPERAT; + YY_BREAK +case 39: +YY_RULE_SETUP +#line 124 "dfgscanner.l" +return DFG_OR; + YY_BREAK +case 40: +YY_RULE_SETUP +#line 125 "dfgscanner.l" +return DFG_PRED; + YY_BREAK +case 41: +YY_RULE_SETUP +#line 126 "dfgscanner.l" +return DFG_PRDICAT; + YY_BREAK +case 42: +YY_RULE_SETUP +#line 127 "dfgscanner.l" +return DFG_QUANTIF; + YY_BREAK +case 43: +YY_RULE_SETUP +#line 128 "dfgscanner.l" +return DFG_SATIS; + YY_BREAK +case 44: +YY_RULE_SETUP +#line 129 "dfgscanner.l" +return DFG_DOMPRED; + YY_BREAK +case 45: +YY_RULE_SETUP +#line 130 "dfgscanner.l" +return DFG_SETFLAG; + YY_BREAK +case 46: +YY_RULE_SETUP +#line 131 "dfgscanner.l" +return DFG_PREC; + YY_BREAK +case 47: +YY_RULE_SETUP +#line 132 "dfgscanner.l" +return DFG_SORT; + YY_BREAK +case 48: +YY_RULE_SETUP +#line 133 "dfgscanner.l" +return DFG_SORTS; + YY_BREAK +case 49: +YY_RULE_SETUP +#line 134 "dfgscanner.l" +return DFG_STATUS; + YY_BREAK +case 50: +YY_RULE_SETUP +#line 135 "dfgscanner.l" +return DFG_STEP; + YY_BREAK +case 51: +YY_RULE_SETUP +#line 136 "dfgscanner.l" +return DFG_SUBSORT; + YY_BREAK +case 52: +YY_RULE_SETUP +#line 137 "dfgscanner.l" +return DFG_TRUE; + YY_BREAK +case 53: +YY_RULE_SETUP +#line 138 "dfgscanner.l" +return DFG_UNKNOWN; + YY_BREAK +case 54: +YY_RULE_SETUP +#line 139 "dfgscanner.l" +return DFG_UNSATIS; + YY_BREAK +case 55: +YY_RULE_SETUP +#line 140 "dfgscanner.l" +return DFG_VERSION; + YY_BREAK +case 56: +YY_RULE_SETUP +#line 141 "dfgscanner.l" +return DFG_MINUS1; + YY_BREAK +case 57: +YY_RULE_SETUP +#line 143 "dfgscanner.l" +/* one-line comment */ + YY_BREAK +case 58: +YY_RULE_SETUP +#line 144 "dfgscanner.l" +{ /* Start of multiline comment */ + if (dfg_IGNORETEXT) { + BEGIN(TXT); + yymore(); + } else + return DFG_OPENBRACE; + } + YY_BREAK +case 59: +YY_RULE_SETUP +#line 151 "dfgscanner.l" +return DFG_CLOSEBRACE; + YY_BREAK +case 60: +YY_RULE_SETUP +#line 152 "dfgscanner.l" +yymore(); + YY_BREAK +case 61: +YY_RULE_SETUP +#line 153 "dfgscanner.l" +yymore(); + YY_BREAK +case 62: +YY_RULE_SETUP +#line 154 "dfgscanner.l" +{ BEGIN(INITIAL); + dfg_lval.string = dfg_StringCopy(); + dfg_LINENUMBER += dfg_CountNewlines(yytext); + return DFG_TEXT; + } + YY_BREAK +case 63: +YY_RULE_SETUP +#line 159 "dfgscanner.l" +{ unsigned long n; + errno = 0; + n = strtoul(yytext, NULL, 10); + if (errno != 0 || n > INT_MAX) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Number too big in line %d.\n", + dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + dfg_lval.number = (int) n; + return DFG_NUM; + } + YY_BREAK +case 64: +YY_RULE_SETUP +#line 171 "dfgscanner.l" +{ dfg_lval.string = dfg_StringCopy(); + return DFG_ID; + } + YY_BREAK +case 65: +YY_RULE_SETUP +#line 174 "dfgscanner.l" +/* ignore */ + YY_BREAK +case 66: +YY_RULE_SETUP +#line 175 "dfgscanner.l" +dfg_LINENUMBER++; + YY_BREAK +case 67: +YY_RULE_SETUP +#line 176 "dfgscanner.l" +return yytext[0]; + YY_BREAK +case 68: +YY_RULE_SETUP +#line 177 "dfgscanner.l" +{ misc_StartUserErrorReport(); + misc_UserErrorReport("\n Illegal character '"); + if (isprint((int)yytext[0])) + misc_UserErrorReport("%c",yytext[0]); + else + misc_UserErrorReport("\\x%x", (unsigned int) yytext[0]); + misc_UserErrorReport("' in line %d.\n", dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + YY_BREAK +case 69: +YY_RULE_SETUP +#line 187 "dfgscanner.l" +ECHO; + YY_BREAK +#line 4301 "dfgscanner.c" + case YY_STATE_EOF(INITIAL): + case YY_STATE_EOF(TXT): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + + yy_current_state = yy_nxt[yy_current_state][1]; + yy_is_jam = (yy_current_state <= 0); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 187 "dfgscanner.l" + + +static NAT dfg_CountNewlines(char* Text) +{ + NAT result = 0; + + while (*Text != 0) { + if (*Text++ == '\n') + result++; + } + return result; +} diff --git a/test/spass/doc-proof.c b/test/spass/doc-proof.c new file mode 100644 index 0000000000000000000000000000000000000000..dadd69834c9ce2151c4660b19654c1e536a1199a --- /dev/null +++ b/test/spass/doc-proof.c @@ -0,0 +1,247 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * PROOF DOCUMENTATION * */ +/* * * */ +/* * $Module: DOCPROOF * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "doc-proof.h" + +/**************************************************************/ +/* Global Variables */ +/**************************************************************/ + +int dp_DEPTH; + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +void dp_Init(void) +{ + dp_DEPTH = 0; +} + + +static void dp_FPrintDFGProof(LIST Clauses, const char *FilePrefix, + FLAGSTORE Flags, PRECEDENCE Precedence) +/********************************************************* + INPUT: A list of clauses representing a proof, a + string indicating a file name prefix, a flag + store and a precedence. + RETURNS: void. + EFFECT: Outputs the proof in DFG proof format to + <FilePrefix>.prf +**********************************************************/ +{ + FILE *Output; + CLAUSE Clause; + LIST AxClauses,ConClauses,ProofClauses,Scan; + char *name; + + AxClauses = ConClauses = ProofClauses = list_Nil(); + + name = memory_Malloc(sizeof(char)*(strlen(FilePrefix)+5)); + sprintf(name,"%s.prf", FilePrefix); + + Output = misc_OpenFile(name,"w"); + + fputs("begin_problem(Unknown).\n\n", Output); + + fputs("list_of_descriptions.\n", Output); + fputs("name({*", Output); + fputs(FilePrefix, Output); + fputs("*}).\n", Output); + fputs("author({*SPASS ", Output); + fputs(misc_VERSION, Output); + fputs("*}).\n", Output); + fputs("status(unsatisfiable).\n", Output); + fputs("description({*File generated by SPASS containing a proof.*}).\n", Output); + fputs("end_of_list.\n\n", Output); + + fputs("list_of_symbols.\n", Output); + fol_FPrintDFGSignature(Output); + fputs("end_of_list.\n\n", Output); + + for (Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Clause = (CLAUSE)list_Car(Scan); + if (clause_IsFromInput(Clause)) { + if (clause_GetFlag(Clause, CONCLAUSE)) + ConClauses = list_Cons(Clause, ConClauses); + else + AxClauses = list_Cons(Clause, AxClauses); + } + else + ProofClauses = list_Cons(Clause, ProofClauses); + } + + ConClauses = list_NReverse(ConClauses); + AxClauses = list_NReverse(AxClauses); + ProofClauses = list_NReverse(ProofClauses); + + clause_FPrintCnfDFG(Output, FALSE, AxClauses, ConClauses, Flags, Precedence); + fputs("\nlist_of_proof(SPASS).\n", Output); + for (Scan=ProofClauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) { + clause_FPrintDFGStep(Output,list_Car(Scan),TRUE); + } + fputs("end_of_list.\n\n", Output); + + fputs("end_problem.\n\n", Output); + + misc_CloseFile(Output, name); + fputs("\nDFG Proof printed to: ", stdout); + puts(name); + + list_Delete(ConClauses); + list_Delete(AxClauses); + list_Delete(ProofClauses); + memory_Free(name, sizeof(char)*(strlen(FilePrefix)+5)); +} + +LIST dp_PrintProof(PROOFSEARCH Search, LIST Clauses, const char *FilePrefix) +/********************************************************* + INPUT: A proofsearch object, a list of empty clauses and + the prefix of the output file name. + RETURNS: The list of clauses required for the proof. + MEMORY: The returned list must be freed. + EFFECT: The proof is printed both to standard output and + to the file <FilePrefix>.prf. +**********************************************************/ +{ + LIST ProofClauses,Scan,EmptyClauses,AllClauses, ReducedProof; + LIST Missing, Incomplete, SplitClauses; + + FLAGSTORE Flags; + + Flags = prfs_Store(Search); + + Missing = pcheck_ConvertParentsInSPASSProof(Search, Clauses); + + if (!list_Empty(Missing)) { + puts("\nNOTE: clauses with following numbers have not been found:"); + for (; !list_Empty(Missing); Missing = list_Pop(Missing)) + printf("%d ", (int)list_Car(Missing)); + putchar('\n'); + } + + EmptyClauses = list_Copy(Clauses); + ProofClauses = list_Nil(); + AllClauses = list_Nconc(list_Copy(prfs_DocProofClauses(Search)), + list_Nconc(list_Copy(prfs_UsableClauses(Search)), + list_Copy(prfs_WorkedOffClauses(Search)))); + + /* + * collect proof clauses by noodling upward in the + * proof tree, starting from <EmptyClauses>. + * Before, add all splitting clauses to avoid gaps in split tree + */ + + SplitClauses = list_Nil(); + for (Scan = AllClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (clause_IsFromSplitting(list_Car(Scan))) + SplitClauses = list_Cons(list_Car(Scan), SplitClauses); + + /* mark all needed clauses */ + pcheck_ClauseListRemoveFlag(EmptyClauses, MARKED); + pcheck_ClauseListRemoveFlag(AllClauses, MARKED); + pcheck_MarkRecursive(EmptyClauses); + pcheck_MarkRecursive(SplitClauses); + + /* collect all marked clauses */ + ProofClauses = list_Nil(); + for (Scan = AllClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (clause_GetFlag(list_Car(Scan), MARKED)) + ProofClauses = list_Cons(list_Car(Scan), ProofClauses); + } + + /* build reduced proof */ + ProofClauses = list_Nconc(ProofClauses, list_Copy(EmptyClauses)); + ProofClauses = pcheck_ClauseNumberMergeSort(ProofClauses); + ReducedProof = pcheck_ReduceSPASSProof(ProofClauses); + + dp_SetProofDepth(pcheck_SeqProofDepth(ReducedProof)); + + pcheck_ParentPointersToParentNumbers(AllClauses); + pcheck_ParentPointersToParentNumbers(Clauses); + + /* check reduced proof for clauses whose parents have been marked as + incomplete (HIDDEN flag) by ConvertParentsInSPASSProof */ + + Incomplete = list_Nil(); + for (Scan = ReducedProof; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (clause_GetFlag(list_Car(Scan), HIDDEN)) + Incomplete = list_Cons(list_Car(Scan), Incomplete); + } + if (!list_Empty(Incomplete)) { + puts("NOTE: Following clauses in reduced proof have incomplete parent sets:"); + for (Scan = Incomplete; !list_Empty(Scan); Scan = list_Cdr(Scan)) + printf("%d ", clause_Number(list_Car(Scan))); + putchar('\n'); + } + + printf("\n\nHere is a proof with depth %d, length %d :\n", + dp_ProofDepth(), list_Length(ReducedProof)); + clause_ListPrint(ReducedProof); + + if (flag_GetFlagValue(Flags, flag_FPDFGPROOF)) + dp_FPrintDFGProof(ReducedProof, FilePrefix, Flags, prfs_Precedence(Search)); + + fflush(stdout); + + list_Delete(EmptyClauses); + list_Delete(AllClauses); + list_Delete(ProofClauses); + list_Delete(SplitClauses); + list_Delete(Incomplete); + + return ReducedProof; +} + + + + diff --git a/test/spass/doc-proof.h b/test/spass/doc-proof.h new file mode 100644 index 0000000000000000000000000000000000000000..327cb4e94d223b48d1d4632d41cb4599ecc48091 --- /dev/null +++ b/test/spass/doc-proof.h @@ -0,0 +1,91 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * PROOF DOCUMENTATION * */ +/* * * */ +/* * $Module: DOCPROOF * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _DOC_PROOF_ +#define _DOC_PROOF_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "clause.h" +#include "st.h" +#include "sharing.h" +#include "search.h" +#include "doc-proof.h" +#include "proofcheck.h" + +/**************************************************************/ +/* Data Structures and Constants */ +/**************************************************************/ + +extern int dp_DEPTH; + + +/**************************************************************/ +/* Macros */ +/**************************************************************/ + +static __inline__ int dp_ProofDepth(void) +{ + return dp_DEPTH; +} + +static __inline__ void dp_SetProofDepth(int Depth) +{ + dp_DEPTH = Depth; +} + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +void dp_Init(void); +LIST dp_PrintProof(PROOFSEARCH, LIST, const char*); + +#endif diff --git a/test/spass/flags.c b/test/spass/flags.c new file mode 100644 index 0000000000000000000000000000000000000000..5cebfc610e24e164d7f2813295ddf172d1171c55 --- /dev/null +++ b/test/spass/flags.c @@ -0,0 +1,810 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * FLAGS OF SPASS * */ +/* * * */ +/* * $Module: FLAGS * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 35442 $ * */ +/* $State$ * */ +/* $Date: 2007-03-28 17:24:40 -0700 (Wed, 28 Mar 2007) $ * */ +/* $Author: jeffc $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include <stdio.h> +#include <string.h> + +#include "flags.h" +#include "misc.h" +#include "stringsx.h" + +/**************************************************************/ +/* Global Declarations */ +/**************************************************************/ + +const int flag_CLEAN = -5; + + +/**************************************************************/ +/* File Local Declarations */ +/**************************************************************/ + +/* Define flag properties */ +typedef struct { + int minimum; + int maximum; + FLAG_TYPE type; + const char *name; +} FLAG_PROPERTY; + + +static FLAGARRAY flag_DEFAULTSTORE; +static FLAG_PROPERTY flag_PROPERTIES[flag_MAXFLAG]; + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +static __inline__ void flag_InitIntern (FLAG_ID Flag, FLAG_TYPE Type, + const char *Name, int Value, + int Minimum, int Maximum) +{ + FLAG_PROPERTY *property; + + flag_CheckFlagIdInRange(Flag); + + property = &(flag_PROPERTIES[Flag]); + + /* Set the flag type */ + flag_CheckFlagTypeInRange(Type); + property->type = Type; + + /* Set flag name */ + property->name = Name; + + /* Set flag minimum and maximum */ + property->minimum = Minimum; + property->maximum = Maximum; + + /* Set flag value */ +#ifdef CHECK + if (Value > Minimum && Value < Maximum) { +#endif + + flag_DEFAULTSTORE[Flag] = Value; + +#ifdef CHECK + } + else { + misc_StartErrorReport(); + misc_ErrorReport("\n In flag_InitIntern: Default value out of range."); + misc_ErrorReport("\n Flag: %s. Value: %d.", Name, Value); + misc_FinishErrorReport(); + } +#endif +} + +void flag_Init(void) +/************************************************************** + INPUT: None. + RETURNS: Nothing. + EFFECT: Sets all default values for known flags. + MEMORY: Allocates memory for the default store. +***************************************************************/ +{ + /* Autonomous mode */ + flag_InitIntern(flag_AUTO, flag_UNIQUE, "Auto", flag_AUTOON, + flag_AUTOMIN, flag_AUTOMAX); + + /* Set of Support Mode */ + flag_InitIntern(flag_SOS, flag_UNIQUE, "SOS", flag_SOSOFF, + flag_SOSMIN, flag_SOSMAX); + + /* If set input is considered from stdin and printed to stdout */ + flag_InitIntern(flag_STDIN, flag_UNIQUE, "Stdin", flag_STDINOFF, + flag_STDINMIN, flag_STDINMAX); + + /* If set interactive queries are possible */ + flag_InitIntern(flag_INTERACTIVE, flag_UNIQUE, "Interactive", flag_INTERACTIVEOFF, + flag_INTERACTIVEMIN, flag_INTERACTIVEMAX); + + /* If set only Flotter CNF-translation is performed */ + flag_InitIntern(flag_FLOTTER, flag_UNIQUE, "Flotter", flag_FLOTTEROFF, + flag_FLOTTERMIN, flag_FLOTTERMAX); + + /* Allowed number of loops, -1 means no restriction */ + flag_InitIntern(flag_LOOPS, flag_UNIQUE, "Loops", flag_LOOPSUNLIMITED, + flag_LOOPSMIN, flag_LOOPSMAX); + + /* Allowed number of splits, -1 means no restriction */ + flag_InitIntern(flag_SPLITS, flag_UNIQUE, "Splits", flag_SPLITSOFF, + flag_SPLITSMIN, flag_SPLITSMAX); + + /* Decides the level of sort usage: if 0 then no sort information is processed, + if 1 all negative monadic literals with a variable as its argument are processed, + if 2 all negative monadic literals are processed */ + flag_InitIntern(flag_SORTS, flag_UNIQUE, "Sorts", flag_SORTSOFF, + flag_SORTSMIN, flag_SORTSMAX); + + /* ForwardSubsumption output not activated */ + flag_InitIntern(flag_PSUB, flag_PRINTING, "PSub", flag_PSUBOFF, + flag_PSUBMIN, flag_PSUBMAX); + + /* Maximal memory allocation */ + flag_InitIntern(flag_MEMORY, flag_UNIQUE, "Memory", flag_MEMORYUNLIMITED, + flag_MEMORYMIN, flag_MEMORYMAX); + + /* Document static soft typing */ + flag_InitIntern(flag_DOCSST, flag_PRINTING, "DocSST", flag_DOCSSTOFF, + flag_DOCSSTMIN, flag_DOCSSTMAX); + + /* Rewriting output not activated */ + flag_InitIntern(flag_PREW, flag_PRINTING, "PRew", flag_PREWOFF, + flag_PREWMIN, flag_PREWMAX); + + /* Contextual rewriting output not activated */ + flag_InitIntern(flag_PCRW, flag_PRINTING, "PCRw", flag_PCRWOFF, + flag_PCRWMIN, flag_PCRWMAX); + + /* Condensing output not activated */ + flag_InitIntern(flag_PCON, flag_PRINTING, "PCon", flag_PCONOFF, + flag_PCONMIN, flag_PCONMAX); + + /* Assignment Equation Deletion output not activated */ + flag_InitIntern(flag_PAED, flag_PRINTING, "PAED", flag_PAEDOFF, + flag_PAEDMIN, flag_PAEDMAX); + + /* Tautology output not activated */ + flag_InitIntern(flag_PTAUT, flag_PRINTING, "PTaut", flag_PTAUTOFF, + flag_PTAUTMIN, flag_PTAUTMAX); + + /* Output of obvious red. not activated */ + flag_InitIntern(flag_POBV, flag_PRINTING, "PObv", flag_POBVOFF, + flag_POBVMIN, flag_POBVMAX); + + /* SortSimplification output not activated */ + flag_InitIntern(flag_PSSI, flag_PRINTING, "PSSi", flag_PSSIOFF, + flag_PSSIMIN, flag_PSSIMAX); + + /* Static soft typing output not activated */ + flag_InitIntern(flag_PSST, flag_PRINTING, "PSST", flag_PSSTOFF, + flag_PSSTMIN, flag_PSSTMAX); + + /* Proof output not activated */ + flag_InitIntern(flag_DOCPROOF, flag_UNIQUE, "DocProof", flag_DOCPROOFOFF, + flag_DOCPROOFMIN, flag_DOCPROOFMAX); + + /* Matching Replacement Resolution output not activated */ + flag_InitIntern(flag_PMRR, flag_PRINTING, "PMRR", flag_PMRROFF, + flag_PMRRMIN, flag_PMRRMAX); + + /* Unit conflict output not activated */ + flag_InitIntern(flag_PUNC, flag_PRINTING, "PUnC", flag_PUNCOFF, + flag_PUNCMIN, flag_PUNCMAX); + + /* Derived clauses output not activated */ + flag_InitIntern(flag_PDER, flag_PRINTING, "PDer", flag_PDEROFF, + flag_PDERMIN, flag_PDERMAX); + + /* Given clause output activated */ + flag_InitIntern(flag_PGIVEN, flag_PRINTING, "PGiven", flag_PGIVENON, + flag_PGIVENMIN, flag_PGIVENMAX); + + /* If labels are created they are not printed */ + flag_InitIntern(flag_PLABELS, flag_PRINTING, "PLabels", flag_PLABELSOFF, + flag_PLABELSMIN, flag_PLABELSMAX); + + /* Kept clauses output not activated */ + flag_InitIntern(flag_PKEPT, flag_PRINTING, "PKept", flag_PKEPTOFF, + flag_PKEPTMIN, flag_PKEPTMAX); + + /* Split backtrack emphasizing not activated */ + flag_InitIntern(flag_DOCSPLIT, flag_PRINTING, "DocSplit", flag_DOCSPLITOFF, + flag_DOCSPLITMIN, flag_DOCSPLITMAX); + + /* Print information about input clauses */ + flag_InitIntern(flag_PPROBLEM, flag_PRINTING, "PProblem", flag_PPROBLEMON, + flag_PPROBLEMMIN, flag_PPROBLEMMAX); + + /* Print all derived empty clauses */ + flag_InitIntern(flag_PEMPTYCLAUSE, flag_PRINTING, "PEmptyClause", flag_PEMPTYCLAUSEOFF, + flag_PEMPTYCLAUSEMIN, flag_PEMPTYCLAUSEMAX); + + /* Print statistic about memory, clauses */ + flag_InitIntern(flag_PSTATISTIC, flag_PRINTING, "PStatistic", flag_PSTATISTICON, + flag_PSTATISTICMIN, flag_PSTATISTICMAX); + + /* Output saturated set of clauses to file, default no */ + flag_InitIntern(flag_FPMODEL, flag_PRINTING, "FPModel", flag_FPMODELOFF, + flag_FPMODELMIN, flag_FPMODELMAX); + + /* Output proof in DFG format to file, default no */ + flag_InitIntern(flag_FPDFGPROOF, flag_PRINTING, "FPDFGProof", flag_FPDFGPROOFOFF, + flag_FPDFGPROOFMIN, flag_FPDFGPROOFMAX); + + /* Output the actual values of all SPASS flags */ + flag_InitIntern(flag_PFLAGS, flag_PRINTING, "PFlags", flag_PFLAGSOFF, + flag_PFLAGSMIN, flag_PFLAGSMAX); + + /* Optimized skolemization output not activated */ + flag_InitIntern(flag_POPTSKOLEM, flag_PRINTING, "POptSkolem", flag_POPTSKOLEMOFF, + flag_POPTSKOLEMMIN, flag_POPTSKOLEMMAX); + + /* Strong skolemization output not activated */ + flag_InitIntern(flag_PSTRSKOLEM, flag_PRINTING, "PStrSkolem", flag_PSTRSKOLEMOFF, + flag_PSTRSKOLEMMIN, flag_PSTRSKOLEMMAX); + + /* Printing of clauses deleted by bound restriction not activated */ + flag_InitIntern(flag_PBDC, flag_PRINTING, "PBDC", flag_PBDCOFF, + flag_PBDCMIN, flag_PBDCMAX); + + /* Printing of bound increase actions */ + flag_InitIntern(flag_PBINC, flag_PRINTING, "PBInc", flag_PBINCOFF, + flag_PBINCMIN, flag_PBINCMAX); + + /* Application of definitions output activated */ + flag_InitIntern(flag_PAPPLYDEFS, flag_PRINTING, "PApplyDefs", flag_PAPPLYDEFSOFF, + flag_PAPPLYDEFSMIN, flag_PAPPLYDEFSMAX); + + /* Amount of time (seconds) available to SPASS, -1 means arbitrary */ + flag_InitIntern(flag_TIMELIMIT, flag_UNIQUE, "TimeLimit", flag_TIMELIMITUNLIMITED, + flag_TIMELIMITMIN, flag_TIMELIMITMAX); + + /* Select: 0 -> no selection, 1 -> select if multiple maximal literals, 2 -> always select */ + flag_InitIntern(flag_SELECT, flag_UNIQUE, "Select", flag_SELECTIFSEVERALMAXIMAL, + flag_SELECTMIN, flag_SELECTMAX); + + /* Activates the inference rule Empty Sort */ + flag_InitIntern(flag_IEMS, flag_INFERENCE, "IEmS", flag_EMPTYSORTOFF, + flag_EMPTYSORTMIN, flag_EMPTYSORTMAX); + + /* Activates the inference rule Sort Resolution */ + flag_InitIntern(flag_ISOR, flag_INFERENCE, "ISoR", flag_SORTRESOLUTIONOFF, + flag_SORTRESOLUTIONMIN, flag_SORTRESOLUTIONMAX); + + /* Activates the inference rule Equality Resolution */ + flag_InitIntern(flag_IEQR, flag_INFERENCE, "IEqR", flag_EQUALITYRESOLUTIONOFF, + flag_EQUALITYRESOLUTIONMIN, flag_EQUALITYRESOLUTIONMAX); + + /* Activates the inference rule Reflexivity Resolution */ + flag_InitIntern(flag_IERR, flag_INFERENCE, "IERR", flag_REFLEXIVITYRESOLUTIONOFF, + flag_REFLEXIVITYRESOLUTIONMIN, flag_REFLEXIVITYRESOLUTIONMAX); + + /* Activates the inference rule Equality Factoring */ + flag_InitIntern(flag_IEQF, flag_INFERENCE, "IEqF", flag_EQUALITYFACTORINGOFF, + flag_EQUALITYFACTORINGMIN, flag_EQUALITYFACTORINGMAX); + + /* Activates the inference rule Merging Paramodulation */ + flag_InitIntern(flag_IMPM, flag_INFERENCE, "IMPm", flag_MERGINGPARAMODULATIONOFF, + flag_MERGINGPARAMODULATIONMIN, flag_MERGINGPARAMODULATIONMAX); + + /* Activates the inference rule Superposition Right */ + flag_InitIntern(flag_ISPR, flag_INFERENCE, "ISpR", flag_SUPERPOSITIONRIGHTOFF, + flag_SUPERPOSITIONRIGHTMIN, flag_SUPERPOSITIONRIGHTMAX); + + /* Inference rule Ordered Paramodulation not active */ + flag_InitIntern(flag_IOPM, flag_INFERENCE, "IOPm", flag_ORDEREDPARAMODULATIONOFF, + flag_ORDEREDPARAMODULATIONMIN, flag_ORDEREDPARAMODULATIONMAX); + + /* Inference rule Paramodulation not active */ + flag_InitIntern(flag_ISPM, flag_INFERENCE, "ISPm", flag_STANDARDPARAMODULATIONOFF, + flag_STANDARDPARAMODULATIONMIN, flag_STANDARDPARAMODULATIONMAX); + + /* Activates the inference rule Superposition Left */ + flag_InitIntern(flag_ISPL, flag_INFERENCE, "ISpL", flag_SUPERPOSITIONLEFTOFF, + flag_SUPERPOSITIONLEFTMIN, flag_SUPERPOSITIONLEFTMAX); + + /* Activates the inference rule Ordered Resolution */ + flag_InitIntern(flag_IORE, flag_INFERENCE, "IORe", flag_ORDEREDRESOLUTIONOFF, + flag_ORDEREDRESOLUTIONMIN, flag_ORDEREDRESOLUTIONMAX); + + /* Activates the inference rule Standard Resolution */ + flag_InitIntern(flag_ISRE, flag_INFERENCE, "ISRe", flag_STANDARDRESOLUTIONOFF, + flag_STANDARDRESOLUTIONMIN, flag_STANDARDRESOLUTIONMAX); + + /* Activates the inference rule Standard Hyperresolution */ + flag_InitIntern(flag_ISHY, flag_INFERENCE, "ISHy", flag_STANDARDHYPERRESOLUTIONOFF, + flag_STANDARDHYPERRESOLUTIONMIN, flag_STANDARDHYPERRESOLUTIONMAX); + + /* Activates the inference rule Ordered Hyperresolution */ + flag_InitIntern(flag_IOHY, flag_INFERENCE, "IOHy", flag_ORDEREDHYPERRESOLUTIONOFF, + flag_ORDEREDHYPERRESOLUTIONMIN, flag_ORDEREDHYPERRESOLUTIONMAX); + + /* Activates the inference rule UR Resolution */ + flag_InitIntern(flag_IURR, flag_INFERENCE, "IURR", flag_UNITRESULTINGRESOLUTIONOFF, + flag_UNITRESULTINGRESOLUTIONMIN, flag_UNITRESULTINGRESOLUTIONMAX); + + /* Activates the inference rule Ordered Factoring */ + flag_InitIntern(flag_IOFC, flag_INFERENCE, "IOFc", flag_FACTORINGOFF, + flag_FACTORINGMIN, flag_FACTORINGMAX); + + /* Activates the inference rule Standard Factoring */ + flag_InitIntern(flag_ISFC, flag_INFERENCE, "ISFc", flag_STANDARDFACTORINGOFF, + flag_STANDARDFACTORINGMIN, flag_STANDARDFACTORINGMAX); + + /* Activates the inference rule Bounded Unit Resolution */ + flag_InitIntern(flag_IBUR, flag_INFERENCE, "IBUR", flag_BOUNDEDDEPTHUNITRESOLUTIONOFF, + flag_BOUNDEDDEPTHUNITRESOLUTIONMIN, flag_BOUNDEDDEPTHUNITRESOLUTIONMAX); + + /* Activates the inference rule Definition Application */ + flag_InitIntern(flag_IDEF, flag_INFERENCE, "IDEF", flag_DEFINITIONAPPLICATIONOFF, + flag_DEFINITIONAPPLICATIONMIN, flag_DEFINITIONAPPLICATIONMAX); + + /* Activates the inference rule Unit Resolution */ + flag_InitIntern(flag_IUNR, flag_INFERENCE, "IUnR", flag_UNITRESOLUTIONOFF, + flag_UNITRESOLUTIONMIN, flag_UNITRESOLUTIONMAX); + + /* Activates Forward Rewriting */ + flag_InitIntern(flag_RFREW, flag_REDUCTION, "RFRew", flag_RFREWOFF, + flag_RFREWMIN, flag_RFREWMAX); + + /* Activates Backward Rewriting */ + flag_InitIntern(flag_RBREW, flag_REDUCTION, "RBRew", flag_RBREWOFF, + flag_RBREWMIN, flag_RBREWMAX); + + /* Activates Forward Contextual Rewriting */ + flag_InitIntern(flag_RFCRW, flag_REDUCTION, "RFCRw", flag_RFCRWOFF, + flag_RFCRWMIN, flag_RFCRWMAX); + + /* Activates Backward Contextual Rewriting */ + flag_InitIntern(flag_RBCRW, flag_REDUCTION, "RBCRw", flag_RBCRWOFF, + flag_RBCRWMIN, flag_RBCRWMAX); + + /* Activates Unit Conflict */ + flag_InitIntern(flag_RUNC, flag_REDUCTION, "RUnC", flag_RUNCOFF, + flag_RUNCMIN, flag_RUNCMAX); + + /* Activates Terminator */ + flag_InitIntern(flag_RTER, flag_REDUCTION, "RTer", flag_RTEROFF, + flag_RTERMIN, flag_RTERMAX); + + /* Activates Forward Subsumption */ + flag_InitIntern(flag_RFSUB, flag_REDUCTION, "RFSub", flag_RFSUBOFF, + flag_RFSUBMIN, flag_RFSUBMAX); + + /* Activates Backward Subsumption */ + flag_InitIntern(flag_RBSUB, flag_REDUCTION, "RBSub", flag_RBSUBOFF, + flag_RBSUBMIN, flag_RBSUBMAX); + + /* Activates Forward Matching Replacement Resolution */ + flag_InitIntern(flag_RFMRR, flag_REDUCTION, "RFMRR", flag_RFMRROFF, + flag_RFMRRMIN, flag_RFMRRMAX); + + /* Activates Backward Matching Replacement Resolution */ + flag_InitIntern(flag_RBMRR, flag_REDUCTION, "RBMRR", flag_RBMRROFF, + flag_RBMRRMIN, flag_RBMRRMAX); + + /* Activates the reduction rule Obvious Reduction */ + flag_InitIntern(flag_ROBV, flag_REDUCTION, "RObv", flag_ROBVOFF, + flag_ROBVMIN, flag_ROBVMAX); + + /* Activates the reduction rule Tautology */ + flag_InitIntern(flag_RTAUT, flag_REDUCTION, "RTaut", flag_RTAUTOFF, + flag_RTAUTMIN, flag_RTAUTMAX); + + /* Activates the reduction rule Sort Simplification */ + flag_InitIntern(flag_RSSI, flag_REDUCTION, "RSSi", flag_RSSIOFF, + flag_RSSIMIN, flag_RSSIMAX); + + /* Activates static soft typing */ + flag_InitIntern(flag_RSST, flag_REDUCTION, "RSST", flag_RSSTOFF, + flag_RSSTMIN, flag_RSSTMAX); + + /* Activates Assignment Equation Deletion */ + /* If set to 2 it also eliminates equations */ + /* that are redundant only in non-trivial domains */ + flag_InitIntern(flag_RAED, flag_REDUCTION, "RAED", flag_RAEDOFF, + flag_RAEDMIN, flag_RAEDMAX); + + /* Activates Condensing */ + flag_InitIntern(flag_RCON, flag_REDUCTION, "RCon", flag_RCONOFF, + flag_RCONMIN, flag_RCONMAX); + + /* Activates reduction of input clauses */ + flag_InitIntern(flag_RINPUT, flag_UNIQUE, "RInput", flag_RINPUTON, + flag_RINPUTMIN, flag_RINPUTMAX); + + /* Activates application of definitions */ + flag_InitIntern(flag_APPLYDEFS, flag_UNIQUE, "ApplyDefs", flag_APPLYDEFSOFF, + flag_APPLYDEFSMIN, flag_APPLYDEFSMAX); + + /* If true usable and worked off are completely interreduced; otherwise only worked off */ + flag_InitIntern(flag_FULLRED, flag_UNIQUE, "FullRed", flag_FULLREDON, + flag_FULLREDMIN, flag_FULLREDMAX); + + /* Activates unit saturation of input clauses */ + flag_InitIntern(flag_SATINPUT, flag_UNIQUE, "SatInput", flag_SATINPUTOFF, + flag_SATINPUTMIN, flag_SATINPUTMAX); + + /* Ratio between weight and depth selection of clauses from usable */ + flag_InitIntern(flag_WDRATIO, flag_UNIQUE, "WDRatio", 5, + flag_WDRATIOMIN, flag_WDRATIOMAX); + + /* Factor to divide the weight of conjecture clauses to prefer them for selection */ + flag_InitIntern(flag_PREFCON, flag_UNIQUE, "PrefCon", flag_PREFCONUNCHANGED, + flag_PREFCONMIN, flag_PREFCONMAX); + + /* Weight of a function symbol; weight of clause is used to select given */ + flag_InitIntern(flag_FUNCWEIGHT, flag_UNIQUE, "FuncWeight", 1, + flag_FUNCWEIGHTMIN, flag_FUNCWEIGHTMAX); + + /* Weight of a variable symbol; weight of clause is used to select given */ + flag_InitIntern(flag_VARWEIGHT, flag_UNIQUE, "VarWeight", 1, + flag_VARWEIGHTMIN, flag_VARWEIGHTMAX); + + /* Prefer the selection of clauses with many variable occurrences */ + flag_InitIntern(flag_PREFVAR, flag_UNIQUE, "PrefVar", flag_PREFVAROFF, + flag_PREFVARMIN, flag_PREFVARMAX); + + /* The type of bound: 0 (no bound) 1 (by clause weight) 2 (by clause term depth) */ + flag_InitIntern(flag_BOUNDMODE, flag_UNIQUE, "BoundMode", flag_BOUNDMODEUNLIMITED, + flag_BOUNDMODEMIN, flag_BOUNDMODEMAX); + + /* The initial bound value, where -1 means no restriction */ + flag_InitIntern(flag_BOUNDSTART, flag_UNIQUE, "BoundStart", flag_BOUNDSTARTUNLIMITED, + flag_BOUNDSTARTMIN, flag_BOUNDSTARTMAX); + + /* The number of bound saturation loops */ + flag_InitIntern(flag_BOUNDLOOPS, flag_UNIQUE, "BoundLoops", 1, + flag_BOUNDLOOPSMIN, flag_BOUNDLOOPSMAX); + + /* Flags for selecting the ordering to use */ + flag_InitIntern(flag_ORD, flag_UNIQUE, "Ordering", flag_ORDKBO, + flag_ORDMIN, flag_ORDMAX); + + /* CNF flag, if set optimized skolemization is performed */ + flag_InitIntern(flag_CNFOPTSKOLEM, flag_UNIQUE, "CNFOptSkolem", flag_CNFOPTSKOLEMON, + flag_CNFOPTSKOLEMMIN, flag_CNFOPTSKOLEMMAX); + + /* CNF flag, restricts the number of optimized skolemization proof steps */ + flag_InitIntern(flag_CNFPROOFSTEPS, flag_UNIQUE, "CNFProofSteps", 100, + flag_CNFPROOFSTEPSMIN, flag_CNFPROOFSTEPSMAX); + + /* CNF flag, if set renaming is performed */ + flag_InitIntern(flag_CNFRENAMING, flag_UNIQUE, "CNFRenaming", flag_CNFRENAMINGON, + flag_CNFRENAMINGMIN, flag_CNFRENAMINGMAX); + + /* CNF flag, if set renaming is printed */ + flag_InitIntern(flag_CNFPRENAMING, flag_UNIQUE, "CNFPRenaming", flag_CNFPRENAMINGOFF, + flag_CNFPRENAMINGMIN, flag_CNFPRENAMINGMAX); + + /* CNF flag, if set strong skolemization is performed */ + flag_InitIntern(flag_CNFSTRSKOLEM, flag_UNIQUE, "CNFStrSkolem", flag_CNFSTRSKOLEMON, + flag_CNFSTRSKOLEMMIN, flag_CNFSTRSKOLEMMAX); + + /* CNF flag, if set reductions on equality literals are performed */ + flag_InitIntern(flag_CNFFEQREDUCTIONS, flag_UNIQUE, "CNFFEqR", flag_CNFFEQREDUCTIONSON, + flag_CNFFEQREDUCTIONSMIN, flag_CNFFEQREDUCTIONSMAX); + + /* dfg2otter flag, if set input options for otter are generated */ + flag_InitIntern(flag_TDFG2OTTEROPTIONS, flag_UNIQUE, "TDfg2OtterOptions", flag_TDFG2OTTEROPTIONSOFF, + flag_TDFG2OTTEROPTIONSMIN, flag_TDFG2OTTEROPTIONSMAX); +} + + +FLAGSTORE flag_DefaultStore(void) +/************************************************************** + INPUT: None. + RETURNS: Default flag store. +***************************************************************/ +{ + return flag_DEFAULTSTORE; +} + + +void flag_Print(FLAGSTORE Store) +/************************************************************** + INPUT: A FlagStore. + RETURNS: Nothing. + EFFECT: Prints the values of all flags to stdout. +***************************************************************/ +{ + flag_FPrint(stdout, Store); +} + + +void flag_FPrint(FILE* File, FLAGSTORE Store) +/************************************************************** + INPUT: A File to print to, and a FlagStore. + RETURNS: Nothing. + EFFECT: Prints the values of all flags to File. +***************************************************************/ +{ + FLAG_ID i; + char name[30]; + + fputs("list_of_settings(SPASS).{*", File); + + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i+= (FLAG_ID) 3) { + sprintf(name,"set_flag(%s,%d).", flag_Name(i), flag_GetFlagValue(Store, i)); + fprintf(File,"\n %-30s",name); + if (i+1 < flag_MAXFLAG) { + sprintf(name,"set_flag(%s,%d).", flag_Name(i+ (FLAG_ID) 1), flag_GetFlagValue(Store, i+ (FLAG_ID) 1)); + fprintf(File," %-30s",name); + if (i+2 < flag_MAXFLAG) { + sprintf(name," set_flag(%s,%d).", flag_Name(i+ (FLAG_ID) 2), flag_GetFlagValue(Store, i+ (FLAG_ID) 2)); + fprintf(File," %-30s",name); + } + } + } + fputs("*}\nend_of_list.\n", File); +} + + +BOOL flag_Lookup(const char* String) +/************************************************************** + INPUT: A string <String>. + RETURNS: TRUE iff <String> is the string of a known flag. +***************************************************************/ +{ + return (flag_Id(String) != -1); +} + + +FLAG_ID flag_Id(const char* String) +/************************************************************** + INPUT: A string <String>. + RETURNS: The identification of the flag <String> if it exists + -1 otherwise. +***************************************************************/ +{ + FLAG_ID i; + + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i++) + if (string_Equal(flag_Name(i), String)) + return i; + + return (FLAG_ID) -1; +} + + +const char* flag_Name(FLAG_ID Flag) +/************************************************************** + INPUT: A FlagId. + RETURNS: The name of the flag <Flag>. + EFFECT: Looks up the name of the flag <Flag> and returns it, + if it exists. +***************************************************************/ +{ + flag_CheckFlagIdInRange(Flag); + + return(flag_PROPERTIES[Flag].name); +} + + +int flag_Minimum(FLAG_ID Flag) +/************************************************************** + INPUT: A FlagId. + RETURNS: The first integer below the minimal legal value + of the flag. +***************************************************************/ +{ + flag_CheckFlagIdInRange(Flag); + + return flag_PROPERTIES[Flag].minimum; +} + + +int flag_Maximum(FLAG_ID Flag) +/************************************************************** + INPUT: A FlagId. + RETURNS: The first integer above the maximal legal value + of the flag. +***************************************************************/ +{ + flag_CheckFlagIdInRange(Flag); + + return flag_PROPERTIES[Flag].maximum; +} + + +FLAG_TYPE flag_Type(FLAG_ID Flag) +/************************************************************** + INPUT: A FlagId. + RETURNS: The flag type. +***************************************************************/ +{ + flag_CheckFlagIdInRange(Flag); + + return flag_PROPERTIES[Flag].type; +} + + +void flag_ClearInferenceRules(FLAGSTORE Store) +/************************************************************** + INPUT: A FlagStore. + RETURNS: Nothing. + EFFECT: Turns all inference rules off. +***************************************************************/ +{ + FLAG_ID i; + + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i++) { + if (flag_IsInference(i)) + flag_SetFlagValue(Store, i, flag_OFF); + } +} + + +void flag_ClearReductionRules(FLAGSTORE Store) +/************************************************************** + INPUT: A FlagStore. + RETURNS: Nothing. + EFFECT: Turns all reduction rules off. +***************************************************************/ +{ + FLAG_ID i; + + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i++) { + if (flag_IsReduction(i)) { + flag_SetFlagValue(Store, i, flag_OFF); + } + } +} + + +void flag_ClearPrinting(FLAGSTORE Store) +/************************************************************** + INPUT: A FlagStore. + RETURNS: Nothing. + EFFECT: Turns all printing off. +***************************************************************/ +{ + + FLAG_ID i; + + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i++) { + if (flag_IsPrinting(i)) + flag_SetFlagValue(Store, i, flag_OFF); + } +} + + +void flag_SetReductionsToDefaults(FLAGSTORE Store) +/************************************************************** + INPUT: A FlagStore. + RETURNS: Nothing. + EFFECT: Sets all reduction rules to defaults. +***************************************************************/ +{ + + FLAG_ID i; + + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i++) { + if (flag_IsReduction(i)) + flag_SetFlagToDefault(Store, i); + } +} + + +void flag_InitFlotterSubproofFlags(FLAGSTORE Source, FLAGSTORE Target) +/************************************************************** + INPUT: Two flag stores. + RETURNS: Nothing. + EFFECT: Initializes the flag store <Target> to the values required by a + Flotter subproof. The other flag store is needed to take over + some flags, e.g. DOCPROOF. +***************************************************************/ +{ + /* Deactivate printing */ + flag_ClearPrinting(Target); + + /* Deactivate inference rules */ + flag_ClearInferenceRules(Target); + + /* Set reductions to default values */ + flag_SetReductionsToDefaults(Target); + + flag_SetFlagToDefault(Target, flag_CNFFEQREDUCTIONS); + flag_SetFlagToDefault(Target, flag_RINPUT); + + /* Copy flag_DOCPROOF and flag_CNFPROOFSTEPS */ + flag_TransferFlag(Source, Target, flag_DOCPROOF); + flag_TransferFlag(Source, Target, flag_CNFPROOFSTEPS); + + /* Activate BoundedDepthUnitResolution */ + flag_SetFlagValue(Target, flag_IBUR, flag_BOUNDEDDEPTHUNITRESOLUTIONON); + + /* Activate KBO */ + flag_SetFlagValue(Target, flag_ORD, flag_ORDKBO); + + /* Transfer Weights for Terms */ + flag_TransferFlag(Source, Target, flag_FUNCWEIGHT); + flag_TransferFlag(Source, Target, flag_VARWEIGHT); + + /* Transfer Selection Strategy, not needed for depth bounded */ + /* unit resolution (see above) but for other potentially useful inference rules */ + flag_TransferFlag(Source, Target, flag_SELECT); +} + + +void flag_InitFlotterFlags(FLAGSTORE Source, FLAGSTORE Target) +/************************************************************** + INPUT: Two flag stores. + RETURNS: Nothing. + EFFECT: Initalizes the flag store <Target> to the values required by + Flotter. The other flag store is needed to set + some flags, e.g. DOCPROOF. +***************************************************************/ +{ + flag_InitFlotterSubproofFlags(Source, Target); + + /* Set ordering to default value */ + flag_SetFlagToDefault(Target, flag_ORD); + + /* Set weighting flags to default values */ + flag_SetFlagToDefault(Target, flag_FUNCWEIGHT); + flag_SetFlagToDefault(Target, flag_VARWEIGHT); + + /* Copy given values to diverse flags */ + flag_TransferFlag(Source, Target, flag_CNFRENAMING); + flag_TransferFlag(Source, Target, flag_CNFOPTSKOLEM); + flag_TransferFlag(Source, Target, flag_CNFSTRSKOLEM); + flag_TransferFlag(Source, Target, flag_PAPPLYDEFS); + flag_TransferFlag(Source, Target, flag_PBDC); + flag_TransferFlag(Source, Target, flag_PBINC); + flag_TransferFlag(Source, Target, flag_CNFPRENAMING); + flag_TransferFlag(Source, Target, flag_POPTSKOLEM); + flag_TransferFlag(Source, Target, flag_PSTRSKOLEM); + flag_TransferFlag(Source, Target, flag_INTERACTIVE); +} + + +void flag_CheckStore(FLAGSTORE Store) +/************************************************************** + INPUT: A flag store. + RETURNS: TRUE is the flag store is in a valid state, + FALSE otherwise. +***************************************************************/ +{ + FLAG_ID i; + FLAG value; + + /* check all flags */ + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i ++) { + /* Get flag value first. We can't use flag_GetFlagValue() since it + prints an error message and exits, if a flag is clean. A flag can + be clean, only reading it is an error (for most functions). + */ + + value = Store[i]; + if (value != flag_CLEAN) { + flag_CheckFlagValueInRange(i,value); + } + } +} diff --git a/test/spass/flags.h b/test/spass/flags.h new file mode 100644 index 0000000000000000000000000000000000000000..2a9e1a55de15442084c0b91c06af890ac28b5fce --- /dev/null +++ b/test/spass/flags.h @@ -0,0 +1,1117 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * FLAGS OF SPASS * */ +/* * * */ +/* * $Module: FLAGS * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _FLAGS_ +#define _FLAGS_ + +#include <limits.h> +#include <stdio.h> + +#include "memory.h" +#include "misc.h" + +/**************************************************************/ +/* Data Structures and Constants */ +/**************************************************************/ + +extern const int flag_CLEAN; + +/* Define the legal values for all flags as data types. + + All flags have a minimum and a maximum. Legal values are + within that range, *excluding* the minimum, maximum value. By using + flag_XXXMIN and flag_XXXMAX we have a simple test for a + flag's correctness: + + if + flag value <= flag minimum + or flag value >= flag maximum + then + the flag has an illegal state. + + Boolean flags have two legal values: + * flag_XXXOFF ( = 0) + * flag_XXXON ( = 1) +*/ + +/* State definitions for boolean flags */ +typedef enum { flag_OFF = 0, + flag_ON = 1 +} FLAG_BOOLEAN; + +/* State definitions for flag_APPLYDEFS */ +typedef enum { flag_APPLYDEFSMIN = -1, + flag_APPLYDEFSOFF = flag_OFF, + flag_APPLYDEFSMAX = INT_MAX +} FLAG_APPLYDEFSTYPE; + +/* State definitions for flag_AUTO */ +typedef enum { flag_AUTOMIN = -1, + flag_AUTOOFF = flag_OFF, + flag_AUTOON = flag_ON, + flag_AUTOMAX +} FLAG_AUTOTYPE; + +/* State definitions for flag_BOUNDLOOPS */ +typedef enum { flag_BOUNDLOOPSMIN = 0, + flag_BOUNDLOOPSMAX = INT_MAX +} FLAG_BOUNDLOOPSTYPE; + +/* State definitions for flag_BOUNDMODE */ +typedef enum { flag_BOUNDMODEMIN = -1, + flag_BOUNDMODEUNLIMITED, + flag_BOUNDMODERESTRICTEDBYWEIGHT, + flag_BOUNDMODERESTRICTEDBYDEPTH, + flag_BOUNDMODEMAX +} FLAG_BOUNDMODETYPE; + +/* State definitions for flag_BOUNDSTART */ +typedef enum { flag_BOUNDSTARTMIN = -2, + flag_BOUNDSTARTUNLIMITED, + flag_BOUNDSTARTMAX = INT_MAX +} FLAG_BOUNDSTARTTYPE; + +/* State definitions for flag_CNFFEQREDUCTIONS */ +typedef enum { flag_CNFFEQREDUCTIONSMIN = -1, + flag_CNFFEQREDUCTIONSOFF = flag_OFF, + flag_CNFFEQREDUCTIONSON = flag_ON, + flag_CNFFEQREDUCTIONSMAX +} FLAG_CNFFEQREDUCTIONSTYPE; + +/* State definitions for flag_CNFOPTSKOLEM */ +typedef enum { flag_CNFOPTSKOLEMMIN = -1, + flag_CNFOPTSKOLEMOFF = flag_OFF, + flag_CNFOPTSKOLEMON = flag_ON, + flag_CNFOPTSKOLEMMAX +} flag_CNFOPTSKOLEMTYPE; + +/* State definitions for flag_CNFPRENAMING */ +typedef enum { flag_CNFPRENAMINGMIN = -1, + flag_CNFPRENAMINGOFF = flag_OFF, + flag_CNFPRENAMINGON = flag_ON, + flag_CNFPRENAMINGMAX +} FLAG_CNFPRENAMINGTYPE; + +/* State definitions for flag_CNFPROOFSTEPS */ +typedef enum { flag_CNFPROOFSTEPSMIN = 0, + flag_CNFPROOFSTEPSMAX = INT_MAX +} FLAG_CNFPROOFSTEPSTYPE; + +/* State definitions for flag_CNFRENAMING */ +typedef enum { flag_CNFRENAMINGMIN = -1, + flag_CNFRENAMINGOFF = flag_OFF, + flag_CNFRENAMINGON = flag_ON, + flag_CNFRENAMINGMAX +} FLAG_CNFRENAMINGTYPE; + +/* State definitions for flag_CNFSTRSKOLEM */ +typedef enum { flag_CNFSTRSKOLEMMIN = -1, + flag_CNFSTRSKOLEMOFF = flag_OFF, + flag_CNFSTRSKOLEMON = flag_ON, + flag_CNFSTRSKOLEMMAX +} FLAG_CNFSTRSKOLEMTYPE; + +/* State definitions for flag_DOCPROOF */ +typedef enum { flag_DOCPROOFMIN = -1, + flag_DOCPROOFOFF = flag_OFF, + flag_DOCPROOFON = flag_ON, + flag_DOCPROOFMAX +} FLAG_DOCPROOFTYPE; + +/* State definitions for flag_DOCSPLIT */ +typedef enum { flag_DOCSPLITMIN = -1, + flag_DOCSPLITOFF = flag_OFF, + flag_DOCSPLITON = flag_ON, + flag_DOCSPLITMAX +} FLAG_DOCSPLITTYPE; + +/* State definitions for flag_DOCSST */ +typedef enum { flag_DOCSSTMIN = -1, + flag_DOCSSTOFF = flag_OFF, + flag_DOCSSTON = flag_ON, + flag_DOCSSTMAX +} FLAG_DOCSSTTYPE; + +/* State definitions for flag_FLOTTER */ +typedef enum { flag_FLOTTERMIN = -1, + flag_FLOTTEROFF = flag_OFF, + flag_FLOTTERON = flag_ON, + flag_FLOTTERMAX +} FLAG_FLOTTERTYPE; + +/* State definitions for flag_FPDFGPROOF */ +typedef enum { flag_FPDFGPROOFMIN = -1, + flag_FPDFGPROOFOFF = flag_OFF, + flag_FPDFGPROOFON = flag_ON, + flag_FPDFGPROOFMAX +} FLAG_FPDFGPROOFTYPE; + +/* State definitions for flag_FPMODEL */ +typedef enum { flag_FPMODELMIN = -1, + flag_FPMODELOFF = flag_OFF, + flag_FPMODELALLCLAUSES, + flag_FPMODELPOTENTIALLYPRODUCTIVECLAUSES, + flag_FPMODELMAX +} FLAG_FPMODELTYPE; + +/* State definitions for flag_FULLRED */ +typedef enum { flag_FULLREDMIN = -1, + flag_FULLREDOFF = flag_OFF, + flag_FULLREDON = flag_ON, + flag_FULLREDMAX +} FLAG_FULLREDTYPE; + +/* State definitions for flag_FUNCWEIGHT */ +typedef enum { flag_FUNCWEIGHTMIN = 0, + flag_FUNCWEIGHTMAX = INT_MAX +} FLAG_FUNCWEIGHTTYPE; + +/* State definitions for flag_IBUR */ +typedef enum { flag_BOUNDEDDEPTHUNITRESOLUTIONMIN = -1, + flag_BOUNDEDDEPTHUNITRESOLUTIONOFF = flag_OFF, + flag_BOUNDEDDEPTHUNITRESOLUTIONON = flag_ON, + flag_BOUNDEDDEPTHUNITRESOLUTIONMAX +} FLAG_IBURTYPE; + +/* State definitions for flag_IDEF */ +typedef enum { flag_DEFINITIONAPPLICATIONMIN = -1, + flag_DEFINITIONAPPLICATIONOFF = flag_OFF, + flag_DEFINITIONAPPLICATIONON = flag_ON, + flag_DEFINITIONAPPLICATIONMAX +} FLAG_IDEFTYPE; + +/* State definitions for flag_IEMS */ +typedef enum { flag_EMPTYSORTMIN = -1, + flag_EMPTYSORTOFF = flag_OFF, + flag_EMPTYSORTON = flag_ON, + flag_EMPTYSORTMAX +} FLAG_IEMSTYPE; + +/* State definitions for flag_IEQF */ +typedef enum { flag_EQUALITYFACTORINGMIN = -1, + flag_EQUALITYFACTORINGOFF = flag_OFF, + flag_EQUALITYFACTORINGON = flag_ON, + flag_EQUALITYFACTORINGMAX +} FLAG_IEQFTYPE; + +/* State definitions for flag_IEQR */ +typedef enum { flag_EQUALITYRESOLUTIONMIN = -1, + flag_EQUALITYRESOLUTIONOFF = flag_OFF, + flag_EQUALITYRESOLUTIONON = flag_ON, + flag_EQUALITYRESOLUTIONMAX +} FLAG_IEQRTYPE; + +/* State definitions for flag_IERR */ +typedef enum { flag_REFLEXIVITYRESOLUTIONMIN = -1, + flag_REFLEXIVITYRESOLUTIONOFF = flag_OFF, + flag_REFLEXIVITYRESOLUTIONON = flag_ON, + flag_REFLEXIVITYRESOLUTIONMAX +} FLAG_IERRTYPE; + +/* State definitions for flag_IMPM */ +typedef enum { flag_MERGINGPARAMODULATIONMIN = -1, + flag_MERGINGPARAMODULATIONOFF = flag_OFF, + flag_MERGINGPARAMODULATIONON = flag_ON, + flag_MERGINGPARAMODULATIONMAX +} FLAG_IMPMTYPE; + +/* State definitions for flag_INTERACTIVE */ +typedef enum { flag_INTERACTIVEMIN = -1, + flag_INTERACTIVEOFF = flag_OFF, + flag_INTERACTIVEON = flag_ON, + flag_INTERACTIVEMAX +} FLAG_INTERACTIVETYPE; + +/* State definitions for flag_IOFC */ +typedef enum { flag_FACTORINGMIN = -1, + flag_FACTORINGOFF = flag_OFF, + flag_FACTORINGONLYRIGHT, + flag_FACTORINGRIGHTANDLEFT, + flag_FACTORINGMAX +} FLAG_IOFCTYPE; + +/* State definitions for flag_IOHY */ +typedef enum { flag_ORDEREDHYPERRESOLUTIONMIN = -1, + flag_ORDEREDHYPERRESOLUTIONOFF = flag_OFF, + flag_ORDEREDHYPERRESOLUTIONON = flag_ON, + flag_ORDEREDHYPERRESOLUTIONMAX +} FLAG_IOHYTYPE; + +/* State definitions for flag_IOPM */ +typedef enum { flag_ORDEREDPARAMODULATIONMIN = -1, + flag_ORDEREDPARAMODULATIONOFF = flag_OFF, + flag_ORDEREDPARAMODULATIONON = flag_ON, + flag_ORDEREDPARAMODULATIONMAX +} FLAG_IOPMTYPE; + +/* State definitions for flag_IORE */ +typedef enum { flag_ORDEREDRESOLUTIONMIN = -1, + flag_ORDEREDRESOLUTIONOFF = flag_OFF, + flag_ORDEREDRESOLUTIONNOEQUATIONS, + flag_ORDEREDRESOLUTIONWITHEQUATIONS, + flag_ORDEREDRESOLUTIONMAX +} FLAG_IORETYPE; + +/* State definitions for flag_ISFC */ +typedef enum { flag_STANDARDFACTORINGMIN = -1, + flag_STANDARDFACTORINGOFF = flag_OFF, + flag_STANDARDFACTORINGON = flag_ON, + flag_STANDARDFACTORINGMAX +} FLAG_ISFCTYPE; + +/* State definitions for flag_ISHY */ +typedef enum { flag_STANDARDHYPERRESOLUTIONMIN = -1, + flag_STANDARDHYPERRESOLUTIONOFF = flag_OFF, + flag_STANDARDHYPERRESOLUTIONON = flag_ON, + flag_STANDARDHYPERRESOLUTIONMAX +} FLAG_ISHYTYPE; + +/* State definitions for flag_ISOR */ +typedef enum { flag_SORTRESOLUTIONMIN = -1, + flag_SORTRESOLUTIONOFF = flag_OFF, + flag_SORTRESOLUTIONON = flag_ON, + flag_SORTRESOLUTIONMAX +} FLAG_ISORTYPE; + +/* State definitions for flag_ISPL */ +typedef enum { flag_SUPERPOSITIONLEFTMIN = -1, + flag_SUPERPOSITIONLEFTOFF = flag_OFF, + flag_SUPERPOSITIONLEFTON = flag_ON, + flag_SUPERPOSITIONLEFTMAX +} FLAG_ISPLTYPE; + +/* State definitions for flag_ISPM */ +typedef enum { flag_STANDARDPARAMODULATIONMIN = -1, + flag_STANDARDPARAMODULATIONOFF = flag_OFF, + flag_STANDARDPARAMODULATIONON = flag_ON, + flag_STANDARDPARAMODULATIONMAX +} FLAG_ISPMTYPE; + +/* State definitions for flag_ISPR */ +typedef enum { flag_SUPERPOSITIONRIGHTMIN = -1, + flag_SUPERPOSITIONRIGHTOFF = flag_OFF, + flag_SUPERPOSITIONRIGHTON = flag_ON, + flag_SUPERPOSITIONRIGHTMAX +} FLAG_ISPRTYPE; + +/* State definitions for flag_ISRE */ +typedef enum { flag_STANDARDRESOLUTIONMIN = -1, + flag_STANDARDRESOLUTIONOFF = flag_OFF, + flag_STANDARDRESOLUTIONNOEQUATIONS, + flag_STANDARDRESOLUTIONWITHEQUATIONS, + flag_STANDARDRESOLUTIONMAX +} FLAG_ISRETYPE; + +/* State definitions for flag_IUNR */ +typedef enum { flag_UNITRESOLUTIONMIN = -1, + flag_UNITRESOLUTIONOFF = flag_OFF, + flag_UNITRESOLUTIONON = flag_ON, + flag_UNITRESOLUTIONMAX +} FLAG_IUNRTYPE; + +/* State definitions for flag_IURR */ +typedef enum { flag_UNITRESULTINGRESOLUTIONMIN = -1, + flag_UNITRESULTINGRESOLUTIONOFF = flag_OFF, + flag_UNITRESULTINGRESOLUTIONON = flag_ON, + flag_UNITRESULTINGRESOLUTIONMAX +} FLAG_IURRTYPE; + +/* State definitions for flag_LOOPS */ +typedef enum { flag_LOOPSMIN = -2, + flag_LOOPSUNLIMITED, + flag_LOOPSMAX = INT_MAX +} FLAG_LOOPSTYPE; + +/* State definitions for flag_MEMORY */ +typedef enum { flag_MEMORYMIN = -2, + flag_MEMORYUNLIMITED, + flag_MEMORYMAX = INT_MAX +} FLAG_MEMORYTYPE; + +/* State definitions for flag_ORD */ +typedef enum { flag_ORDMIN = -1, + flag_ORDKBO, + flag_ORDRPOS, + flag_ORDMAX +} FLAG_ORDTYPE; + +/* State definitions for flag_PAPPLYDEFS */ +typedef enum { flag_PAPPLYDEFSMIN = -1, + flag_PAPPLYDEFSOFF = flag_OFF, + flag_PAPPLYDEFSON = flag_ON, + flag_PAPPLYDEFSMAX +} FLAG_PAPPLYDEFSTYPE; + +/* State definitions for flag_PBDC */ +typedef enum { flag_PBDCMIN = -1, + flag_PBDCOFF = flag_OFF, + flag_PBDCON = flag_ON, + flag_PBDCMAX +} FLAG_PBDCTYPE; + +/* State definitions for flag_PBINC */ +typedef enum { flag_PBINCMIN = -1, + flag_PBINCOFF = flag_OFF, + flag_PBINCON = flag_ON, + flag_PBINCMAX +} FLAG_PBINCTYPE; + +/* State definitions for flag_PMRR */ +typedef enum { flag_PMRRMIN = -1, + flag_PMRROFF = flag_OFF, + flag_PMRRON = flag_ON, + flag_PMRRMAX +} FLAG_PMRRTYPE; + +/* State definitions for flag_PCON */ +typedef enum { flag_PCONMIN = -1, + flag_PCONOFF = flag_OFF, + flag_PCONON = flag_ON, + flag_PCONMAX +} FLAG_PCONTYPE; + +/* State definitions for flag_PDER */ +typedef enum { flag_PDERMIN = -1, + flag_PDEROFF = flag_OFF, + flag_PDERON = flag_ON, + flag_PDERMAX +} FLAG_PDERTYPE; + +/* State definitions for flag_PEMPTYCLAUSE */ +typedef enum { flag_PEMPTYCLAUSEMIN = -1, + flag_PEMPTYCLAUSEOFF = flag_OFF, + flag_PEMPTYCLAUSEON = flag_ON, + flag_PEMPTYCLAUSEMAX +} FLAG_PEMPTYCLAUSETYPE; + +/* State definitions for flag_PFLAGS */ +typedef enum { flag_PFLAGSMIN = -1, + flag_PFLAGSOFF = flag_OFF, + flag_PFLAGSON = flag_ON, + flag_PFLAGSMAX +} FLAG_PFLAGSTYPE; + +/* State definitions for flag_PGIVEN */ +typedef enum { flag_PGIVENMIN = -1, + flag_PGIVENOFF = flag_OFF, + flag_PGIVENON = flag_ON, + flag_PGIVENMAX +} FLAG_PGIVENTYPE; + +/* State definitions for flag_PKEPT */ +typedef enum { flag_PKEPTMIN = -1, + flag_PKEPTOFF = flag_OFF, + flag_PKEPTON = flag_ON, + flag_PKEPTMAX +} FLAG_PKEPTTYPE; + +/* State definitions for flag_PLABELS */ +typedef enum { flag_PLABELSMIN = -1, + flag_PLABELSOFF = flag_OFF, + flag_PLABELSON = flag_ON, + flag_PLABELSMAX +} FLAG_PLABELSTYPE; + +/* State definitions for flag_POBV */ +typedef enum { flag_POBVMIN = -1, + flag_POBVOFF = flag_OFF, + flag_POBVON = flag_ON, + flag_POBVMAX +} FLAG_POBVTYPE; + +/* State definitions for flag_POPTSKOLEM */ +typedef enum { flag_POPTSKOLEMMIN = -1, + flag_POPTSKOLEMOFF = flag_OFF, + flag_POPTSKOLEMON = flag_ON, + flag_POPTSKOLEMMAX +} FLAG_POPTSKOLEMTYPE; + +/* State definitions for flag_PPROBLEM */ +typedef enum { flag_PPROBLEMMIN = -1, + flag_PPROBLEMOFF = flag_OFF, + flag_PPROBLEMON = flag_ON, + flag_PPROBLEMMAX +} FLAG_PPROBLEMTYPE; + +/* State definitions for flag_PREFCON */ +typedef enum { flag_PREFCONMIN = 0, + flag_PREFCONUNCHANGED, + flag_PREFCONMAX = INT_MAX +} FLAG_PREFCONTYPE; + +/* State definitions for flag_PREFVAR */ +typedef enum { flag_PREFVARMIN = -1, + flag_PREFVAROFF = flag_OFF, + flag_PREFVARON = flag_ON, + flag_PREFVARMAX +} FLAG_PREFVARTYPE; + +/* State definitions for flag_PREW */ +typedef enum { flag_PREWMIN = -1, + flag_PREWOFF = flag_OFF, + flag_PREWON = flag_ON, + flag_PREWMAX +} FLAG_PREWTYPE; + +/* State definitions for flag_PCRW */ +typedef enum { flag_PCRWMIN = -1, + flag_PCRWOFF = flag_OFF, + flag_PCRWON = flag_ON, + flag_PCRWMAX +} FLAG_PCRWTYPE; + +/* State definitions for flag_PAED */ +typedef enum { flag_PAEDMIN = -1, + flag_PAEDOFF = flag_OFF, + flag_PAEDON = flag_ON, + flag_PAEDMAX +} FLAG_PAEDTYPE; + +/* State definitions for flag_PSSI */ +typedef enum { flag_PSSIMIN = -1, + flag_PSSIOFF = flag_OFF, + flag_PSSION = flag_ON, + flag_PSSIMAX +} FLAG_PSSITYPE; + +/* State definitions for flag_PSST */ +typedef enum { flag_PSSTMIN = -1, + flag_PSSTOFF = flag_OFF, + flag_PSSTON = flag_ON, + flag_PSSTMAX +} FLAG_PSSTTYPE; + +/* State definitions for flag_PSTATISTIC */ +typedef enum { flag_PSTATISTICMIN = -1, + flag_PSTATISTICOFF = flag_OFF, + flag_PSTATISTICON = flag_ON, + flag_PSTATISTICMAX +} FLAG_PSTATISTICTYPE; + +/* State definitions for flag_PSTRSKOLEM */ +typedef enum { flag_PSTRSKOLEMMIN = -1, + flag_PSTRSKOLEMOFF = flag_OFF, + flag_PSTRSKOLEMON = flag_ON, + flag_PSTRSKOLEMMAX +} FLAG_PSTRSKOLEMTYPE; + +/* State definitions for flag_PSUB */ +typedef enum { flag_PSUBMIN = -1, + flag_PSUBOFF = flag_OFF, + flag_PSUBON = flag_ON, + flag_PSUBMAX +} FLAG_PSUBTYPE; + +/* State definitions for flag_PTAUT */ +typedef enum { flag_PTAUTMIN = -1, + flag_PTAUTOFF = flag_OFF, + flag_PTAUTON = flag_ON, + flag_PTAUTMAX +} FLAG_PTAUTTYPE; + +/* State definitions for flag_PUNC */ +typedef enum { flag_PUNCMIN = -1, + flag_PUNCOFF = flag_OFF, + flag_PUNCON = flag_ON, + flag_PUNCMAX +} FLAG_PUNCTYPE; + +/* State definitions for flag_RBMRR */ +typedef enum { flag_RBMRRMIN = -1, + flag_RBMRROFF = flag_OFF, + flag_RBMRRON = flag_ON, + flag_RBMRRMAX +} FLAG_RBMRRTYPE; + +/* State definitions for flag_RBREW */ +typedef enum { flag_RBREWMIN = -1, + flag_RBREWOFF = flag_OFF, + flag_RBREWON = flag_ON, + flag_RBREWMAX +} FLAG_RBREWTYPE; + +/* State definitions for flag_RBCRW */ +typedef enum { flag_RBCRWMIN = -1, + flag_RBCRWOFF = flag_OFF, + flag_RBCRWON = flag_ON, + flag_RBCRWMAX +} FLAG_RBCRWTYPE; + +/* State definitions for flag_RBSUB */ +typedef enum { flag_RBSUBMIN = -1, + flag_RBSUBOFF = flag_OFF, + flag_RBSUBON = flag_ON, + flag_RBSUBMAX +} FLAG_RBSUBTYPE; + +/* State definitions for flag_RCON */ +typedef enum { flag_RCONMIN = -1, + flag_RCONOFF = flag_OFF, + flag_RCONON = flag_ON, + flag_RCONMAX +} FLAG_RCONTYPE; + +/* State definitions for flag_RFMRR */ +typedef enum { flag_RFMRRMIN = -1, + flag_RFMRROFF = flag_OFF, + flag_RFMRRON = flag_ON, + flag_RFMRRMAX +} FLAG_RFMRRTYPE; + +/* State definitions for flag_RFREW */ +typedef enum { flag_RFREWMIN = -1, + flag_RFREWOFF = flag_OFF, + flag_RFREWON = flag_ON, + flag_RFREWMAX +} FLAG_RFREWTYPE; + +/* State definitions for flag_RFCRW */ +typedef enum { flag_RFCRWMIN = -1, + flag_RFCRWOFF = flag_OFF, + flag_RFCRWON = flag_ON, + flag_RFCRWMAX +} FLAG_RFCRWTYPE; + +/* State definitions for flag_RFSUB */ +typedef enum { flag_RFSUBMIN = -1, + flag_RFSUBOFF = flag_OFF, + flag_RFSUBON = flag_ON, + flag_RFSUBMAX +} FLAG_RFSUBTYPE; + +/* State definitions for flag_RINPUT */ +typedef enum { flag_RINPUTMIN = -1, + flag_RINPUTOFF = flag_OFF, + flag_RINPUTON = flag_ON, + flag_RINPUTMAX +} FLAG_RINPUTTYPE; + +/* State definitions for flag_ROBV */ +typedef enum { flag_ROBVMIN = -1, + flag_ROBVOFF = flag_OFF, + flag_ROBVON = flag_ON, + flag_ROBVMAX +} FLAG_ROBVTYPE; + +/* State definitions for flag_RAED */ +typedef enum { flag_RAEDMIN = -1, + flag_RAEDOFF = flag_OFF, + flag_RAEDSOUND, + flag_RAEDPOTUNSOUND, + flag_RAEDMAX +} FLAG_RAEDTYPE; + +/* State definitions for flag_RSSI */ +typedef enum { flag_RSSIMIN = -1, + flag_RSSIOFF = flag_OFF, + flag_RSSION = flag_ON, + flag_RSSIMAX +} FLAG_RSSITYPE; + +/* State definitions for flag_RSST */ +typedef enum { flag_RSSTMIN = -1, + flag_RSSTOFF = flag_OFF, + flag_RSSTON = flag_ON, + flag_RSSTMAX +} FLAG_RSSTTYPE; + +/* State definitions for flag_RTAUT */ +typedef enum { flag_RTAUTMIN = -1, + flag_RTAUTOFF = flag_OFF, + flag_RTAUTSYNTACTIC, + flag_RTAUTSEMANTIC, + flag_RTAUTMAX +} FLAG_RTAUTTYPE; + +/* State definitions for flag_RTER */ +typedef enum { flag_RTERMIN = -1, + flag_RTEROFF = flag_OFF, + flag_RTERMAX = INT_MAX +} FLAG_RTERTYPE; + +/* State definitions for flag_RUNC */ +typedef enum { flag_RUNCMIN = -1, + flag_RUNCOFF = flag_OFF, + flag_RUNCON = flag_ON, + flag_RUNCMAX +} FLAG_RUNCTYPE; + +/* State definitions for flag_SATINPUT */ +typedef enum { flag_SATINPUTMIN = -1, + flag_SATINPUTOFF = flag_OFF, + flag_SATINPUTON = flag_ON, + flag_SATINPUTMAX +} FLAG_SATINPUTTYPE; + +/* State definitions for flag_SELECT */ +typedef enum { flag_SELECTMIN = -1, + flag_SELECTOFF = flag_OFF, + flag_SELECTIFSEVERALMAXIMAL, + flag_SELECTALWAYS, + flag_SELECTMAX +} FLAG_SELECTTYPE; + +/* State definitions for flag_SORTS */ +typedef enum { flag_SORTSMIN = -1, + flag_SORTSOFF = flag_OFF, + flag_SORTSMONADICWITHVARIABLE, + flag_SORTSMONADICALL, + flag_SORTSMAX +} FLAG_SORTSTYPE; + +/* State definitions for flag_SOS */ +typedef enum { flag_SOSMIN = -1, + flag_SOSOFF = flag_OFF, + flag_SOSON = flag_ON, + flag_SOSMAX +} FLAG_SOSTYPE; + +/* State definitions for flag_SPLITS */ +typedef enum { flag_SPLITSMIN = -2, + flag_SPLITSUNLIMITED, + flag_SPLITSOFF = flag_OFF, + flag_SPLITSMAX = INT_MAX +} FLAG_SPLITSTYPE; + +/* State definitions for flag_STDIN */ +typedef enum { flag_STDINMIN = -1, + flag_STDINOFF = flag_OFF, + flag_STDINON = flag_ON, + flag_STDINMAX +} FLAG_STDINTYPE; + +/* State definitions for flag_TDFG2OTTEROPTIONS */ +typedef enum { flag_TDFG2OTTEROPTIONSMIN = -1, + flag_TDFG2OTTEROPTIONSOFF = flag_OFF, + flag_TDFG2OTTEROPTIONSPROOFCHECK, + flag_TDFG2OTTEROPTIONSAUTO, + flag_TDFG2OTTEROPTIONSAUTO2, + flag_TDFG2OTTEROPTIONSMAX +} FLAG_TDFG2OTTEROPTIONSTYPE; + +/* State definitions for flag_TIMELIMIT */ +typedef enum { flag_TIMELIMITMIN = -2, + flag_TIMELIMITUNLIMITED, + flag_TIMELIMITMAX = INT_MAX +} FLAG_TIMELIMITTYPE; + +/* State definitions for flag_VARWEIGHT */ +typedef enum { flag_VARWEIGHTMIN = 0, + flag_VARWEIGHTMAX = INT_MAX +} FLAG_VARWEIGHTTYPE; + +/* State definitions for flag_WDRATIO */ +typedef enum { flag_WDRATIOMIN = 0, + flag_WDRATIOMAX = INT_MAX +} FLAG_WDRATIOTYPE; + + +/* Define all flags */ + +typedef enum { flag_AUTO, flag_STDIN, flag_INTERACTIVE, flag_FLOTTER, + flag_SOS, + + flag_SPLITS, flag_MEMORY, flag_TIMELIMIT, + flag_DOCSST, flag_DOCPROOF, + flag_DOCSPLIT, flag_LOOPS, flag_PSUB, + flag_PREW, flag_PCRW, flag_PCON, + flag_PTAUT, flag_POBV, flag_PSSI, + flag_PSST, flag_PMRR, flag_PUNC, + flag_PAED, + + flag_PDER, flag_PGIVEN, flag_PLABELS, + flag_PKEPT, flag_PPROBLEM, flag_PEMPTYCLAUSE, + flag_PSTATISTIC, flag_FPMODEL, flag_FPDFGPROOF, + flag_PFLAGS, flag_POPTSKOLEM, flag_PSTRSKOLEM, + flag_PBDC, flag_PBINC, + flag_PAPPLYDEFS, + + flag_SELECT, flag_RINPUT, flag_SORTS, + flag_SATINPUT, flag_WDRATIO, flag_PREFCON, + flag_FULLRED, + flag_FUNCWEIGHT, flag_VARWEIGHT, flag_PREFVAR, + flag_BOUNDMODE, flag_BOUNDSTART, + flag_BOUNDLOOPS, flag_APPLYDEFS, + + flag_ORD, + + flag_CNFOPTSKOLEM, flag_CNFSTRSKOLEM, flag_CNFPROOFSTEPS, + flag_CNFRENAMING, flag_CNFPRENAMING, flag_CNFFEQREDUCTIONS, + + flag_IEMS, flag_ISOR, + flag_IEQR, flag_IERR, + flag_IEQF, flag_IMPM, flag_ISPR, + flag_IOPM, flag_ISPM, + flag_ISPL, flag_IORE, flag_ISRE, + flag_ISHY, flag_IOHY, flag_IURR, + flag_IOFC, flag_ISFC, + flag_IUNR, flag_IBUR, flag_IDEF, + + flag_RFREW, flag_RBREW, + flag_RFCRW, flag_RBCRW, + flag_RFMRR, flag_RBMRR, + flag_ROBV, flag_RUNC, flag_RTER, + flag_RTAUT, flag_RSST, flag_RSSI, + flag_RFSUB, flag_RBSUB, flag_RAED, + flag_RCON, + + flag_TDFG2OTTEROPTIONS, + + flag_MAXFLAG } FLAG_ID; /* flag_MAXFLAG is a final Dummy */ + + +/* Define different flag types */ +typedef enum { flag_INFERENCE, + flag_PRINTING, + flag_REDUCTION, + flag_UNIQUE, /* miscellaneous flags */ + flag_MAXTYPE +} FLAG_TYPE; + + +/* Define the flag data type */ +typedef int FLAG; + +/* Define the internal representation of a flag store */ +typedef FLAG FLAGARRAY[flag_MAXFLAG]; + +/* Define the flag store */ +typedef FLAG *FLAGSTORE; + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +void flag_Init(void); +void flag_InitFlotterFlags(FLAGSTORE, FLAGSTORE); +void flag_InitFlotterSubproofFlags(FLAGSTORE, FLAGSTORE); +FLAGSTORE flag_DefaultStore(void); +void flag_Print(FLAGSTORE); +void flag_FPrint(FILE*, FLAGSTORE); +BOOL flag_Lookup(const char*); +FLAG_ID flag_Id(const char*); +const char* flag_Name(FLAG_ID); +int flag_Minimum(FLAG_ID); +int flag_Maximum(FLAG_ID); +FLAG_TYPE flag_Type(FLAG_ID Flag); +void flag_ClearInferenceRules(FLAGSTORE Store); +void flag_ClearReductionRules(FLAGSTORE Store); +void flag_ClearPrinting(FLAGSTORE Store); +void flag_SetReductionsToDefaults(FLAGSTORE Store); +void flag_CheckStore(FLAGSTORE Store); + +/**************************************************************/ +/* Macros */ +/**************************************************************/ + +static __inline__ void flag_CheckFlagIdInRange(FLAG_ID FlagId) + /* prints an error report if a FLAG_ID is not valid */ +{ +#ifdef CHECK + if (FlagId >= flag_MAXFLAG) { + misc_StartErrorReport(); + misc_ErrorReport("\n In flag_CheckFlagIdInRange: Range of flags exceeded."); + misc_FinishErrorReport(); + } +#endif +} + +static __inline__ void flag_CheckFlagValueInRange(FLAG_ID FlagId, int Value) + /* prints an error report if a flag's value is out of range */ +{ + flag_CheckFlagIdInRange(FlagId); + + if (Value <= flag_Minimum(FlagId)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Flag value %d is too small for flag %s.\n", Value, flag_Name(FlagId)); + misc_FinishUserErrorReport(); + } + else + if (Value >= flag_Maximum(FlagId)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Flag value %d is too large for flag %s.\n", Value, flag_Name(FlagId)); + misc_FinishUserErrorReport(); + } +} + +static __inline__ void flag_CheckFlagTypeInRange(FLAG_TYPE Type) + /* prints an error report if a flag's type is out of range */ +{ +#ifdef CHECK + if (Type >= flag_MAXTYPE) { + misc_StartErrorReport(); + misc_ErrorReport("\n In flag_CheckFlagTypeInRange: Range of types exceeded."); + misc_FinishErrorReport(); + } +#endif +} + +static __inline__ BOOL flag_StoreIsDefaultStore(FLAGSTORE Store) + /* returns TRUE if a flag store is the default store, FALSE otherwise */ +{ + return (BOOL) (Store == flag_DefaultStore()); +} + +static __inline__ int flag_GetFlagValue(FLAGSTORE Store, FLAG_ID FlagId) +{ + int Value; + + flag_CheckFlagIdInRange(FlagId); + + Value = Store[FlagId]; +#ifdef CHECK + if (Value == flag_CLEAN) { + misc_StartErrorReport(); + misc_ErrorReport("\n In flag_GetFlagValue:"); + misc_ErrorReport(" Attempt to read undefined flag value."); + misc_FinishErrorReport(); + } +#endif + + return Value; +} + +static __inline__ void flag_SetFlagValue(FLAGSTORE Store, FLAG_ID FlagId, int Value) +{ +#ifdef CHECK + if (flag_StoreIsDefaultStore(Store)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In flag_SetFlagValue:"); + misc_ErrorReport(" Attempt to modify default flag value."); + misc_FinishErrorReport(); + } +#endif + + flag_CheckFlagIdInRange(FlagId); + + flag_CheckFlagValueInRange (FlagId, Value); + + Store[FlagId] = Value; +} + +static __inline__ BOOL flag_ValueIsClean(FLAGSTORE Store, FLAG_ID FlagId) +{ +#ifdef CHECK + flag_CheckFlagIdInRange(FlagId); + return (BOOL) (Store[FlagId] == flag_CLEAN); +#else + return (BOOL) (flag_GetFlagValue(Store, FlagId) == flag_CLEAN); +#endif +} + +static __inline__ void flag_CleanStore(FLAGSTORE Store) +{ + int i; + for (i = 0; i < flag_MAXFLAG; i++) + Store[i] = flag_CLEAN; +} + + +static __inline__ FLAGSTORE flag_CreateStore(void) + /* creates a fresh, clean FLAGSTORE */ +{ + FLAGSTORE store; + + store = (FLAGSTORE) memory_Malloc(sizeof(FLAGARRAY)); + flag_CleanStore(store); + return store; +} + + +static __inline__ void flag_DeleteStore(FLAGSTORE Store) +{ +#ifdef CHECK + /* Check if the flag store is a valid state */ + flag_CheckStore(Store); +#endif + + memory_Free(Store,sizeof(FLAGARRAY)); +} + + +static __inline__ void flag_InitStoreByDefaults(FLAGSTORE Store) +{ + FLAG_ID i; + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i++) + flag_SetFlagValue(Store, i, flag_GetFlagValue(flag_DefaultStore(),i)); +} + + +static __inline__ void flag_SetFlagToDefault(FLAGSTORE Store, FLAG_ID Flag) +{ + flag_SetFlagValue(Store, Flag, flag_GetFlagValue(flag_DefaultStore(), Flag)); +} + + +static __inline__ void flag_TransferFlag(FLAGSTORE Source, FLAGSTORE Destination, FLAG_ID FlagId) +{ + flag_SetFlagValue(Destination, FlagId, flag_GetFlagValue(Source, FlagId)); +} + + +static __inline__ void flag_TransferAllFlags(FLAGSTORE Source, FLAGSTORE Destination) +{ + FLAG_ID i; + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i++) + Destination[i] = Source[i]; +} + + +static __inline__ void flag_TransferSetFlags(FLAGSTORE Source, FLAGSTORE Destination) +{ + FLAG_ID i; + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i++) + if (!flag_ValueIsClean(Source,i)) + flag_TransferFlag(Source, Destination, i); +} + + +static __inline__ BOOL flag_IsOfType(FLAG_ID Flag, FLAG_TYPE Type) +/************************************************************** + INPUT: A FlagId and a flag type. + RETURNS: TRUE is the flag is of given type, + FALSE otherwise. +***************************************************************/ +{ + flag_CheckFlagIdInRange(Flag); + flag_CheckFlagTypeInRange(Type); + + return (BOOL) (flag_Type(Flag) == Type); +} + + +static __inline__ BOOL flag_IsInference(FLAG_ID Flag) +/************************************************************** + INPUT: A FlagId. + RETURNS: TRUE is the flag is an inference flag, + FALSE otherwise. +***************************************************************/ +{ + flag_CheckFlagIdInRange(Flag); + + return flag_IsOfType(Flag, flag_INFERENCE); +} + + +static __inline__ BOOL flag_IsReduction(FLAG_ID Flag) +/************************************************************** + INPUT: A FlagId. + RETURNS: TRUE is the flag is a reduction flag, + FALSE otherwise. +***************************************************************/ +{ + flag_CheckFlagIdInRange(Flag); + + return flag_IsOfType(Flag, flag_REDUCTION); +} + + +static __inline__ BOOL flag_IsPrinting(FLAG_ID Flag) +/************************************************************** + INPUT: A FlagId. + RETURNS: TRUE is the flag is a printing flag, + FALSE otherwise. +***************************************************************/ +{ + flag_CheckFlagIdInRange(Flag); + + return flag_IsOfType(Flag, flag_PRINTING); +} + + +static __inline__ BOOL flag_IsUnique(FLAG_ID Flag) +/************************************************************** + INPUT: A FlagId. + RETURNS: TRUE is the flag is an unique flag, + FALSE otherwise. +***************************************************************/ +{ + flag_CheckFlagIdInRange(Flag); + + return flag_IsOfType(Flag, flag_UNIQUE); +} + + +static __inline__ void flag_PrintReductionRules(FLAGSTORE Store) +/************************************************************** + INPUT: A FlagStore. + RETURNS: Nothing. + EFFECT: Prints the values of all reduction flags to stdout. +***************************************************************/ +{ + FLAG_ID i; + fputs("\n Reductions: ", stdout); + + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i++) { + if (flag_IsReduction(i) && flag_GetFlagValue(Store, i)) + printf("%s=%d ",flag_Name(i), flag_GetFlagValue(Store, i)); + } +} + +static __inline__ void flag_PrintInferenceRules(FLAGSTORE Store) +/************************************************************** + INPUT: A FlagStore. + RETURNS: Nothing. + EFFECT: Prints the values of all inference flags to stdout. +***************************************************************/ +{ + FLAG_ID i; + fputs("\n Inferences: ", stdout); + + for (i = (FLAG_ID) 0; i < flag_MAXFLAG; i++) { + if (flag_IsInference(i) && flag_GetFlagValue(Store, i)) + printf("%s=%d ",flag_Name(i), flag_GetFlagValue(Store,i)); + } +} + +#endif + + + + + + diff --git a/test/spass/foldfg.c b/test/spass/foldfg.c new file mode 100644 index 0000000000000000000000000000000000000000..549b92e080d6c3fa0d7f33133b2a2dfb6c201ce5 --- /dev/null +++ b/test/spass/foldfg.c @@ -0,0 +1,2444 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * FIRST ORDER LOGIC SYMBOLS * */ +/* * * */ +/* * $Module: FOL DFG * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + + +#include "foldfg.h" +#include "flags.h" + + +SYMBOL fol_ALL; +SYMBOL fol_EXIST; +SYMBOL fol_AND; +SYMBOL fol_OR; +SYMBOL fol_NOT; +SYMBOL fol_IMPLIES; +SYMBOL fol_IMPLIED; +SYMBOL fol_EQUIV; +SYMBOL fol_VARLIST; +SYMBOL fol_EQUALITY; +SYMBOL fol_TRUE; +SYMBOL fol_FALSE; + +LIST fol_SYMBOLS; + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +void fol_Init(BOOL All, PRECEDENCE Precedence) +/************************************************************** + INPUT: A boolean value determining whether only 'equality' or + all fol symbols are created, and a precedence. + RETURNS: Nothing. + SUMMARY: Initializes the Fol Module. + EFFECTS: If <All> then all fol-symbols are created, + only 'equality' otherwise. + The precedence of the first order logic symbols is set + in <Precedence>. + CAUTION: MUST BE CALLED BEFORE ANY OTHER fol-FUNCTION. +***************************************************************/ +{ + if (All) { + + fol_ALL = symbol_CreateJunctor("forall", 2, symbol_STATLEX, Precedence); + fol_EXIST = symbol_CreateJunctor("exists", 2, symbol_STATLEX, Precedence); + fol_AND = symbol_CreateJunctor("and", symbol_ArbitraryArity(), + symbol_STATLEX, Precedence); + fol_OR = symbol_CreateJunctor("or", symbol_ArbitraryArity(), + symbol_STATLEX, Precedence); + fol_NOT = symbol_CreateJunctor("not", 1, symbol_STATLEX, Precedence); + fol_IMPLIES = symbol_CreateJunctor("implies", 2, symbol_STATLEX, Precedence); + fol_IMPLIED = symbol_CreateJunctor("implied", 2, symbol_STATLEX, Precedence); + fol_EQUIV = symbol_CreateJunctor("equiv", 2, symbol_STATLEX, Precedence); + fol_VARLIST = symbol_CreateJunctor("", symbol_ArbitraryArity(), + symbol_STATLEX, Precedence); + fol_EQUALITY = symbol_CreatePredicate("equal", 2, symbol_STATLEX, Precedence); + fol_TRUE = symbol_CreatePredicate("true", 0, symbol_STATLEX, Precedence); + fol_FALSE = symbol_CreatePredicate("false", 0, symbol_STATLEX, Precedence); + + fol_SYMBOLS = + list_Cons((POINTER)fol_ALL, list_Cons((POINTER)fol_EXIST, + list_Cons((POINTER)fol_AND, list_Cons((POINTER)fol_OR, + list_Cons((POINTER)fol_NOT, + list_Cons((POINTER)fol_IMPLIES, list_Cons((POINTER)fol_IMPLIED, + list_Cons((POINTER)fol_EQUIV, list_Cons((POINTER)fol_VARLIST, + list_Cons((POINTER)fol_EQUALITY, list_Cons((POINTER)fol_TRUE, + list_List((POINTER)fol_FALSE)))))))))))); + } + else { + fol_EQUALITY = symbol_CreatePredicate("equal", 2, symbol_STATLEX, Precedence); + fol_NOT = symbol_CreateJunctor("not", 1, symbol_STATLEX, Precedence); + fol_SYMBOLS = list_Cons((POINTER)fol_NOT, list_List((POINTER)fol_EQUALITY)); + } +} + + +SYMBOL fol_IsStringPredefined(const char* String) +/************************************************************** + INPUT: A string. + RETURNS: The symbol iff String is a predefined fol string, + symbol NULL otherwise +***************************************************************/ +{ + LIST Scan; + for (Scan=fol_SYMBOLS; !list_Empty(Scan); Scan=list_Cdr(Scan)) + if (string_Equal(String, symbol_Name((SYMBOL)list_Car(Scan)))) + return (SYMBOL)list_Car(Scan); + return symbol_Null(); +} + + +TERM fol_CreateQuantifier(SYMBOL Quantifier, LIST VarList, LIST Arguments) +/************************************************************** + INPUT: A symbol (which MUST be a fol quantifier), + a list of variables that will be bound, and + a list of arguments. + RETURNS: A quantified term. +***************************************************************/ +{ +#ifdef CHECK + if (!fol_IsQuantifier(Quantifier)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_CreateQuantifier: Symbol isn't FOL quantifier.\n"); + misc_FinishErrorReport(); + } +#endif + + return term_Create(Quantifier, list_Cons(term_Create(fol_Varlist(), VarList), + Arguments)); +} + + +TERM fol_CreateQuantifierAddFather(SYMBOL Quantifier, LIST VarList, LIST Arguments) +/************************************************************** + INPUT: A symbol (which MUST be a fol quantifier), + a list of variables that will be bound, and + a list of arguments. + In contrast to fol_CreateQuantifier the superterm members + are set for the arguments. + RETURNS: A quantified term. +***************************************************************/ +{ + return term_CreateAddFather(Quantifier, + list_Cons(term_CreateAddFather(fol_Varlist(), + VarList), + Arguments)); +} + + +TERM fol_ComplementaryTerm(TERM Term) +/************************************************************** + INPUT: A formula. + RETURNS: The (copied) complementary (in sign) formula of <Term> +***************************************************************/ +{ + if (symbol_Equal(term_TopSymbol(Term), fol_Not())) + return term_Copy((TERM)list_First(term_ArgumentList(Term))); + else + return term_Create(fol_Not(), list_List(term_Copy(Term))); +} + + +LIST fol_GetNonFOLPredicates(void) +/************************************************************** + INPUT: None. + RETURNS: The list of all predicate symbols except the predefined + FOL symbols. +***************************************************************/ +{ + LIST Result; + + Result = symbol_GetAllPredicates(); + Result = list_DeleteElementIf(Result, (BOOL (*)(POINTER))fol_IsPredefinedPred); + return Result; +} + + +LIST fol_GetAssignments(TERM Term) +/************************************************************** + INPUT: A formula. + RETURNS: All assignemnts that occur inside the formula, i.e., + equations of the form "x=t" where "x" does not + occur in "t". +***************************************************************/ +{ + if (term_IsAtom(Term)) { + if (fol_IsAssignment(Term)) + return list_List(Term); + } + else + if (term_IsComplex(Term)) { + LIST Scan,Result; + Result = list_Nil(); + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + Result = list_Nconc(fol_GetAssignments(list_Car(Scan)),Result); + return Result; + } + + return list_Nil(); + +} + +static void fol_NormalizeVarsIntern(TERM Formula) +/************************************************************** + INPUT: A sentence. + RETURNS: void. + EFFECT: The quantifier variables of the formula are + normalized, i.e., no two different quantifiers + bind the same variable. + CAUTION: Desctructive. +***************************************************************/ +{ + SYMBOL Top; + LIST Scan1; + +#ifdef CHECK + if (!term_IsTerm(Formula)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_NormalizeVarsIntern: Formula is corrupted.\n"); + misc_FinishErrorReport(); + } +#endif + + Top = term_TopSymbol(Formula); + + if (term_IsComplex(Formula)) { + if (fol_IsQuantifier(Top)) { + SYMBOL Var; + LIST OldVars,Scan2; + OldVars = list_Nil(); + for (Scan1=fol_QuantifierVariables(Formula);!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { + Var = term_TopSymbol(list_Car(Scan1)); + OldVars = list_Nconc(OldVars,list_List((POINTER)term_BindingValue(Var))); + term_CreateValueBinding(Var, term_OldMark(), (POINTER)symbol_CreateStandardVariable()); + } + fol_NormalizeVarsIntern(term_SecondArgument(Formula)); + for (Scan1=fol_QuantifierVariables(Formula),Scan2=OldVars; + !list_Empty(Scan1); + Scan1=list_Cdr(Scan1),Scan2=list_Cdr(Scan2)) { + Var = term_TopSymbol(list_Car(Scan1)); + term_RplacTop(list_Car(Scan1),(SYMBOL)term_BindingValue(Var)); + term_CreateValueBinding(Var, term_OldMark(), list_Car(Scan2)); + } + list_Delete(OldVars); + } + else + for (Scan1=term_ArgumentList(Formula);!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) + fol_NormalizeVarsIntern(list_Car(Scan1)); + } + else + if (symbol_IsVariable(Top)) + term_RplacTop(Formula,(SYMBOL)term_BindingValue(Top)); + + return; +} + + +void fol_NormalizeVars(TERM Formula) +/************************************************************** + INPUT: A sentence. + RETURNS: void. + EFFECT: The quantifier variables of the formula are + normalized, i.e., no two different quantifiers + bind the same variable. + CAUTION: Destructive. +***************************************************************/ +{ + symbol_ResetStandardVarCounter(); + term_NewMark(); + fol_NormalizeVarsIntern(Formula); +} + + +void fol_NormalizeVarsStartingAt(TERM Formula, SYMBOL S) +/************************************************************** + INPUT: A sentence. + RETURNS: void. + EFFECT: The quantifier variables of the formula are + normalized, i.e., no two different quantifiers + bind the same variable. + CAUTION: Destructive. +***************************************************************/ +{ + SYMBOL old = symbol_STANDARDVARCOUNTER; + symbol_SetStandardVarCounter(S); + term_NewMark(); + fol_NormalizeVarsIntern(Formula); + symbol_SetStandardVarCounter(old); +} + + +void fol_RemoveImplied(TERM Formula) +/********************************************************* + INPUT: A formula. + RETURNS: void. + EFFECT: All occurrences of "implied" are replaced by "implies" + CAUTION: Destructive. +*******************************************************/ +{ + if (!fol_IsLiteral(Formula)) { + if (fol_IsQuantifier(term_TopSymbol(Formula))) + fol_RemoveImplied(term_SecondArgument(Formula)); + else { + LIST Scan; + if (symbol_Equal(term_TopSymbol(Formula),fol_Implied())) { + term_RplacTop(Formula,fol_Implies()); + term_RplacArgumentList(Formula,list_NReverse(term_ArgumentList(Formula))); + } + for (Scan=term_ArgumentList(Formula);!list_Empty(Scan);Scan=list_Cdr(Scan)) + fol_RemoveImplied(list_Car(Scan)); + } + } +} + + +BOOL fol_VarOccursFreely(TERM Var,TERM Term) +/************************************************************** + INPUT: A variable and a term. + RETURNS: TRUE iff <Var> occurs freely in <Term> +***************************************************************/ +{ + LIST Scan; + int Stack; + SYMBOL Top; + BOOL Hit; + +#ifdef CHECK + if (!term_IsTerm(Term) || !term_IsVariable(Var)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_VarOccursFreely: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + Stack = stack_Bottom(); + + do { + Top = term_TopSymbol(Term); + if (term_IsComplex(Term)) { + if (fol_IsQuantifier(Top)) { + Hit = TRUE; + for (Scan=fol_QuantifierVariables(Term);!list_Empty(Scan)&&Hit;Scan=list_Cdr(Scan)) + if (symbol_Equal(term_TopSymbol(list_Car(Scan)),term_TopSymbol(Var))) + Hit = FALSE; + if (Hit) + stack_Push(list_Cdr(term_ArgumentList(Term))); + } + else + stack_Push(term_ArgumentList(Term)); + } + else { + if (symbol_IsVariable(Top) && symbol_Equal(Top,term_TopSymbol(Var))) { + stack_SetBottom(Stack); + return TRUE; + } + } + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Stack)) { + Term = (TERM)list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); + + return FALSE; +} + + +LIST fol_FreeVariables(TERM Term) +/************************************************************** + INPUT: A term where we assume that no variable is bound by more than + one quantifier in <Term> !!!!! + RETURNS: The list of variables occurring in the term. Variables are + not (!) copied. + Note that there may be many terms with same variable symbol. + All Variable terms are newly created. +***************************************************************/ +{ + LIST Variables,Scan; + int Stack; + SYMBOL Top; + NAT BoundMark,FreeMark; + +#ifdef CHECK + if (!term_IsTerm(Term) || term_InBindingPhase()) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_FreeVariables: Illegal input or context.\n"); + misc_FinishErrorReport(); + } +#endif + + term_StartBinding(); + + Variables = list_Nil(); + Stack = stack_Bottom(); + BoundMark = term_ActMark(); + FreeMark = term_ActMark(); + + do { + Top = term_TopSymbol(Term); + if (term_IsComplex(Term)) { + if (fol_IsQuantifier(Top)) { + for (Scan=fol_QuantifierVariables(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (!term_VarIsMarked(term_TopSymbol(list_Car(Scan)), FreeMark)) + term_CreateBinding(term_TopSymbol(list_Car(Scan)), BoundMark); + stack_Push(term_ArgumentList(Term)); /* Mark has to be removed ! */ + stack_Push(list_Cdr(term_ArgumentList(Term))); + } + else + if (symbol_Equal(Top,fol_Varlist())) { + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (!term_VarIsMarked(term_TopSymbol(list_Car(Scan)), FreeMark)) + term_CreateBinding(term_TopSymbol(list_Car(Scan)), 0); /* Mark has to be removed ! */ + stack_RplacTop(list_Cdr(stack_Top())); /* Second Argument is Quantifier Arg */ + } + else + stack_Push(term_ArgumentList(Term)); + } + else { + if (symbol_IsVariable(Top) && !term_VarIsMarked(Top, FreeMark) + && !term_VarIsMarked(Top, BoundMark)) { + Variables = list_Cons(Term, Variables); + term_CreateBinding(Top, FreeMark); + } + } + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Stack)) { + Term = (TERM)list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); + + term_StopBinding(); + + return Variables; +} + +LIST fol_BoundVariables(TERM Term) +/************************************************************** + INPUT: A term + RETURNS: The list of bound variables occurring in the term. +***************************************************************/ +{ + int stack; + LIST result; + + stack = stack_Bottom(); + result = list_Nil(); + + do { + if (fol_IsQuantifier(term_TopSymbol(Term))) { + result = list_Nconc(result, list_Copy(fol_QuantifierVariables(Term))); + stack_Push(list_Cdr(term_ArgumentList(Term))); + } + else + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + + while (!stack_Empty(stack) && list_Empty(stack_Top())) + stack_Pop(); + + if (!stack_Empty(stack)) { + Term = list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(stack)); + result = term_DeleteDuplicatesFromList(result); + return result; +} + + +void fol_Free(void) +/************************************************************** + INPUT: None. + RETURNS: void. + EFFECT: The memory used by the fol modul is freed. +***************************************************************/ +{ + list_Delete(fol_SYMBOLS); +} + + +BOOL fol_FormulaIsClause(TERM Formula) +/************************************************************** + INPUT: A formula. + RETURNS: TRUE, if <Formula> is a clause, FALSE otherwise. +***************************************************************/ +{ + LIST LitList; + + if (term_TopSymbol(Formula) == fol_ALL) + Formula = term_SecondArgument(Formula); + + if (term_TopSymbol(Formula) != fol_OR) + return FALSE; + + LitList = term_ArgumentList(Formula); + + while (!list_Empty(LitList)) { + if (!fol_IsLiteral(list_Car(LitList))) + return FALSE; + LitList = list_Cdr(LitList); + } + + return TRUE; +} + + +void fol_FPrintOtterOptions(FILE* File, BOOL Equality, + FLAG_TDFG2OTTEROPTIONSTYPE Options) +/************************************************************** + INPUT: A file, a boolean flag and an Flag determining printed options. + RETURNS: Nothing. + SUMMARY: Prints Otter Options to <File>. + If <Equality> then appropriate paramodulation options + are possibly added. +***************************************************************/ +{ + switch (Options) { + case flag_TDFG2OTTEROPTIONSPROOFCHECK: + fputs("\nset(process_input).", File); + fputs("\nset(binary_res).", File); + fputs("\nset(factor).", File); + /*fputs("\nassign(pick_given_ratio, 4).", File);*/ + fputs("\nclear(print_kept).", File); + fputs("\nassign(max_seconds, 20).", File); + if (Equality) { + fputs("\nclear(print_new_demod).", File); + fputs("\nclear(print_back_demod).", File); + fputs("\nclear(print_back_sub).", File); + /*fputs("\nset(knuth_bendix).", File);*/ + fputs("\nset(para_from).", File); + fputs("\nset(para_into).", File); + fputs("\nset(para_from_vars).", File); + fputs("\nset(back_demod).", File); + } /* No break: add auto */ + case flag_TDFG2OTTEROPTIONSAUTO: + fputs("\nset(auto).", File); + break; + case flag_TDFG2OTTEROPTIONSAUTO2: + fputs("\nset(auto2).", File); + break; + case flag_TDFG2OTTEROPTIONSOFF: + /* print nothing */ + break; + default: + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_FPrintOtterOptions: Illegal parameter value %d.", + Options); + misc_FinishErrorReport(); + } + + fputs("\n\n",File); +} + +static void fol_FPrintOtterFormula(FILE* File, TERM Formula) +/************************************************************** + INPUT: A file and a formula. + RETURNS: Nothing. + SUMMARY: Prints the formula in Otter format to <File>. +***************************************************************/ +{ + SYMBOL Top; + + Top = term_TopSymbol(Formula); + + if (symbol_IsPredicate(Top)) { + if (symbol_Equal(Top, fol_Equality())) { + term_FPrintOtterPrefix(File,term_FirstArgument(Formula)); + fputs(" = ", File); + term_FPrintOtterPrefix(File,term_SecondArgument(Formula)); + } + else + term_FPrintOtterPrefix(File,Formula); + } + else { + if (fol_IsQuantifier(Top)) { + LIST Scan; + for (Scan=fol_QuantifierVariables(Formula);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + if (symbol_Equal(Top,fol_All())) + fputs("all ", File); + else + fputs("exists ", File); + term_FPrintOtterPrefix(File, list_Car(Scan)); + fputs(" (", File); + } + fol_FPrintOtterFormula(File, term_SecondArgument(Formula)); + for (Scan=fol_QuantifierVariables(Formula);!list_Empty(Scan);Scan=list_Cdr(Scan)) + fputs(")", File); + } + else + if (symbol_Equal(Top,fol_Not())) { + fputs("- (", File); + fol_FPrintOtterFormula(File, term_FirstArgument(Formula)); + fputs(")", File); + } + else + if (symbol_Equal(Top, fol_And()) || symbol_Equal(Top, fol_Or()) || + symbol_Equal(Top, fol_Equiv()) || symbol_Equal(Top, fol_Implies()) ) { + LIST Scan; + fputs("(", File); + for (Scan=term_ArgumentList(Formula);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + if (fol_IsLiteral(list_Car(Scan))) + fol_FPrintOtterFormula(File, list_Car(Scan)); + else { + fputs("(", File); + fol_FPrintOtterFormula(File, list_Car(Scan)); + fputs(")", File); + } + if (!list_Empty(list_Cdr(Scan))) { + if (symbol_Equal(Top, fol_And())) + fputs(" & ", File); + if (symbol_Equal(Top, fol_Or())) + fputs(" | ", File); + if (symbol_Equal(Top, fol_Equiv())) + fputs(" <-> ", File); + if (symbol_Equal(Top, fol_Implies())) + fputs(" -> ", File); + } + } + fputs(")", File); + } + } +} + +void fol_FPrintOtter(FILE* File, LIST Formulae, FLAG_TDFG2OTTEROPTIONSTYPE Option) +/************************************************************** + INPUT: A file, a list of pairs (label.formula) and an option flag. + RETURNS: Nothing. + SUMMARY: Prints a the respective formulae in Otter format to <File>. +***************************************************************/ +{ + LIST Scan; + BOOL Equality; + TERM Formula; + + Equality = FALSE; + + for (Scan=Formulae;!list_Empty(Scan) && !Equality; Scan=list_Cdr(Scan)) { + Formula = (TERM)list_PairSecond(list_Car(Scan)); + Equality = term_ContainsSymbol(Formula, fol_Equality()); + } + + fol_FPrintOtterOptions(File, Equality, Option); + + if (!list_Empty(Formulae)) { + fputs("formula_list(usable).\n", File); + if (Equality) + fputs("all x (x=x).\n", File); + for (Scan=Formulae;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + if (list_PairFirst(list_Car(Scan)) != NULL) + fprintf(File,"\n%% %s \n",(char *)list_PairFirst(list_Car(Scan))); + fol_FPrintOtterFormula(File,list_PairSecond(list_Car(Scan))); + fputs(".\n\n", File); + } + fputs("end_of_list.\n\n", File); + } +} + + +void fol_FPrintDFGSignature(FILE* File) +/************************************************************** + INPUT: A file stream. + RETURNS: Nothing. + SUMMARY: Prints all signature symbols in DFG format to the + file stream. +***************************************************************/ + +{ + NAT i; + SYMBOL symbol; + LIST functions, predicates; + + functions = symbol_GetAllFunctions(); + predicates = fol_GetNonFOLPredicates(); + + /* First print the function symbols */ + if (!list_Empty(functions)) { + fputs(" functions[", File); + i = 0; + do { + symbol = (SYMBOL) list_Top(functions); + fprintf(File, "(%s, %d)", symbol_Name(symbol), symbol_Arity(symbol)); + functions = list_Pop(functions); + if (!list_Empty(functions)) + fputs(", ", File); + if (i < 15) + i++; + else { + i = 0; + fputs("\n\t", File); + } + + } while (!list_Empty(functions)); + fputs("].\n", File); + } + + /* Now print the predicate symbols */ + if (!list_Empty(predicates)) { + i = 0; + fputs(" predicates[", File); + do { + symbol = (SYMBOL) list_Top(predicates); + fprintf(File, "(%s, %d)", symbol_Name(symbol), symbol_Arity(symbol)); + predicates = list_Pop(predicates); + if (!list_Empty(predicates)) + fputs(", ", File); + if (i < 15) + i++; + else { + i = 0; + fputs("\n\t", File); + } + } while (!list_Empty(predicates)); + fputs("].\n", File); + } + list_Delete(predicates); + list_Delete(functions); +} + + +static void fol_TermListFPrintDFG(FILE* File, LIST List) +/************************************************************** + INPUT: A list of terms. + RETURNS: Nothing. +***************************************************************/ +{ + for (; !list_Empty(List); List=list_Cdr(List)) { + fol_FPrintDFG(File,list_Car(List)); + if (!list_Empty(list_Cdr(List))) + putc(',', File); + } +} + + +void fol_FPrintDFG(FILE* File, TERM Term) +/************************************************************** + INPUT: A file and a term. + RETURNS: none. + SUMMARY: Prints the term in prefix notation to the file. + CAUTION: Uses the other fol_Output functions. +***************************************************************/ +{ + if (term_IsComplex(Term)) { + if (fol_IsQuantifier(term_TopSymbol(Term))) { + symbol_FPrint(File,term_TopSymbol(Term)); + fputs("([", File); + fol_TermListFPrintDFG(File,fol_QuantifierVariables(Term)); + fputs("],", File); + fol_FPrintDFG(File, term_SecondArgument(Term)); + putc(')', File); + } + else { + symbol_FPrint(File,term_TopSymbol(Term)); + putc('(', File); + fol_TermListFPrintDFG(File,term_ArgumentList(Term)); + putc(')', File); + } + } + else + symbol_FPrint(File,term_TopSymbol(Term)); +} + +void fol_PrintDFG(TERM Term) +{ + fol_FPrintDFG(stdout,Term); +} + + +void fol_PrintPrecedence(PRECEDENCE Precedence) +/************************************************************** + INPUT: A precedence. + RETURNS: void + EFFECT: Prints the current precedence to stdout, + fol symbols are excluded. +***************************************************************/ +{ + if (symbol_SignatureExists()) { + LIST Symbols, Scan; + SYMBOL Symbol; + int Index; + SIGNATURE S; + + Symbols = list_Nil(); + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + S = symbol_Signature(Index); + if (S != NULL) { + Symbol = S->info; + if ((symbol_IsPredicate(Symbol) || symbol_IsFunction(Symbol)) && + !fol_IsPredefinedPred(Symbol)) + Symbols = list_Cons((POINTER)Symbol, Symbols); + } + } + Symbols = symbol_SortByPrecedence(Symbols, Precedence); + for (Scan = Symbols; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + S = symbol_Signature(symbol_Index((SYMBOL)list_Car(Scan))); + fputs(S->name, stdout); + if (!list_Empty(list_Cdr(Scan))) + fputs(" > ", stdout); + } + list_Delete(Symbols); + } +} + +void fol_FPrintPrecedence(FILE *File, PRECEDENCE Precedence) +/************************************************************** + INPUT: A file to print to, and a precedence. + RETURNS: Nothing. + EFFECT: Prints the current precedence as a setting + command in DFG syntax to <File>. + fol symbols are excluded. +***************************************************************/ +{ + if (symbol_SignatureExists()) { + LIST Symbols, Scan; + SYMBOL Symbol; + int Index; + SIGNATURE S; + + Symbols = list_Nil(); + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + S = symbol_Signature(Index); + if (S != NULL) { + Symbol = S->info; + if ((symbol_IsPredicate(Symbol) || symbol_IsFunction(Symbol)) && + !fol_IsPredefinedPred(Symbol)) + Symbols = list_Cons((POINTER)Symbol, Symbols); + } + } + Symbols = symbol_SortByPrecedence(Symbols, Precedence); + Index = 0; + fputs("set_precedence(", File); + for (Scan = Symbols; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + S = symbol_Signature(symbol_Index((SYMBOL)list_Car(Scan))); + putc('(', File); + fputs(S->name, File); + putc(',', File); + fprintf(File, "%d", S->weight); + putc(',', File); + putc((symbol_HasProperty((SYMBOL)list_Car(Scan),ORDRIGHT) ? 'r' : + (symbol_HasProperty((SYMBOL)list_Car(Scan),ORDMUL) ? 'm' : 'l')), + File); + putc(')', File); + if (!list_Empty(list_Cdr(Scan))) + putc(',', File); + + if (Index > 15) { + Index = 0; + fputs("\n\t", File); + } + else + Index++; + } + fputs(").", File); + list_Delete(Symbols); + } +} + + +static void fol_FPrintFormulaList(FILE* File, LIST Formulas, const char* Name) +/************************************************************** + INPUT: A file, a list of formulas, a name. + EFFECTS: Print a list formulas in DFG format, with given list name. + **************************************************************/ +{ + LIST scan; + + fputs("list_of_formulae(", File); + fputs(Name, File); + fputs(").\n", File); + for (scan = Formulas; !list_Empty(scan); scan= list_Cdr(scan)) { + fputs("\tformula(", File); + fol_FPrintDFG(File, list_Car(scan)); + fputs(").\n", File); + } + fputs("end_of_list.\n\n", File); +} + + +void fol_FPrintDFGProblem(FILE* File, const char* Name, const char* Author, + const char* Status, const char* Description, + LIST Axioms, LIST Conjectures) +/************************************************************** + INPUT: A file, two lists of formulas, ??? EK + EFFECTS: Prints a complete DFG file containing these lists. +**************************************************************/ +{ + fputs("begin_problem(Unknown).\n\n", File); + + fputs("list_of_descriptions.\n", File); + fprintf(File,"name(%s).\n",Name); + fprintf(File,"author(%s).\n",Author); + fprintf(File,"status(%s).\n",Status); + fprintf(File,"description(%s).\n",Description); + fputs("end_of_list.\n\n", File); + + fputs("list_of_symbols.\n", File); + fol_FPrintDFGSignature(File); + fputs("end_of_list.\n\n", File); + + fol_FPrintFormulaList(File, Axioms, "axioms"); + fol_FPrintFormulaList(File, Conjectures, "conjectures"); + + fputs("end_problem.\n", File); +} + + +BOOL fol_AssocEquation(TERM Term, SYMBOL *Result) +/************************************************************** + INPUT: A term. + RETURNS: TRUE if the term is an equation defining associativity + for some function symbol. + EFFECT: If the <Term> is an assoc equation, then <*Result> is + assigned the assoc symbol. +***************************************************************/ +{ + + if (fol_IsEquality(Term)) { + SYMBOL Top; + TERM Left,Right; + Left = term_FirstArgument(Term); + Right= term_SecondArgument(Term); + Top = term_TopSymbol(Left); + if (symbol_IsFunction(Top) && symbol_Arity(Top) == 2 && + symbol_Equal(Top,term_TopSymbol(Right))) { + SYMBOL v1,v2,v3; + if (term_IsVariable(term_FirstArgument(Left))) + v1 = term_TopSymbol(term_FirstArgument(Left)); + else + if (term_IsVariable(term_FirstArgument(Right))) { + Term = Right; + Right = Left; + Left = Term; + v1 = term_TopSymbol(term_FirstArgument(Left)); + } + else + return FALSE; + if (symbol_Equal(term_TopSymbol(term_SecondArgument(Left)),Top) && + symbol_IsVariable((v2=term_TopSymbol(term_FirstArgument(term_SecondArgument(Left)))))&& + symbol_IsVariable((v3=term_TopSymbol(term_SecondArgument(term_SecondArgument(Left)))))&& + symbol_Equal(term_TopSymbol(term_FirstArgument(Right)),Top) && + symbol_Equal(v1,term_TopSymbol(term_FirstArgument(term_FirstArgument(Right)))) && + symbol_Equal(v2,term_TopSymbol(term_SecondArgument(term_FirstArgument(Right)))) && + symbol_Equal(v3,term_TopSymbol(term_SecondArgument(Right)))) { + *Result = Top; + return TRUE; + } + } + } + + return FALSE; +} + + +BOOL fol_DistributiveEquation(TERM Term, SYMBOL* Addition, + SYMBOL* Multiplication) +/************************************************************** + INPUT: A term. + RETURNS: TRUE if the term is an equation defining distributivity + for two function symbols, FALSE otherwise. + EFFECT: If the function returns TRUE, < Addition> and + <Multiplication> return the respective symbols. +***************************************************************/ +{ + TERM left, right, help, v1, v2, v3; + + if (!fol_IsEquality(Term)) + return FALSE; + + left = term_FirstArgument(Term); + right = term_SecondArgument(Term); + + if (term_EqualTopSymbols(left, right) || + !symbol_IsFunction(term_TopSymbol(left)) || + !symbol_IsFunction(term_TopSymbol(right)) || + symbol_Arity(term_TopSymbol(left)) != 2 || + symbol_Arity(term_TopSymbol(right)) != 2) + return FALSE; + + if (term_IsVariable(term_FirstArgument(left))) + v1 = term_FirstArgument(left); + else if (term_IsVariable(term_FirstArgument(right))) { + help = right; /* Exchange left and right terms */ + right = left; + left = help; + v1 = term_FirstArgument(left); + } else + return FALSE; + + if (!term_EqualTopSymbols(left, term_FirstArgument(right)) || + !term_EqualTopSymbols(left, term_SecondArgument(right)) || + !term_EqualTopSymbols(term_SecondArgument(left), right)) + return FALSE; + + v2 = term_FirstArgument(term_SecondArgument(left)); + v3 = term_SecondArgument(term_SecondArgument(left)); + + if (term_IsVariable(v2) && term_IsVariable(v3) && + term_EqualTopSymbols(term_FirstArgument(term_FirstArgument(right)), v1) && + term_EqualTopSymbols(term_SecondArgument(term_FirstArgument(right)), v2) && + term_EqualTopSymbols(term_FirstArgument(term_SecondArgument(right)), v1) && + term_EqualTopSymbols(term_SecondArgument(term_SecondArgument(right)), v3)) { + *Addition = term_TopSymbol(right); + *Multiplication = term_TopSymbol(left); + return TRUE; + } + + return FALSE; +} + + +static LIST fol_InstancesIntern(TERM Formula, TERM ToMatch, NAT Symbols) +/************************************************************** + INPUT: A formula in which all instances of <ToMatch> are searched. + The number of symbols of <ToMatch>. + RETURNS: The list of found instances. + CAUTION: Bound variables must be different, for otherwise the + used matching produces wrong results!! +***************************************************************/ +{ + NAT HitSymbols; + LIST Result; + int Stack; + + Stack = stack_Bottom(); + Result = list_Nil(); + + do { + HitSymbols = term_Size(Formula); /* First check number of symbols of current formula */ + + if (HitSymbols >= Symbols && (Formula != ToMatch)) { + cont_StartBinding(); + if (unify_MatchFlexible(cont_LeftContext(), ToMatch, Formula)) + Result = list_Cons(Formula, Result); + else + if (!symbol_IsPredicate(term_TopSymbol(Formula))) { + if (fol_IsQuantifier(term_TopSymbol(Formula))) + stack_Push(list_Cdr(term_ArgumentList(Formula))); + else + stack_Push(term_ArgumentList(Formula)); + } + cont_BackTrack(); + } + + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Stack)) { + Formula = (TERM)list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); + + return Result; +} + + +LIST fol_Instances(TERM Formula, TERM ToMatch) +/************************************************************** + INPUT: A formula in which all instances of <ToMatch> are searched. + RETURNS: The list of found occurrences matched by <ToMatch>. + The formula <ToMatch> is not included! +***************************************************************/ +{ + NAT Symbols; + + Symbols = term_ComputeSize(ToMatch); /* We use the number of symbols as a filter */ + term_InstallSize(Formula); + + return fol_InstancesIntern(Formula, ToMatch, Symbols); +} + + +static LIST fol_GeneralizationsIntern(TERM Formula, TERM MatchedBy, NAT Symbols) +/************************************************************** + INPUT: A formula in which all instances of <ToMatch> are searched. + The number of symbols of <ToMatch>. + RETURNS: The list of found instances. + CAUTION: Bound variables must be different, for otherwise the + used matching produces wrong results!! +***************************************************************/ +{ + NAT HitSymbols; + LIST Result; + int Stack; + + Stack = stack_Bottom(); + Result = list_Nil(); + + do { + if (Formula != MatchedBy) { + HitSymbols = term_Size(Formula); /* First check number of symbols of current formula */ + if (HitSymbols <= Symbols) { + cont_StartBinding(); + if (unify_MatchFlexible(cont_LeftContext(), Formula, MatchedBy)) + Result = list_Cons(Formula, Result); + else + if (!symbol_IsPredicate(term_TopSymbol(Formula))) { + if (fol_IsQuantifier(term_TopSymbol(Formula))) + stack_Push(list_Cdr(term_ArgumentList(Formula))); + else + stack_Push(term_ArgumentList(Formula)); + } + cont_BackTrack(); + } + else + if (!symbol_IsPredicate(term_TopSymbol(Formula))) { + if (fol_IsQuantifier(term_TopSymbol(Formula))) + stack_Push(list_Cdr(term_ArgumentList(Formula))); + else + stack_Push(term_ArgumentList(Formula)); + } + } + + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Stack)) { + Formula = (TERM)list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); + + return Result; +} + + +LIST fol_Generalizations(TERM Formula, TERM MatchedBy) +/************************************************************** + INPUT: A formula in which all first-order generalizations of <MatchedBy> are searched. + RETURNS: The list of found occurrences that are more general than <MatchedBy>. + The formula <MatchedBy> is not included! +***************************************************************/ +{ + NAT Symbols; + + Symbols = term_ComputeSize(MatchedBy); /* We use the number of symbols as a filter */ + term_InstallSize(Formula); + + return fol_GeneralizationsIntern(Formula, MatchedBy, Symbols); +} + + +TERM fol_MostGeneralFormula(LIST Formulas) +/************************************************************** + INPUT: A list of formulas. + RETURNS: A most general formula out of the list, i.e., if + some formula is returned, there is no formula in the + list that is more general than that formula. +***************************************************************/ +{ + TERM Result, Candidate; + LIST Scan; + +#ifdef CHECK + if (list_Empty(Formulas)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_MostGeneralFormula: Called with empty list.\n"); + misc_FinishErrorReport(); + } +#endif + + Result = list_Car(Formulas); + + for (Scan=list_Cdr(Formulas);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Candidate = (TERM)list_Car(Scan); + cont_StartBinding(); + if (unify_MatchFlexible(cont_LeftContext(), Candidate, Result)) + Result = Candidate; + cont_BackTrack(); + } + + return Result; +} + + +void fol_ReplaceVariable(TERM Term, SYMBOL Symbol, TERM Repl) +/************************************************************** + INPUT: A term, a variable symbol and a replacement term. + RETURNS: void + EFFECT: All free variables with <Symbol> in <Term> are replaced with copies of <Repl> + CAUTION: Destructive +***************************************************************/ +{ + LIST Scan; + +#ifdef CHECK + if (!(term_IsTerm(Term) && term_IsTerm(Repl) && symbol_IsVariable(Symbol))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_ReplaceVariable: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if (fol_IsQuantifier(term_TopSymbol(Term))) { + for (Scan=term_ArgumentList(term_FirstArgument(Term)); !list_Empty(Scan); Scan=list_Cdr(Scan)) + if (symbol_Equal(term_TopSymbol(list_Car(Scan)), Symbol)) /* var is bound */ + return; + fol_ReplaceVariable(term_SecondArgument(Term), Symbol, Repl); + } + + if (symbol_Equal(term_TopSymbol(Term), Symbol)) { + term_RplacTop(Term,term_TopSymbol(Repl)); + term_RplacArgumentList(Term,term_CopyTermList(term_ArgumentList(Repl))); + } + else + for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) + fol_ReplaceVariable(list_Car(Scan),Symbol,Repl); +} + + +static void fol_PrettyPrintInternDFG(TERM Term, int Depth) +/************************************************************** + INPUT: A term and a depth parameter for indentation. + RETURNS: none. + SUMMARY: Prints the term hopefully more pretty to stdout. +***************************************************************/ +{ + int i; + LIST scan; + SYMBOL Top; + + Top = term_TopSymbol(Term); + if (!symbol_Equal(Top,fol_Varlist())) { + for (i = 0; i < Depth; i++) + fputs(" ", stdout); + if (fol_IsLiteral(Term)) + term_PrintPrefix(Term); + else { + if (symbol_IsJunctor(Top)) { + if (term_IsComplex(Term)) { + symbol_Print(Top); + putchar('('); + if (!fol_IsQuantifier(Top)) + putchar('\n'); + for (scan=term_ArgumentList(Term); !list_Empty(scan); scan= list_Cdr(scan)) { + fol_PrettyPrintInternDFG((TERM) list_Car(scan), Depth+1); + if (!list_Empty(list_Cdr(scan))) + fputs(",\n", stdout); + } + putchar(')'); + } + else { + if (term_IsVariable(Term)) { + symbol_Print(Top); + } + else { + putchar('('); + symbol_Print(Top); + putchar(')'); + } + } + } + else { + term_PrintPrefix(Term); + } + } + } + else { + putchar('['); + term_TermListPrintPrefix(term_ArgumentList(Term)); + putchar(']'); + } +} + + +void fol_PrettyPrintDFG(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: none. + SUMMARY: Prints the term hopefully more pretty to stdout. +***************************************************************/ +{ + fol_PrettyPrintInternDFG(Term, 0); +} + + +TERM fol_CheckFatherLinksIntern(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: A subterm whose superterm pointer is not set correctly, + else NULL. + SUMMARY: Checks if all superterm links except of those from quantifier + variables are set correctly. +***************************************************************/ +{ + LIST l; + if (fol_IsQuantifier(term_TopSymbol(Term))) + return fol_CheckFatherLinksIntern(term_SecondArgument(Term)); + if (term_IsComplex(Term)) { + for (l=term_ArgumentList(Term); !list_Empty(l); l=list_Cdr(l)) { + TERM result; + if (term_Superterm((TERM) list_Car(l)) != Term) + return (TERM) list_Car(l); + result = fol_CheckFatherLinksIntern((TERM) list_Car(l)); + if (result != NULL) + return result; + } + } + return NULL; +} + + +void fol_CheckFatherLinks(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: none. + SUMMARY: Checks if all superterm links except of those from + quantifier variables are set correctly. +***************************************************************/ +{ + TERM Result; + + Result = fol_CheckFatherLinksIntern(Term); +#ifdef CHECK + if (Result != NULL || term_Superterm(Term) != NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_CheckFatherLinks:"); + misc_ErrorReport(" Found a term where the father links"); + misc_ErrorReport(" are not correctly set."); + misc_FinishErrorReport(); + } +#endif +} + + +static void fol_PrettyPrintIntern(TERM Term, int Depth) +/************************************************************** + INPUT: A term and a depth parameter for indentation. + RETURNS: none. + SUMMARY: Prints the term hopefully more pretty to stdout. +***************************************************************/ +{ + int i; + LIST scan; + + for (i = 0; i < Depth; i++) + fputs(" ", stdout); + if (symbol_IsJunctor(term_TopSymbol(Term))) { + if (term_IsComplex(Term)) { + if (fol_IsQuantifier(term_TopSymbol(Term))) { + symbol_Print(term_TopSymbol(Term)); + fputs("([", stdout); + for (scan=fol_QuantifierVariables(Term); !list_Empty(scan); scan=list_Cdr(scan)) { + symbol_Print(term_TopSymbol((TERM) list_Car(scan))); + if (!list_Empty(list_Cdr(scan))) + putchar(','); + } + fputs("],\n", stdout); + fol_PrettyPrintIntern(term_SecondArgument(Term), Depth+1); + } + else { + symbol_Print(term_TopSymbol(Term)); + fputs("(\n", stdout); + for (scan=term_ArgumentList(Term); !list_Empty(scan); scan= list_Cdr(scan)) { + fol_PrettyPrintIntern((TERM) list_Car(scan), Depth+1); + if (!list_Empty(list_Cdr(scan))) + fputs(",\n", stdout); + } + putchar(')'); + } + } + else { + if (term_IsVariable(Term)) { + symbol_Print(term_TopSymbol(Term)); + } + else { + putchar('('); + symbol_Print(term_TopSymbol(Term)); + putchar(')'); + } + } + } + else { + term_PrintPrefix(Term); + } +} + + +void fol_PrettyPrint(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: none. + SUMMARY: Prints the term hopefully more pretty to stdout. +***************************************************************/ +{ + fol_PrettyPrintIntern(Term, 0); +} + + +LIST fol_GetSubstEquations(TERM Term) +/************************************************************** + INPUT: A Term. + RETURNS: The list of all equations of the form x=t or t=x in <Term> + where x is a variable and t is a term not containing x. +***************************************************************/ +{ + LIST Result; + LIST Scan; + + Result = list_Nil(); + + if (fol_IsQuantifier(term_TopSymbol(Term))) + return fol_GetSubstEquations(term_SecondArgument(Term)); + if (fol_IsEquality(Term)) { + if (term_IsVariable(term_SecondArgument(Term))) { + if (!term_ContainsSymbol(term_FirstArgument(Term), term_TopSymbol(term_SecondArgument(Term)))) + Result = list_Cons(Term, Result); + } + else { + if (term_IsVariable(term_FirstArgument(Term))) + if (!term_ContainsSymbol(term_SecondArgument(Term), term_TopSymbol(term_FirstArgument(Term)))) + Result = list_Cons(Term, Result); + } + } + if (symbol_IsPredicate(term_TopSymbol(Term))) + return Result; + else + for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) + Result = list_Nconc(Result, fol_GetSubstEquations(list_Car(Scan))); + + return Result; +} + + +TERM fol_GetBindingQuantifier(TERM Term, SYMBOL Symbol) +/************************************************************** + INPUT: A symbol and a term containing the symbol. + RETURNS: The Quantifier binding the symbol. +***************************************************************/ +{ + LIST Scan; + +#ifdef CHECK + if (!term_IsTerm(Term) || !symbol_IsSymbol(Symbol)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_GetBindingQuantifier: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if (fol_IsQuantifier(term_TopSymbol(Term))) { + for ( Scan = fol_QuantifierVariables(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (symbol_Equal(Symbol, term_TopSymbol(list_Car(Scan)))) { + return Term; + } + } + + return fol_GetBindingQuantifier(term_Superterm(Term), Symbol); +} + + +int fol_TermPolarity(TERM SubTerm, TERM Term) +/************************************************************** + INPUT: Two terms, SubTerm subterm of Term. + It is assumed that the superterm links in <Term> + are established. + RETURNS: The polarity of SubTerm in Term. +***************************************************************/ +{ + TERM SuperTerm; + +#ifdef CHECK + if (!term_IsTerm(SubTerm) || !term_IsTerm(Term) || !term_FatherLinksEstablished(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_TermPolarity: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if (SubTerm == Term) + return 1; + + SuperTerm = term_Superterm(SubTerm); + + if (SuperTerm) { + SYMBOL Top; + Top = term_TopSymbol(SuperTerm); + + if (symbol_Equal(Top,fol_AND) || symbol_Equal(Top,fol_OR) || fol_IsQuantifier(Top)) + return fol_TermPolarity(SuperTerm, Term); + + if (symbol_Equal(Top,fol_NOT)) + return (-fol_TermPolarity(SuperTerm, Term)); + + if (symbol_Equal(Top,fol_EQUIV)) + return 0; + + if (symbol_Equal(Top, fol_IMPLIES)) { + if (SubTerm == term_FirstArgument(SuperTerm)) + return (-fol_TermPolarity(SuperTerm, Term)); + else + return fol_TermPolarity(SuperTerm, Term); + } + if (symbol_Equal(Top, fol_IMPLIED)) { + if (SubTerm == term_SecondArgument(SuperTerm)) + return (-fol_TermPolarity(SuperTerm, Term)); + else + return fol_TermPolarity(SuperTerm, Term); + } + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_TermPolarity: Unknown first-order operator.\n"); + misc_FinishErrorReport(); + } + + return 1; +} + + +static int fol_PolarCheckCount(TERM Nowterm, TERM SuperTerm, int Nowpolar) +/************************************************************** + INPUT: Two terms, Nowterm and its superterm, and the polarity of + Nowterm. + RETURNS: The polarity of SuperTerm according to Nowterm. + COMMENT: Helpfunction for fol_PolarCheck. +***************************************************************/ +{ + SYMBOL Top; + Top = term_TopSymbol(SuperTerm); + + if (Nowterm == SuperTerm) + return Nowpolar; + + if (symbol_Equal(Top, fol_OR) || symbol_Equal(Top, fol_AND) || fol_IsQuantifier(Top) || + (symbol_Equal(Top, fol_IMPLIES) && Nowterm == term_SecondArgument(SuperTerm)) || + (symbol_Equal(Top, fol_IMPLIED) && Nowterm == term_FirstArgument(SuperTerm))) + return Nowpolar; + + if (symbol_Equal(term_TopSymbol(SuperTerm), fol_EQUIV)) + return 0; + + return -Nowpolar; +} + + +static BOOL fol_PolarCheckAllquantor(TERM Subterm, TERM Term, int SubtermPolar) +/************************************************************** + INPUT: Two terms, Subterm subterm of Term, and polarity of Subterm. + RETURNS: TRUE iff Subterm occurs in Term disjunctively. + COMMENT: Help function for fol_PolarCheck. Dual case to Exist quantor. +***************************************************************/ +{ + TERM SuperTerm; + SYMBOL Top; + int SubPolar; + + if (Subterm == Term) + return TRUE; + + SuperTerm = term_Superterm(Subterm); + + if (SuperTerm == Term) /* Ugly, but it does not make sense to introduce a further function */ + return TRUE; + + Top = term_TopSymbol(SuperTerm); + SubPolar = fol_PolarCheckCount(Subterm, SuperTerm, SubtermPolar); + + /* To be clarified: can the below condition generalized to universal quantifiers? */ + + if (symbol_Equal(Top,fol_NOT) || + (symbol_Equal(Top, fol_OR) && SubPolar == 1) || + (symbol_Equal(Top, fol_AND) && SubPolar == -1) || + (symbol_Equal(Top,fol_IMPLIES) && SubPolar == 1) || + (symbol_Equal(Top,fol_IMPLIED) && SubPolar == 1)) + return fol_PolarCheckAllquantor(SuperTerm, Term, SubPolar); + + return FALSE; +} + + +static BOOL fol_PolarCheckExquantor(TERM Subterm, TERM Term, int SubtermPolar) +/************************************************************** + INPUT: Two terms, Subterm subterm of Term, and polarity of Subterm. + RETURNS: TRUE iff Subterm occurs in Term conjunctively. + COMMENT: Help function for fol_PolarCheck. Dual case to Allquantor. +***************************************************************/ +{ + TERM SuperTerm; + SYMBOL Top; + int SubPolar; + + if (Subterm == Term) + return TRUE; + + SuperTerm = term_Superterm(Subterm); + + if (SuperTerm == Term) /* Ugly, but it does not make sense to introduce a further function */ + return TRUE; + + Top = term_TopSymbol(SuperTerm); + SubPolar = fol_PolarCheckCount(Subterm, SuperTerm, SubtermPolar); + + /* To be clarified: can the below condition generalized to existential quantifiers? */ + + if (symbol_Equal(Top,fol_NOT) || + (symbol_Equal(Top, fol_OR) && SubPolar == -1) || + (symbol_Equal(Top, fol_AND) && SubPolar == 1) || + (symbol_Equal(Top,fol_IMPLIES) && SubPolar == -1) || + (symbol_Equal(Top,fol_IMPLIED) && SubPolar == -1)) + return fol_PolarCheckExquantor(SuperTerm, Term, SubPolar); + + return FALSE; +} + +BOOL fol_PolarCheck(TERM Subterm, TERM Term) +/************************************************************** + INPUT: Two terms, <Subterm> is of the form x=t, where x or t variable. + <Subterm> is a subterm of <Term> and the top symbol of + <Term> must be the binding quantifier of x or t. + RETURNS: BOOL if check is ok. +***************************************************************/ +{ + int SubtermPolar; + SYMBOL Top; + + SubtermPolar = fol_TermPolarity(Subterm, Term); + Top = term_TopSymbol(Term); + + if (SubtermPolar == -1 && symbol_Equal(Top, fol_ALL)) + return fol_PolarCheckAllquantor(Subterm, Term, SubtermPolar); + + if (SubtermPolar == 1 && symbol_Equal(Top, fol_EXIST)) + return fol_PolarCheckExquantor(Subterm, Term, SubtermPolar); + + return FALSE; +} + + +void fol_PopQuantifier(TERM Term) +/************************************************************** + INPUT: A term whose top symbol is a quantifier. + RETURNS: Nothing. + EFFECT: Removes the quantifier. + If supertermlinks were set, they are updated. +***************************************************************/ +{ + TERM SubTerm; + LIST Scan; + +#ifdef CHECK + if (!fol_IsQuantifier(term_TopSymbol(Term))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_PopQuantifier: Top symbol of term isn't a quantifier.\n"); + misc_FinishErrorReport(); + } +#endif + + term_Delete(term_FirstArgument(Term)); + SubTerm = term_SecondArgument(Term); + list_Delete(term_ArgumentList(Term)); + term_RplacTop(Term,term_TopSymbol(SubTerm)); + term_RplacArgumentList(Term,term_ArgumentList(SubTerm)); + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (term_Superterm(list_Car(Scan))) + term_RplacSuperterm(list_Car(Scan),Term); + term_Free(SubTerm); +} + + +void fol_DeleteQuantifierVariable(TERM Quant,SYMBOL Var) +/**************************************************************** + INPUT: A term starting with a quantifier and a variable symbol. + RETURNS: Nothing. + EFFECT: The variable is deleted from the list of variables + bound by the quantor of <Quant> +*****************************************************************/ +{ + LIST Scan; + + for (Scan=fol_QuantifierVariables(Quant);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (symbol_Equal(term_TopSymbol(list_Car(Scan)), Var)) { + term_Delete((TERM)list_Car(Scan)); + list_Rplaca(Scan, (POINTER)NULL); + } + term_RplacArgumentList(term_FirstArgument(Quant), + list_PointerDeleteElement(fol_QuantifierVariables(Quant),(POINTER)NULL)); + if (list_Empty(fol_QuantifierVariables(Quant))) + fol_PopQuantifier(Quant); +} + + + +void fol_SetTrue(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: Nothing. + EFFECT: Replaces Term destructively by fol_True(). +***************************************************************/ +{ + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term, list_Nil()); + term_RplacTop(Term, fol_True()); +} + +void fol_SetFalse(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: Nothing. + EFFECT: Replaces Term destructively by fol_False(). +***************************************************************/ +{ + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term, list_Nil()); + term_RplacTop(Term, fol_False()); +} + + +static void fol_ReplaceByArgCon(TERM Term) +/************************************************************** + INPUT: A term of the form f(...)=f(...), where f is a function. + RETURNS: True. + EFFECT: Substitutes Term by <and(t1=s1, t2=s2, ..., tn=sn)>, + where ti and si are the arguments of both f's in Term. +***************************************************************/ +{ + LIST Scan, Bscan, List, Hlist; + TERM Func1, Func2, NewTerm; + + Func1 = term_FirstArgument(Term); + Func2 = term_SecondArgument(Term); + List = term_ArgumentList(Term); + Scan = list_Nil(); + term_RplacArgumentList(Term, list_Nil()); + term_RplacTop(Term, fol_And()); + + for (Scan = term_ArgumentList(Func1),Bscan = term_ArgumentList(Func2); + !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Hlist = list_Nil(); + Hlist = list_Cons(list_Car(Bscan), Hlist); + Hlist = list_Cons(list_Car(Scan), Hlist); + NewTerm = term_Create(fol_Equality(), Hlist); + term_RplacArgumentList(Term, list_Cons(NewTerm, term_ArgumentList(Term))); + Bscan = list_Cdr(Bscan); + } + + list_Delete(term_ArgumentList(Func1)); + list_Delete(term_ArgumentList(Func2)); + term_RplacArgumentList(Func1, list_Nil()); + term_RplacArgumentList(Func2, list_Nil()); + term_Delete(Func1); + term_Delete(Func2); + list_Delete(List); +} + + +BOOL fol_PropagateFreeness(TERM Term) +/************************************************************** + INPUT: A term and a list of functions. + RETURNS: True iff a subterm of the form f(...)=f(...) occurs in the term, + where f has property FREELY and GENERATED. + EFFECT: Substitutes all occurences of f=f by <and(t1=s1,...tn=sn)>,where + ti and si are the arguments of each f in f=f. +***************************************************************/ +{ + BOOL Free; + LIST Scan; + TERM Argum1, Argum2; + + Free = FALSE; + + if (fol_IsQuantifier(term_TopSymbol(Term))) + return fol_PropagateFreeness(term_SecondArgument(Term)); + + if (!term_IsAtom(Term)) { + for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (fol_PropagateFreeness(list_Car(Scan))) + Free = TRUE; + } + else + if (fol_IsEquality(Term)) { + Argum1 = term_FirstArgument(Term); + Argum2 = term_SecondArgument(Term); + if (symbol_Equal(term_TopSymbol(Argum1), term_TopSymbol(Argum2)) && + symbol_HasProperty(term_TopSymbol(Argum1), FREELY) && + symbol_HasProperty(term_TopSymbol(Argum1), GENERATED)) { + fol_ReplaceByArgCon(Term); + return TRUE; + } + } + + return Free; +} + + +static BOOL fol_PropagateWitnessIntern(TERM Equation, SYMBOL Variable) +/************************************************************** + INPUT: A Term which is an equation where <Variable> is one + of the equation's arguments that does not occur in the + other argument. Father links must exist. + RETURNS: True in case of witness propagation. + EFFECT: Checks whether subterm the equation is part of + is of the form described in fol_PropagateWitness and + substitutes in case of a hit. +***************************************************************/ +{ + TERM SuperTerm, BindQuantor, Predicat; + SYMBOL SuperTop; + + SuperTerm = term_Superterm(Equation); + + if (SuperTerm == term_Null()) + return FALSE; + + SuperTop = term_TopSymbol(SuperTerm); + BindQuantor = term_Superterm(SuperTerm); + + if (BindQuantor == term_Null()) + return FALSE; + + if (!fol_IsQuantifier(term_TopSymbol(BindQuantor)) || + list_Length(term_ArgumentList(SuperTerm)) != 2) + return FALSE; + + if (Equation == term_SecondArgument(SuperTerm)) + Predicat = term_FirstArgument(SuperTerm); + else + Predicat = term_SecondArgument(SuperTerm); + + if (symbol_Equal(term_TopSymbol(BindQuantor), fol_All()) && + symbol_Equal(SuperTop, fol_Or()) && + symbol_Equal(term_TopSymbol(Predicat), fol_Not()) && + symbol_HasProperty(term_TopSymbol(term_FirstArgument(Predicat)), FREELY) && + symbol_HasProperty(term_TopSymbol(term_FirstArgument(Predicat)), GENERATED) && + symbol_Equal(term_TopSymbol(term_FirstArgument(term_FirstArgument(Predicat))), Variable)) { + fol_SetFalse(BindQuantor); + return TRUE; + } + if (!symbol_HasProperty(term_TopSymbol(Predicat), FREELY) || + !symbol_HasProperty(term_TopSymbol(Predicat), GENERATED) || + !symbol_Equal(Variable, term_TopSymbol(term_FirstArgument(Predicat)))) + return FALSE; + + if (symbol_Equal(term_TopSymbol(BindQuantor), fol_All())) { + if (symbol_Equal(SuperTop, fol_Implies()) && + term_SecondArgument(SuperTerm) == Equation) { + fol_SetFalse(BindQuantor); + return TRUE; + } + if (symbol_Equal(SuperTop, fol_Implied()) && + term_FirstArgument(SuperTerm) == Equation) { + fol_SetFalse(BindQuantor); + return TRUE; + } + } + else /* Exquantor */ + if (symbol_Equal(SuperTop, fol_And())) { + fol_SetTrue(BindQuantor); + return TRUE; + } + + return FALSE; +} + + +BOOL fol_PropagateWitness(TERM Term) +/************************************************************** + INPUT: A Term. + RETURNS: True in case of witness propagation. + EFFECT: Substitutes any subterm of Term of the form + forall([x],implies(P(x),x=t)) + forall([x],implied(x=t,P(x))) + forall([x],or(notP(x),x=t)) by FALSE and + exists([x],and(P(x),x=t)) by TRUE, where + P has property FREELY and GENERATED, x doesn't occur in t. +***************************************************************/ +{ + BOOL Hit; + LIST Scan; + + Hit = FALSE; + + if (fol_IsQuantifier(term_TopSymbol(Term))) + return fol_PropagateWitness(term_SecondArgument(Term)); + if (fol_IsEquality(Term)) { + if (term_IsVariable(term_SecondArgument(Term))) { + if (!term_ContainsSymbol(term_FirstArgument(Term), term_TopSymbol(term_SecondArgument(Term)))) + Hit = fol_PropagateWitnessIntern(Term,term_TopSymbol(term_SecondArgument(Term))); + } + else { + if (term_IsVariable(term_FirstArgument(Term))) + if (!term_ContainsSymbol(term_SecondArgument(Term), term_TopSymbol(term_FirstArgument(Term)))) + Hit = fol_PropagateWitnessIntern(Term,term_TopSymbol(term_FirstArgument(Term))); + } + } + if (symbol_IsPredicate(term_TopSymbol(Term))) + return FALSE; + + for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (fol_PropagateWitness(list_Car(Scan))) + Hit = TRUE; + + return Hit; +} + +BOOL fol_PropagateTautologies(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: True iff function replaced a subterm. + EFFECT: Replaces all occurences of t=t, or(A,not(A)) by TRUE + and and(A,not(A)) by FALSE. +***************************************************************/ +{ + BOOL Hit; + LIST Scan, Bscan, ArgumentList; + SYMBOL Top; + + Top = term_TopSymbol(Term); + Hit = FALSE; + ArgumentList = term_ArgumentList(Term); + + if (fol_IsQuantifier(Top)) + return fol_PropagateTautologies(term_SecondArgument(Term)); + + if (fol_IsEquality(Term)) { + if (term_Equal(term_FirstArgument(Term), term_SecondArgument(Term))) { + fol_SetTrue(Term); + return TRUE; + } + } + + if (symbol_Equal(Top, fol_Or()) || symbol_Equal(Top, fol_And())) { + for (Scan = ArgumentList; !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (symbol_Equal(term_TopSymbol(list_Car(Scan)), fol_Not())) { + for (Bscan = ArgumentList; !list_Empty(Bscan); Bscan = list_Cdr(Bscan)) { + if (list_Car(Scan) != list_Car(Bscan) && + fol_AlphaEqual(term_FirstArgument(list_Car(Scan)), list_Car(Bscan))) { + if (symbol_Equal(Top, fol_Or())) + fol_SetTrue(Term); + else + fol_SetFalse(Term); + return TRUE; + } + } + } + } + + if (!term_IsAtom(Term)) + for (Scan = ArgumentList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (fol_PropagateTautologies(list_Car(Scan))) + Hit = TRUE; + } + + return Hit; +} + + +static BOOL fol_AlphaEqualIntern(TERM Term1, TERM Term2, NAT Mark) +/************************************************************** + INPUT: Two terms which represent formulae and a binding mark. + RETURNS: True iff Term2 is equal to Term1 with respect to the + renaming of bound variables. +***************************************************************/ +{ + LIST Scan, Bscan; + SYMBOL Top1, Top2; + + Top1 = term_TopSymbol(Term1); + Top2 = term_TopSymbol(Term2); + + if (symbol_IsVariable(Top1) && symbol_IsVariable(Top2)) { + if (term_VarIsMarked(Top2, Mark)) + return symbol_Equal(Top1, (SYMBOL)term_BindingValue(Top2)); + else + return symbol_Equal(Top1, Top2); + } + + if (!symbol_Equal(Top1, Top2)) + return FALSE; + + if (fol_IsQuantifier(Top1)) { + if (list_Length(fol_QuantifierVariables(Term1)) != list_Length(fol_QuantifierVariables(Term2))) + return FALSE; + for (Scan = fol_QuantifierVariables(Term1), Bscan = fol_QuantifierVariables(Term2); + !list_Empty(Scan); + Scan = list_Cdr(Scan), Bscan = list_Cdr(Bscan)) + term_CreateValueBinding(term_TopSymbol(list_Car(Bscan)), Mark, + (POINTER)term_TopSymbol(list_Car(Scan))); + + if (!fol_AlphaEqualIntern(term_SecondArgument(Term1), term_SecondArgument(Term2), Mark)) + return FALSE; + for (Scan = fol_QuantifierVariables(Term1), Bscan = fol_QuantifierVariables(Term2); + !list_Empty(Scan); + Scan = list_Cdr(Scan), Bscan = list_Cdr(Bscan)) + term_SetBindingMark(term_TopSymbol(list_Car(Bscan)), term_NullMark()); + } + else { + if (list_Length(term_ArgumentList(Term1)) != list_Length(term_ArgumentList(Term2))) + return FALSE; + + for (Scan = term_ArgumentList(Term1), Bscan = term_ArgumentList(Term2); + !list_Empty(Scan); Scan = list_Cdr(Scan), Bscan = list_Cdr(Bscan)) + if (!fol_AlphaEqualIntern(list_Car(Scan), list_Car(Bscan), Mark)) + return FALSE; + } + return TRUE; +} + + +BOOL fol_AlphaEqual(TERM Term1, TERM Term2) +/************************************************************** + INPUT: Two terms of the form Qx(<rest>). All variables that occur in + Term1 and Term2 must be bound by only one quantifier! + RETURNS: TRUE iff Term2 is bound renaming of Term1. +***************************************************************/ +{ + BOOL Hit; + +#ifdef CHECK + if (Term1 == term_Null() || Term2 == term_Null()) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_AlphaEqual: Corrupted term as parameter.\n"); + misc_FinishErrorReport(); + } + if (fol_VarBoundTwice(Term1) || fol_VarBoundTwice(Term2)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_AlphaEqual: Variables are bound more than once.\n"); + misc_FinishErrorReport(); + } + if (term_InBindingPhase()) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_AlphaEqual: Term context is in binding phase.\n"); + misc_FinishErrorReport(); + } +#endif + + term_StartBinding(); + + Hit = fol_AlphaEqualIntern(Term1, Term2, term_ActMark()); + + term_StopBinding(); + + return Hit; +} + + +static BOOL fol_VarBoundTwiceIntern(TERM Term, NAT Mark) +/************************************************************** + INPUT: A term, possibly a NULL Term and a valid binding mark. + RETURNS: TRUE iff a variable in <Term> is bound by more than one quantifier. +***************************************************************/ +{ + LIST Scan; + + if (Term == term_Null()) + return FALSE; + + if (term_IsAtom(Term)) + return FALSE; + + if (!fol_IsQuantifier(term_TopSymbol(Term))) { + for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (fol_VarBoundTwiceIntern(list_Car(Scan), Mark)) + return TRUE; + } + else { + for (Scan = fol_QuantifierVariables(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (!term_VarIsMarked(term_TopSymbol(list_Car(Scan)), Mark)) + term_SetBindingMark(term_TopSymbol(list_Car(Scan)), Mark); + else + return TRUE; + } + if (fol_VarBoundTwiceIntern(term_SecondArgument(Term), Mark)) + return TRUE; + for (Scan = fol_QuantifierVariables(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) + term_SetBindingMark(term_TopSymbol(list_Car(Scan)), term_NullMark()); + } + return FALSE; +} + + +BOOL fol_VarBoundTwice(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: TRUE iff a variable in term is bound by more than one quantifier. +***************************************************************/ +{ + BOOL Hit; + +#ifdef CHECK + if (term_InBindingPhase()) { + misc_StartErrorReport(); + misc_ErrorReport("\n\n Context in fol_VarBoundTwice: term in binding phase\n"); + misc_FinishErrorReport(); + } +#endif + + term_StartBinding(); + + Hit = fol_VarBoundTwiceIntern(Term, (NAT)term_ActMark()); + + term_StopBinding(); + + return Hit; +} + + +NAT fol_Depth(TERM Term) +/************************************************************** + INPUT: A formula. + RETURNS: The depth of the formula up to predicate level. +***************************************************************/ +{ + NAT Depth,Help; + LIST Scan; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_Depth: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + Depth = 0; + + if (symbol_IsPredicate(term_TopSymbol(Term))) + return 1; + + if (fol_IsQuantifier(term_TopSymbol(Term))) + return (fol_Depth(term_SecondArgument(Term)) + 1); + + for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) { + Help = fol_Depth(list_Car(Scan)); + if (Help > Depth) + Depth = Help; + } + + return (Depth+1); +} + + +static void fol_ApplyContextToTermIntern(CONTEXT Context, TERM Term) +/******************************************************************** + INPUT: A context (Context) and a term (Term). + RETURN: void. + EFFECT: Term is destructively changed modulo Context. +*********************************************************************/ +{ + LIST Scan; + + if (fol_IsQuantifier(term_TopSymbol(Term))) { + fol_ApplyContextToTermIntern(Context, term_SecondArgument(Term)); + } + else if (symbol_IsVariable(term_TopSymbol(Term))) { + if (cont_VarIsBound(Context, term_TopSymbol(Term))) + Term = cont_ApplyBindingsModuloMatching(Context, Term, TRUE); + } + else { + for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) + fol_ApplyContextToTermIntern(Context, list_Car(Scan)); + } +} + + +static BOOL fol_CheckApplyContextToTerm(CONTEXT Context, TERM Term) +/************************************************************* + INPUT: A Context and a term. + RETURN: TRUE iff Context can be applied to Term. + COMMENT: Intern funktion of fol_ApplyContextToTerm. +**************************************************************/ +{ + LIST Scan; + BOOL Apply; + + Apply = TRUE; + + if (fol_IsQuantifier(term_TopSymbol(Term))) { + for (Scan=fol_QuantifierVariables(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) + if (cont_VarIsBound(Context, term_TopSymbol(list_Car(Scan)))) + return FALSE; + for (Scan=term_ArgumentList(term_SecondArgument(Term)); !list_Empty(Scan); Scan=list_Cdr(Scan)) { + if (!fol_CheckApplyContextToTerm(Context, list_Car(Scan))) + Apply = FALSE; + } + } + else { + for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) + if (!fol_CheckApplyContextToTerm(Context, list_Car(Scan))) + Apply = FALSE; + } + return Apply; +} + + +BOOL fol_ApplyContextToTerm(CONTEXT Context, TERM Term) +/*************************************************************** + INPUT: A context (Context) and a term (Term). + RETURN: TRUE iff context could be applied on Term. + EFFECT: Term is destructively changed modulo Context iff possible. +****************************************************************/ +{ + if (fol_CheckApplyContextToTerm(Context, Term)) { + fol_ApplyContextToTermIntern(Context, Term); + return TRUE; + } + + return FALSE; +} + + +BOOL fol_SignatureMatchFormula(TERM Formula, TERM Instance, BOOL Variant) +/******************************************************************** + INPUT : Two formulas and a flag. + It is assumed that the symbol context is clean. + RETURN: TRUE iff <Formula> can be matched to <Instance> by matching + variables as well as signature symbols. If <Variant> is TRUE + variables must be matched to variables. + EFFECT: The symbol matches are stored in the symbol context. +*********************************************************************/ +{ + int Stack; + SYMBOL FormulaTop, InstanceTop; + NAT ActMark; + TERM ActFormula, ActInstance; + +#ifdef CHECK + if (!term_IsTerm(Formula) || term_InBindingPhase() || + !term_IsTerm(Instance) || !symbol_ContextIsClean()) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_SignatureMatchFormula: Illegal input or context."); + misc_FinishErrorReport(); + } +#endif + + term_StartBinding(); + + Stack = stack_Bottom(); + term_NewMark(); + ActMark = term_OldMark(); + ActFormula = Formula; + ActInstance = Instance; + + do { + FormulaTop = term_TopSymbol(ActFormula); + InstanceTop = term_TopSymbol(ActInstance); + + if (!symbol_IsVariable(FormulaTop)) { + if (!symbol_ContextIsBound(FormulaTop)) { + if (!symbol_IsJunctor(FormulaTop) && !symbol_IsJunctor(InstanceTop) && + !fol_IsPredefinedPred(FormulaTop) && !fol_IsPredefinedPred(InstanceTop)) + symbol_ContextSetValue(FormulaTop, InstanceTop); /* Symbols are ALWAYS bound !*/ + else { + if (!symbol_Equal(FormulaTop, InstanceTop)) { + term_StopBinding(); + return FALSE; + } + } + } + else { + if (symbol_ContextIsBound(FormulaTop) && + !symbol_Equal(symbol_ContextGetValue(FormulaTop),InstanceTop)) { + term_StopBinding(); + return FALSE; + } + } + } + + if (list_Length(term_ArgumentList(ActFormula)) != list_Length(term_ArgumentList(ActInstance))) { + term_StopBinding(); + return FALSE; + } + + if (term_IsComplex(ActFormula)) { + stack_Push(term_ArgumentList(ActInstance)); + stack_Push(term_ArgumentList(ActFormula)); + } + else { + if (symbol_IsVariable(FormulaTop)) { + if (!term_VarIsMarked(FormulaTop, ActMark)) { + if (!Variant || symbol_IsVariable(InstanceTop)) + term_CreateValueBinding(FormulaTop, ActMark, (POINTER)InstanceTop); + else { + term_StopBinding(); + return FALSE; + } + } + else { + if (!symbol_Equal((SYMBOL)term_BindingValue(FormulaTop), InstanceTop)) { + term_StopBinding(); + return FALSE; + } + } + } + } + + while (!stack_Empty(Stack) && list_Empty(stack_Top())) { + stack_Pop(); + stack_Pop(); + } + if (!stack_Empty(Stack)) { + ActFormula = (TERM)list_Car(stack_Top()); + ActInstance = (TERM)list_Car(stack_NthTop(1)); + stack_RplacTop(list_Cdr(stack_Top())); + stack_RplacNthTop(1,list_Cdr(stack_NthTop(1))); + } + } while (!stack_Empty(Stack)); + + term_StopBinding(); + + return TRUE; +} + + +BOOL fol_SignatureMatch(TERM Term, TERM Instance, LIST* Bindings, BOOL Variant) +/***************************************************************** + INPUT : Two formulas, a binding list and a boolean flag. + RETURN: TRUE iff <Term> can be matched to <Instance> by matching + variables as well as signature symbols. If <Variant> is TRUE + variables must be matched to variables. Signature symbol + matchings have to be injective. + EFFECT: The symbol matches are stored in the symbol context. +******************************************************************/ +{ + int Stack; + SYMBOL TermTop, InstanceTop; + NAT ActMark; + TERM ActTerm, ActInstance; + +#ifdef CHECK + if (!term_IsTerm(Term) || !term_IsTerm(Instance)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In fol_SignatureMatch: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Stack = stack_Bottom(); + ActMark = term_OldMark(); + ActTerm = Term; + ActInstance = Instance; + + do { + TermTop = term_TopSymbol(ActTerm); + InstanceTop = term_TopSymbol(ActInstance); + + if (!symbol_IsVariable(TermTop)) { + if (!symbol_ContextIsBound(TermTop)) { + if (!symbol_IsJunctor(TermTop) && !symbol_IsJunctor(InstanceTop) && + !fol_IsPredefinedPred(TermTop) && !fol_IsPredefinedPred(InstanceTop) && + !symbol_ContextIsMapped(InstanceTop)) { + symbol_ContextSetValue(TermTop, InstanceTop); /* Symbols are ALWAYS bound !*/ + *Bindings = list_Cons((POINTER)TermTop,*Bindings); + } + else { + if (!symbol_Equal(TermTop, InstanceTop)) { + return FALSE; + } + } + } + else { + if (symbol_ContextIsBound(TermTop) && + !symbol_Equal(symbol_ContextGetValue(TermTop),InstanceTop)) { + return FALSE; + } + } + } + + if (list_Length(term_ArgumentList(ActTerm)) != list_Length(term_ArgumentList(ActInstance))) { + return FALSE; + } + + if (term_IsComplex(ActTerm)) { + stack_Push(term_ArgumentList(ActInstance)); + stack_Push(term_ArgumentList(ActTerm)); + } + else { + if (symbol_IsVariable(TermTop)) { + if (!term_VarIsMarked(TermTop, ActMark)) { + if (!Variant || symbol_IsVariable(InstanceTop)) { + term_CreateValueBinding(TermTop, ActMark, (POINTER)InstanceTop); + *Bindings = list_Cons((POINTER)TermTop,*Bindings); + } + else + return FALSE; + } + else { + if (!symbol_Equal((SYMBOL)term_BindingValue(TermTop), InstanceTop)) { + return FALSE; + } + } + } + } + + while (!stack_Empty(Stack) && list_Empty(stack_Top())) { + stack_Pop(); + stack_Pop(); + } + if (!stack_Empty(Stack)) { + ActTerm = (TERM)list_Car(stack_Top()); + ActInstance = (TERM)list_Car(stack_NthTop(1)); + stack_RplacTop(list_Cdr(stack_Top())); + stack_RplacNthTop(1,list_Cdr(stack_NthTop(1))); + } + } while (!stack_Empty(Stack)); + + return TRUE; +} + + +BOOL fol_CheckFormula(TERM Formula) +/******************************************************************* + INPUT : A term Formula. + RETURN: TRUE iff no free variables occure in Formula + and father links are properly set + and argument list lengths match arities +********************************************************************/ +{ + LIST FreeVars; + + FreeVars = fol_FreeVariables(Formula); + + if (!list_Empty(FreeVars)) { + list_Delete(FreeVars); + return FALSE; + } + + return term_CheckTerm(Formula); +} diff --git a/test/spass/foldfg.h b/test/spass/foldfg.h new file mode 100644 index 0000000000000000000000000000000000000000..3704e44e469dd66a7ed59084c04dff0d1901f9be --- /dev/null +++ b/test/spass/foldfg.h @@ -0,0 +1,303 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * FIRST ORDER LOGIC SYMBOLS * */ +/* * * */ +/* * $Module: FOL DFG * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _FOLDFG_ +#define _FOLDFG_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "flags.h" +#include "unify.h" +#include "context.h" +#include "term.h" + +/**************************************************************/ +/* Global Variables and Constants (Only seen by macros) */ +/**************************************************************/ + +extern SYMBOL fol_ALL; +extern SYMBOL fol_EXIST; +extern SYMBOL fol_AND; +extern SYMBOL fol_OR; +extern SYMBOL fol_NOT; +extern SYMBOL fol_IMPLIES; +extern SYMBOL fol_IMPLIED; +extern SYMBOL fol_EQUIV; +extern SYMBOL fol_VARLIST; +extern SYMBOL fol_EQUALITY; +extern SYMBOL fol_TRUE; +extern SYMBOL fol_FALSE; + +/**************************************************************/ +/* Access to the first-order symbols. */ +/**************************************************************/ + +static __inline__ SYMBOL fol_All(void) +{ + return fol_ALL; +} + +static __inline__ SYMBOL fol_Exist(void) +{ + return fol_EXIST; +} + +static __inline__ SYMBOL fol_And(void) +{ + return fol_AND; +} + +static __inline__ SYMBOL fol_Or(void) +{ + return fol_OR; +} + +static __inline__ SYMBOL fol_Not(void) +{ + return fol_NOT; +} + +static __inline__ SYMBOL fol_Implies(void) +{ + return fol_IMPLIES; +} + +static __inline__ SYMBOL fol_Implied(void) +{ + return fol_IMPLIED; +} + +static __inline__ SYMBOL fol_Equiv(void) +{ + return fol_EQUIV; +} + +static __inline__ SYMBOL fol_Varlist(void) +{ + return fol_VARLIST; +} + +static __inline__ SYMBOL fol_Equality(void) +{ + return fol_EQUALITY; +} + +static __inline__ SYMBOL fol_True(void) +{ + return fol_TRUE; +} + +static __inline__ SYMBOL fol_False(void) +{ + return fol_FALSE; +} + +/**************************************************************/ +/* Macros */ +/**************************************************************/ + +static __inline__ BOOL fol_IsQuantifier(SYMBOL S) +{ + return symbol_Equal(fol_ALL,S) || symbol_Equal(fol_EXIST,S); +} + +static __inline__ BOOL fol_IsTrue(TERM S) +{ + return symbol_Equal(fol_TRUE,term_TopSymbol(S)); +} + +static __inline__ BOOL fol_IsFalse(TERM S) +{ + return symbol_Equal(fol_FALSE,term_TopSymbol(S)); +} + +static __inline__ LIST fol_QuantifierVariables(TERM T) + /* T's top symbol must be a quantifier ! */ +{ + return term_ArgumentList(term_FirstArgument(T)); +} + +static __inline__ BOOL fol_IsLiteral(TERM T) +{ + return symbol_IsPredicate(term_TopSymbol(T)) || + (symbol_Equal(term_TopSymbol(T),fol_Not()) && + symbol_IsPredicate(term_TopSymbol(term_FirstArgument(T)))); +} + +static __inline__ BOOL fol_IsNegativeLiteral(TERM T) +{ + return (symbol_Equal(term_TopSymbol(T),fol_Not()) && + symbol_IsPredicate(term_TopSymbol(term_FirstArgument(T)))); +} + + +static __inline__ BOOL fol_IsJunctor(SYMBOL S) +{ + return fol_IsQuantifier(S) || symbol_Equal(S, fol_AND) || + symbol_Equal(S, fol_OR) || symbol_Equal(S, fol_NOT) || + symbol_Equal(S, fol_IMPLIED) || symbol_Equal(S, fol_VARLIST) || + symbol_Equal(S, fol_IMPLIES) || symbol_Equal(S, fol_EQUIV); +} + +static __inline__ BOOL fol_IsPredefinedPred(SYMBOL S) +{ + return symbol_Equal(S, fol_EQUALITY) || symbol_Equal(S, fol_TRUE) || + symbol_Equal(S, fol_FALSE); +} + +static __inline__ TERM fol_Atom(TERM Lit) +{ + if (term_TopSymbol(Lit) == fol_NOT) + return term_FirstArgument(Lit); + else + return Lit; +} + +static __inline__ BOOL fol_IsEquality(TERM Term) +{ + return term_TopSymbol(Term) == fol_EQUALITY; +} + + +static __inline__ BOOL fol_IsAssignment(TERM Term) +{ + return (term_TopSymbol(Term) == fol_EQUALITY && + ((term_IsVariable(term_FirstArgument(Term)) && + !term_ContainsVariable(term_SecondArgument(Term), + term_TopSymbol(term_FirstArgument(Term)))) || + (term_IsVariable(term_SecondArgument(Term)) && + !term_ContainsVariable(term_FirstArgument(Term), + term_TopSymbol(term_SecondArgument(Term)))))); +} + + +static __inline__ LIST fol_DeleteFalseTermFromList(LIST List) +/************************************************************** + INPUT: A list of terms. + RETURNS: The list where all terms equal to the 'False' term are removed. + EFFECTS: 'False' is a special predicate from the fol module. + Terms are compared with respect to the term_Equal function. + The terms are deleted, too. +***************************************************************/ +{ + return list_DeleteElementIfFree(List, (BOOL (*)(POINTER))fol_IsFalse, + (void (*)(POINTER))term_Delete); +} + + +static __inline__ LIST fol_DeleteTrueTermFromList(LIST List) +/************************************************************** + INPUT: A list of terms. + RETURNS: The list where all terms equal to the 'True' term are removed. + EFFECTS: 'True' is a special predicate from the fol module. + Terms are compared with respect to the term_Equal function. + The terms are deleted, too. +***************************************************************/ +{ + return list_DeleteElementIfFree(List, (BOOL (*)(POINTER))fol_IsTrue, + (void (*)(POINTER))term_Delete); +} + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +void fol_Init(BOOL, PRECEDENCE); +SYMBOL fol_IsStringPredefined(const char*); +TERM fol_CreateQuantifier(SYMBOL, LIST, LIST); +TERM fol_CreateQuantifierAddFather(SYMBOL, LIST, LIST); +LIST fol_GetNonFOLPredicates(void); +TERM fol_ComplementaryTerm(TERM); +LIST fol_GetAssignments(TERM); +void fol_Free(void); +void fol_CheckFatherLinks(TERM); +BOOL fol_FormulaIsClause(TERM); +void fol_FPrintOtterOptions(FILE*, BOOL, FLAG_TDFG2OTTEROPTIONSTYPE); +void fol_FPrintOtter(FILE*, LIST, FLAG_TDFG2OTTEROPTIONSTYPE); +void fol_FPrintDFGSignature(FILE*); +void fol_PrettyPrintDFG(TERM); +void fol_PrintDFG(TERM); +void fol_FPrintDFG(FILE*, TERM); +void fol_FPrintDFGProblem(FILE*, const char*, const char*, const char*, const char*, LIST, LIST); +void fol_PrintPrecedence(PRECEDENCE); +void fol_FPrintPrecedence(FILE*, PRECEDENCE); +LIST fol_Instances(TERM, TERM); +LIST fol_Generalizations(TERM, TERM); +TERM fol_MostGeneralFormula(LIST); +void fol_NormalizeVars(TERM); +void fol_NormalizeVarsStartingAt(TERM, SYMBOL); +LIST fol_FreeVariables(TERM); +LIST fol_BoundVariables(TERM); +BOOL fol_VarOccursFreely(TERM,TERM); +BOOL fol_AssocEquation(TERM, SYMBOL *); +BOOL fol_DistributiveEquation(TERM, SYMBOL*, SYMBOL*); +void fol_ReplaceVariable(TERM, SYMBOL, TERM); +void fol_PrettyPrint(TERM); +LIST fol_GetSubstEquations(TERM); +TERM fol_GetBindingQuantifier(TERM, SYMBOL); +int fol_TermPolarity(TERM, TERM); +BOOL fol_PolarCheck(TERM, TERM); +void fol_PopQuantifier(TERM); +void fol_DeleteQuantifierVariable(TERM,SYMBOL); +void fol_SetTrue(TERM); +void fol_SetFalse(TERM); +void fol_RemoveImplied(TERM); +BOOL fol_PropagateFreeness(TERM); +BOOL fol_PropagateWitness(TERM); +BOOL fol_PropagateTautologies(TERM); +BOOL fol_AlphaEqual(TERM, TERM); +BOOL fol_VarBoundTwice(TERM); +NAT fol_Depth(TERM); +BOOL fol_ApplyContextToTerm(CONTEXT, TERM); +BOOL fol_CheckFormula(TERM); +BOOL fol_SignatureMatchFormula(TERM, TERM, BOOL); +BOOL fol_SignatureMatch(TERM, TERM, LIST*, BOOL); + +#endif diff --git a/test/spass/graph.c b/test/spass/graph.c new file mode 100644 index 0000000000000000000000000000000000000000..732fa0e82f6a5a275b6e293544d1b2a266944777 --- /dev/null +++ b/test/spass/graph.c @@ -0,0 +1,318 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * GRAPHS * */ +/* * * */ +/* * $Module: GRAPH * */ +/* * * */ +/* * Copyright (C) 1998, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "graph.h" + + +static LIST graph_ROOTS; /* used as stack by SCC algorithm */ +static LIST graph_UNFINISHED; /* used as stack by SCC algorithm */ + + +void graph_NodePrint(GRAPHNODE Node) +/************************************************************** + INPUT: A graph node. + RETURNS: Nothing. + EFFECT: Prints some node information to stdout. +***************************************************************/ +{ + printf("(%d,%d,%d) ", graph_NodeNumber(Node), graph_NodeDfsNum(Node), + graph_NodeCompNum(Node)); +} + + +GRAPH graph_Create(void) +/************************************************************** + INPUT: None. + RETURNS: A new graph without nodes and edges. +***************************************************************/ +{ + GRAPH result; + + result = memory_Malloc(sizeof(GRAPH_STRUCT)); + result->size = 0; + result->dfscount = 0; + result->compcount = 0; + result->nodes = list_Nil(); + return result; +} + + +void graph_Delete(GRAPH Graph) +/************************************************************** + INPUT: A graph. + RETURNS: Nothing. + EFFECT: All memory required by the graph and its nodes + is freed. +***************************************************************/ +{ + for ( ; !list_Empty(Graph->nodes); Graph->nodes = list_Pop(Graph->nodes)) { + list_Delete(graph_NodeNeighbors(list_Car(Graph->nodes))); + memory_Free(list_Car(Graph->nodes), sizeof(GRAPHNODE_STRUCT)); + } + memory_Free(Graph, sizeof(GRAPH_STRUCT)); +} + + +GRAPHNODE graph_GetNode(GRAPH Graph, NAT Number) +/************************************************************** + INPUT: A graph and the ID of a node. + RETURNS: The node with the requested number or NULL + if such a node doesn't exist. +***************************************************************/ +{ + LIST scan; + + for (scan = Graph->nodes; !list_Empty(scan); scan= list_Cdr(scan)) { + if (graph_NodeNumber(list_Car(scan)) == Number) + return list_Car(scan); + } + + return NULL; +} + + +GRAPHNODE graph_AddNode(GRAPH Graph, NAT Number) +/************************************************************** + INPUT: A graph and the ID of a node. + RETURNS: A node with the requested number. + EFFECT: If the graph has no such node, a new node is created. +***************************************************************/ +{ + GRAPHNODE result; + + result = graph_GetNode(Graph, Number); + if (result == NULL) { + result = memory_Malloc(sizeof(GRAPHNODE_STRUCT)); + Graph->nodes = list_Cons(result, Graph->nodes); + result->number = Number; + result->dfs_num = -1; + result->comp_num = -1; + result->info = NULL; + result->neighbors = list_Nil(); + } + return result; +} + + +void graph_AddEdge(GRAPHNODE From, GRAPHNODE To) +/************************************************************** + INPUT: Two graph nodes. + RETURNS: Nothing. + EFFECT: Adds a single (directed) edge (From, To). +***************************************************************/ +{ + From->neighbors = list_Cons(To, From->neighbors); +} + + +void graph_DeleteEdge(GRAPHNODE From, GRAPHNODE To) +/************************************************************** + INPUT: Two graph nodes. + RETURNS: Nothing. + EFFECT: Removes ALL edges (From, To) from a graph. +***************************************************************/ +{ + From->neighbors = list_PointerDeleteElement(From->neighbors, To); +} + + +void graph_DeleteDuplicateEdges(GRAPH Graph) +/************************************************************** + INPUT: A graph. + RETURNS: Nothing. + EFFECT: Removes duplicate edges between all nodes. +***************************************************************/ +{ + LIST scan; + + for (scan = graph_Nodes(Graph); !list_Empty(scan); scan = list_Cdr(scan)) { + GRAPHNODE n = list_Car(scan); + n->neighbors = list_PointerDeleteDuplicates(n->neighbors); + } +} + + +void graph_SortNodes(GRAPH Graph, BOOL (*SortFunction)(GRAPHNODE, GRAPHNODE)) +/************************************************************** + INPUT: A graph and a sorting function for graph nodes. + RETURNS: Nothing. + EFFECT: The node list is sorted with respect to the + sorting function. +***************************************************************/ +{ + Graph->nodes = list_Sort(graph_Nodes(Graph), + (BOOL (*) (POINTER, POINTER)) SortFunction); +} + + +static void graph_ReinitDFS(GRAPH Graph) +/************************************************************** + INPUT: A graph. + RETURNS: Nothing. + EFFECT: Prepares the graph and its nodes for a new DFS run. + The DFS and COMP numbers are reset. +***************************************************************/ +{ + LIST scan; + + Graph->dfscount = 0; + Graph->compcount = 0; + + for (scan = graph_Nodes(Graph); !list_Empty(scan); scan = list_Cdr(scan)) { + graph_NodeSetDfsNum(list_Car(scan), -1); + graph_NodeSetCompNum(list_Car(scan), -1); + } +} + + +static void graph_InternSCC(GRAPH Graph, GRAPHNODE Node) +/************************************************************** + INPUT: A graph and a node of the graph. + RETURNS: Nothing. + EFFECT: This is an internal function used by + graph_StronglyConnnectedComponents. + It sets information in the graph structure which + specifies the strongly connected components of + the graph. +***************************************************************/ +{ + GRAPHNODE n; + LIST scan; + NAT act_dfs; + + act_dfs = (Graph->dfscount)++; + graph_NodeSetDfsNum(Node, act_dfs); + + graph_UNFINISHED = list_Push(Node, graph_UNFINISHED); + graph_ROOTS = list_Push(Node, graph_ROOTS); + + /* putchar('\n'); list_Apply(graph_NodePrint, graph_UNFINISHED); + putchar('\n'); list_Apply(graph_NodePrint, graph_ROOTS); + fflush(stdout); DBG */ + + for (scan = graph_NodeNeighbors(Node); + !list_Empty(scan); scan = list_Cdr(scan)) { + n = list_Car(scan); + if (!graph_NodeVisited(n)) { + graph_InternSCC(Graph, n); /* Visit <n> */ + } else if (!graph_NodeCompleted(n)) { + /* <n> was visited but is not yet in a permanent component */ + NAT dfs_num_of_n = graph_NodeDfsNum(n); + while (!list_StackEmpty(graph_ROOTS) && + graph_NodeDfsNum(list_Top(graph_ROOTS)) > dfs_num_of_n) + graph_ROOTS = list_Pop(graph_ROOTS); + /* putchar('\n'); list_Apply(symbol_Print, graph_UNFINISHED); + putchar('\n'); list_Apply(symbol_Print, graph_ROOTS); + fflush(stdout); DBG */ + } + } + + /* printf("\nDFS(%u) complete.", graph_NodeNumber(Node)); DBG */ + + if (Node == list_Top(graph_ROOTS)) { + /* Node is root of a component, so make this component permanent */ + while (!list_StackEmpty(graph_UNFINISHED) && + graph_NodeDfsNum(list_Top(graph_UNFINISHED)) >= act_dfs) { + n = list_Top(graph_UNFINISHED); + graph_UNFINISHED = list_Pop(graph_UNFINISHED); + graph_NodeSetCompNum(n, Graph->compcount); + } + Graph->compcount++; + graph_ROOTS = list_Pop(graph_ROOTS); + } + + /* putchar('\n'); list_Apply(graph_NodePrint, graph_UNFINISHED); + putchar('\n'); list_Apply(graph_NodePrint, graph_ROOTS); fflush(stdout); DBG */ +} + + +NAT graph_StronglyConnectedComponents(GRAPH Graph) +/************************************************************** + INPUT: A graph. + RETURNS: The number of strongly connected components + in the graph. + EFFECT: This function sets the component numbers of all nodes. + Two nodes that belong to the same component will have + the same component number. + The algorithm is taken from the script + "Datenstrukturen und Algorithmen" by Kurt Mehlhorn + in winter semester 1997/98, pages 86-92. +***************************************************************/ +{ + LIST scan; + + if (Graph->dfscount != 0) + graph_ReinitDFS(Graph); /* Reinitializations for Depth First Search */ + + graph_ROOTS = list_Nil(); + graph_UNFINISHED = list_Nil(); + + for (scan = graph_Nodes(Graph); !list_Empty(scan); scan = list_Cdr(scan)) { + if (!graph_NodeVisited(list_Car(scan))) + graph_InternSCC(Graph, list_Car(scan)); + } + return Graph->compcount; +} + + +void graph_Print(GRAPH Graph) +/************************************************************** + INPUT: A graph. + RETURNS: Nothing. + EFFECT: The adjacency list representation of the graph + is printed to stdout. +***************************************************************/ +{ + LIST scan1, scan2; + + for (scan1 = graph_Nodes(Graph); !list_Empty(scan1); scan1 = list_Cdr(scan1)) { + printf("\n%u -> ", graph_NodeNumber(list_Car(scan1))); + for (scan2 = graph_NodeNeighbors(list_Car(scan1)); !list_Empty(scan2); + scan2 = list_Cdr(scan2)) { + printf("%u,", graph_NodeNumber(list_Car(scan2))); + } + } +} diff --git a/test/spass/graph.h b/test/spass/graph.h new file mode 100644 index 0000000000000000000000000000000000000000..411f4f26a51222e049df4eab91ae060408b4f281 --- /dev/null +++ b/test/spass/graph.h @@ -0,0 +1,148 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * GRAPHS * */ +/* * * */ +/* * $Module: GRAPH * */ +/* * * */ +/* * Copyright (C) 1998, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _GRAPH_ +#define _GRAPH_ + +#include "list.h" + +typedef struct { + NAT number; + int dfs_num; + int comp_num; /* completion number */ + POINTER info; /* user defined information */ + LIST neighbors; +} GRAPHNODE_STRUCT, *GRAPHNODE; + +typedef struct { + NAT size; /* number of nodes */ + LIST nodes; /* list of GRAPHNODES */ + NAT dfscount; /* used for DFS */ + NAT compcount; /* used for DFS */ +} GRAPH_STRUCT, *GRAPH; + +static __inline__ NAT graph_NodeNumber(GRAPHNODE Node) +{ + return Node->number; +} + +static __inline__ int graph_NodeDfsNum(GRAPHNODE Node) +{ + return Node->dfs_num; +} + +static __inline__ void graph_NodeSetDfsNum(GRAPHNODE Node, int Number) +{ + Node->dfs_num = Number; +} + +static __inline__ int graph_NodeCompNum(GRAPHNODE Node) +{ + return Node->comp_num; +} + +static __inline__ void graph_NodeSetCompNum(GRAPHNODE Node, int Number) +{ + Node->comp_num = Number; +} + +static __inline__ LIST graph_NodeNeighbors(GRAPHNODE Node) +{ + return Node->neighbors; +} + +static __inline__ POINTER graph_NodeInfo(GRAPHNODE Node) +{ + return Node->info; +} + +static __inline__ void graph_NodeSetInfo(GRAPHNODE Node, POINTER Info) +{ + Node->info = Info; +} + +static __inline__ NAT graph_NodeOutdegree(GRAPHNODE Node) +{ + return list_Length(graph_NodeNeighbors(Node)); +} + +static __inline__ BOOL graph_NodeVisited(GRAPHNODE Node) +{ + return graph_NodeDfsNum(Node) >= 0; +} + +static __inline__ BOOL graph_NodeCompleted(GRAPHNODE Node) +{ + return graph_NodeCompNum(Node) >= 0; +} + +static __inline__ NAT graph_Size(GRAPH Graph) +{ + return Graph->size; +} + +static __inline__ LIST graph_Nodes(GRAPH Graph) +{ + return Graph->nodes; +} + +GRAPH graph_Create(void); +void graph_Delete(GRAPH); + +GRAPHNODE graph_GetNode(GRAPH, NAT); +GRAPHNODE graph_AddNode(GRAPH, NAT); + +void graph_AddEdge(GRAPHNODE, GRAPHNODE); +void graph_DeleteEdge(GRAPHNODE, GRAPHNODE); +void graph_DeleteDuplicateEdges(GRAPH); + +void graph_SortNodes(GRAPH, BOOL (*)(GRAPHNODE, GRAPHNODE)); +NAT graph_StronglyConnectedComponents(GRAPH); + +void graph_NodePrint(GRAPHNODE Node); +void graph_Print(GRAPH); + +#endif diff --git a/test/spass/hash.c b/test/spass/hash.c new file mode 100644 index 0000000000000000000000000000000000000000..d9f996c06be7517f30ea6e70d23a94435811fc60 --- /dev/null +++ b/test/spass/hash.c @@ -0,0 +1,115 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SIMPLE HASHING * */ +/* * * */ +/* * $Module: HASH * */ +/* * * */ +/* * Copyright (C) 1996, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "hash.h" + +/**************************************************************/ +/* Global Variables */ +/**************************************************************/ + +LIST hash_TABLE[hash__SIZE]; + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +void hash_Init(void) +{ + int i; + + for (i = 0; i < hash__SIZE; i++) + hash_PutList(i, list_Nil()); +} + +void hash_Reset(void) +{ + int i; + LIST Scan; + + for (i = 0; i < hash__SIZE; i++) { + Scan = hash_List(i); + while (!list_Empty(Scan)) { + list_Free(list_Car(Scan)); + Scan = list_Cdr(Scan); + } + list_Delete(hash_List(i)); + hash_PutList(i, list_Nil()); + } +} + +void hash_ResetWithValue(void (*ValueDelete)(POINTER)) +{ + int i; + LIST Scan; + + for (i = 0; i < hash__SIZE; i++) { + Scan = hash_List(i); + while (!list_Empty(Scan)) { + ValueDelete(list_PairSecond(list_Car(Scan))); + list_Free(list_Car(Scan)); + Scan = list_Cdr(Scan); + } + list_Delete(hash_List(i)); + hash_PutList(i, list_Nil()); + } +} + +POINTER hash_Get(POINTER key) +{ + LIST Scan; + + Scan = hash_List(hash_Index(key)); + + while (!list_Empty(Scan)) { + if (list_PairFirst(list_Car(Scan)) == key) + return list_PairSecond(list_Car(Scan)); + Scan = list_Cdr(Scan); + } + + return NULL; +} diff --git a/test/spass/hash.h b/test/spass/hash.h new file mode 100644 index 0000000000000000000000000000000000000000..3556e5dcc005e65210edd85f41f903a5207dfa96 --- /dev/null +++ b/test/spass/hash.h @@ -0,0 +1,107 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SIMPLE HASHING * */ +/* * * */ +/* * $Module: HASH * */ +/* * * */ +/* * Copyright (C) 1996, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _HASH_ +#define _HASH_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "list.h" + + +/**************************************************************/ +/* Structures */ +/**************************************************************/ + +#define hash__SIZE 29 /* a prime */ + +/* Each Entry is a list of pairs <key,value> */ +extern LIST hash_TABLE[hash__SIZE]; + + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +static __inline__ NAT hash_Index(POINTER Key) +{ + return (NAT)Key % hash__SIZE; +} + +static __inline__ LIST hash_List(NAT Index) +{ + return hash_TABLE[Index]; +} + +static __inline__ void hash_PutList(NAT Index, LIST List) +{ + hash_TABLE[Index] = List; +} + +static __inline__ void hash_Put(POINTER Key, POINTER Value) +{ + hash_PutList(hash_Index(Key), list_Cons(list_PairCreate((POINTER)Key, Value), + hash_List(hash_Index(Key)))); +} + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +void hash_Init(void); +void hash_Reset(void); +void hash_ResetWithValue(void (*)(POINTER)); + +POINTER hash_Get(POINTER); + + +#endif + + diff --git a/test/spass/hasharray.c b/test/spass/hasharray.c new file mode 100644 index 0000000000000000000000000000000000000000..9822b71c1075394286a97a9fa27ecf6baac73989 --- /dev/null +++ b/test/spass/hasharray.c @@ -0,0 +1,138 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * HASHING * */ +/* * * */ +/* * $Module: HASHARRAY * */ +/* * * */ +/* * Copyright (C) 1997, 1998, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "hasharray.h" + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +HASH hsh_Create(void) +/************************************************************** + RETURNS: A new, empty hasharray +***************************************************************/ +{ + HASH h; + NAT l; + h = (LIST*) memory_Malloc(sizeof(LIST) * hsh__SIZE); + for (l=0; l < hsh__SIZE; l++) + h[l] = list_Nil(); + return h; +} + +void hsh_Reset(HASH H) +/************************************************************** + INPUT: A hasharray + EFFECT: Deletes all information stored in the array but keeps + the array itself. + Keys and data items are not deleted ! +***************************************************************/ +{ + int i; + LIST Scan, Pair; + for (i = 0; i < hsh__SIZE; i++) { + for (Scan = H[i]; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Pair = list_Car(Scan); + list_Delete(list_PairSecond(Pair)); + list_PairFree(Pair); + } + list_Delete(H[i]); + H[i] = list_Nil(); + } +} + +void hsh_Delete(HASH H) +/************************************************************** + INPUT: A hasharray + EFFECT: Deletes all information stored in the array and + the array itself. + Keys and data items are not deleted ! +***************************************************************/ +{ + hsh_Reset(H); + memory_Free(H, sizeof(LIST) * hsh__SIZE); +} + +LIST hsh_GetAllEntries(HASH H) +/************************************************************** + INPUT: A hasharray + RETURNS: A new list of all data items stored in the hasharray +***************************************************************/ +{ + LIST Scan, Result; + NAT i; + Result = list_Nil(); + for (i = 0; i < hsh__SIZE; i++) { + for (Scan = H[i]; !list_Empty(Scan); Scan = list_Cdr(Scan)) + Result = list_Nconc(Result, list_Copy(list_PairSecond(list_Car(Scan)))); + } + return Result; +} + +void hsh_Check(HASH H) +/************************************************************** + INPUT: A hasharray + EFFECT: Traverses the whole array and the lists to find dangling pointers. +***************************************************************/ +{ + LIST Scan, Scan2, Pair; + NAT i; + unsigned long Key; + for (i = 0; i < hsh__SIZE; i++) { + for (Scan = H[i]; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Pair = list_Car(Scan); + Key = (unsigned long)list_PairFirst(Pair); + for (Scan2 = list_PairSecond(Pair); !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) { + POINTER Value; + char Z; + Value = list_Car(Scan2); + Z = * ((char*) Value); + } + } + } +} diff --git a/test/spass/hasharray.h b/test/spass/hasharray.h new file mode 100644 index 0000000000000000000000000000000000000000..de6e118af2e8411ce08024ffc43262429beef3ec --- /dev/null +++ b/test/spass/hasharray.h @@ -0,0 +1,246 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * HASHING * */ +/* * * */ +/* * $Module: HASHARRAY * */ +/* * * */ +/* * Copyright (C) 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _HASHARRAY_ +#define _HASHARRAY_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "list.h" + +/**************************************************************/ +/* Structures */ +/**************************************************************/ + +#define hsh__SIZE 29 /* a prime */ + +/* Each Entry is a list of pairs <key,list of values> */ + +typedef LIST* HASH; + +void hsh_Check(HASH H); + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +static __inline__ unsigned long hsh_Index(POINTER Key) +/************************************************************** + INPUT: A pointer + RETURNS: A key for the hasharray +***************************************************************/ +{ + return (unsigned long)Key % hsh__SIZE; +} + +static __inline__ void hsh_Put(HASH H, POINTER Key, POINTER Value) +/************************************************************** + INPUT: A hasharray, a pointer used as key and a pointer to a data item + EFFECT: Add Value to the list of data items associated with the key, + if it isn't a member already +***************************************************************/ +{ + LIST Scan, Pair; + unsigned long HashKey; + HashKey = hsh_Index(Key); + for (Scan = H[HashKey]; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Pair = list_Car(Scan); + if (list_PairFirst(Pair) == Key) { + if (!list_PointerMember(list_PairSecond(Pair), Value)) + list_Rplacd(Pair, list_Cons(Value, list_PairSecond(Pair))); +#ifdef CHECK + hsh_Check(H); +#endif + return; + } + } + H[HashKey] = list_Cons(list_PairCreate(Key, list_List(Value)), H[HashKey]); +#ifdef CHECK + hsh_Check(H); +#endif +} + +static __inline__ void hsh_PutList(HASH H, POINTER Key, LIST List) +/************************************************************** + INPUT: A hasharray, a pointer used as key and a list of data items + EFFECT: Add the list to the list of data items associated with the key, + and delete all duplicates. +***************************************************************/ +{ + LIST Scan, Pair; + unsigned long HashKey; + + HashKey = hsh_Index(Key); + for (Scan = H[HashKey]; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Pair = list_Car(Scan); + if (list_PairFirst(Pair) == Key) { + list_Rplacd(Pair, list_Nconc(list_PairSecond(Pair), List)); +#ifdef CHECK + hsh_Check(H); +#endif + return; + } + } + H[HashKey] = list_Cons(list_PairCreate(Key, List), H[HashKey]); +#ifdef CHECK + hsh_Check(H); +#endif +} + +static __inline__ void hsh_PutListWithCompareFunc(HASH H, POINTER Key, + LIST List, + BOOL (*Test)(POINTER, POINTER), + unsigned long (*HashFunc)(POINTER)) +/************************************************************** + INPUT: A hasharray, a pointer used as key, a list of data + items, a test function for key equality and a + hashing function. + EFFECT: Add the list to the list of data items associated + with the key, and delete all duplicates. +***************************************************************/ +{ + LIST Scan, Pair; + unsigned long HashKey; + + HashKey = (unsigned long) HashFunc(Key); + for (Scan = H[HashKey]; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Pair = (LIST) list_Car(Scan); + if (Test(list_PairFirst(Pair), Key)) { + list_Rplacd(Pair, list_Nconc(list_PairSecond(Pair), List)); +#ifdef CHECK + hsh_Check(H); +#endif + return; + } + } + H[HashKey] = list_Cons(list_PairCreate(Key, List), H[HashKey]); +#ifdef CHECK + hsh_Check(H); +#endif +} + +static __inline__ LIST hsh_Get(HASH H, POINTER Key) +/************************************************************** + INPUT: A hasharray and a pointer used as key + RETURNS: The list of data items associated with the key +***************************************************************/ +{ + LIST Scan, Pair; + + for (Scan = H[hsh_Index(Key)]; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Pair = list_Car(Scan); + if (list_PairFirst(Pair) == Key) + return list_PairSecond(Pair); + } + return NULL; +} + +static __inline__ void hsh_DelItem(HASH H, POINTER Key) +/************************************************************** + INPUT: A hasharray and a pointer used as key + RETURNS: The information associated with the key is deleted +***************************************************************/ +{ + LIST Scan, Pair; + unsigned long k; + + k = hsh_Index(Key); + for (Scan = H[k]; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Pair = list_Car(Scan); + if (list_PairFirst(Pair) == Key) { + list_Delete(list_PairSecond(Pair)); + list_PairFree(Pair); + H[k] = list_PointerDeleteElement(H[k], Pair); + return; + } + } +} + +static __inline__ LIST hsh_GetWithCompareFunc(HASH H, POINTER Key, + BOOL (*Test)(POINTER, POINTER), + unsigned long (*HashFunc)(POINTER)) +/************************************************************** + INPUT: A hasharray, a pointer used as key, a compare function + for keys and a hash function for keys. + RETURNS: The list of data items associated with the key +***************************************************************/ +{ + LIST Scan, Pair; + + for (Scan = H[HashFunc(Key)]; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Pair = list_Car(Scan); + if (Test(list_PairFirst(Pair), Key)) + return list_PairSecond(Pair); + } + return NULL; +} + + +static __inline__ unsigned long hsh_StringHashKey(const char* Label) +{ + unsigned long i, s; + s = 0; + for (i = 0; i <= strlen(Label); i++) + s += Label[i]; + s = s % hsh__SIZE; + return s; +} + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +HASH hsh_Create(void); +void hsh_Reset(HASH H); +void hsh_Delete(HASH H); +LIST hsh_GetAllEntries(HASH H); + +#endif + + diff --git a/test/spass/ia.h b/test/spass/ia.h new file mode 100644 index 0000000000000000000000000000000000000000..4cf2fb9cbeeb3e60d41558bcba96c4bf31e2e2e1 --- /dev/null +++ b/test/spass/ia.h @@ -0,0 +1,58 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INTERFACE FOR SPASS INTERACTICE MODE * */ +/* * * */ +/* * $Module: DFG * */ +/* * * */ +/* * Copyright (C) 1997, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _IA_ +#define _IA_ + +#include <stdio.h> +#include "list.h" +#include "flags.h" + +/* Parser functions */ +LIST ia_GetNextRequest(FILE*,FLAGSTORE); /* Returns a pair! */ + +#endif diff --git a/test/spass/iaparser.c b/test/spass/iaparser.c new file mode 100644 index 0000000000000000000000000000000000000000..4fa8697954a6ef20ea365094f830cf02c20cf218 --- /dev/null +++ b/test/spass/iaparser.c @@ -0,0 +1,1773 @@ +/* A Bison parser, made from iaparser.y, by GNU bison 1.75. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* If NAME_PREFIX is specified substitute the variables and functions + names. */ +#define yyparse ia_parse +#define yylex ia_lex +#define yyerror ia_error +#define yylval ia_lval +#define yychar ia_char +#define yydebug ia_debug +#define yynerrs ia_nerrs + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + IA_AND = 258, + IA_EQUAL = 259, + IA_EQUIV = 260, + IA_EXISTS = 261, + IA_FALSE = 262, + IA_FORALL = 263, + IA_IMPLIED = 264, + IA_IMPLIES = 265, + IA_NOT = 266, + IA_OR = 267, + IA_PROVE = 268, + IA_TRUE = 269, + IA_NUM = 270, + IA_ID = 271 + }; +#endif +#define IA_AND 258 +#define IA_EQUAL 259 +#define IA_EQUIV 260 +#define IA_EXISTS 261 +#define IA_FALSE 262 +#define IA_FORALL 263 +#define IA_IMPLIED 264 +#define IA_IMPLIES 265 +#define IA_NOT 266 +#define IA_OR 267 +#define IA_PROVE 268 +#define IA_TRUE 269 +#define IA_NUM 270 +#define IA_ID 271 + + + + +/* Copy the first part of user declarations. */ +#line 48 "iaparser.y" + + +#include "flags.h" +#include "ia.h" +#include "symbol.h" +#include "term.h" +#include "foldfg.h" +#include "clause.h" + +extern NAT dfg_LINENUMBER; /* Defined in dfgparser.y */ +LIST ia_PROOFREQUEST; /* A pair! */ +FLAGSTORE ia_FLAGS; + +void yyerror(const char*); +int yylex(void); /* Defined in iascanner.l */ + +static SYMBOL ia_Symbol(char*, NAT); +static TERM ia_CreateQuantifier(SYMBOL, LIST, TERM); + +static __inline__ void ia_StringFree(char* String) +{ + memory_Free(String, sizeof(char)*(strlen(String)+1)); +} + +static __inline__ TERM ia_TermCreate(char* Name, LIST Arguments) +/* Look up the symbol, check its arity and create the term */ +{ + return term_Create(ia_Symbol(Name,list_Length(Arguments)), Arguments); +} + +/**************************************************************/ +/* Functions to check the arity of symbols */ +/**************************************************************/ + +static void ia_SymCheck(SYMBOL, NAT); + +/**************************************************************/ +/* Functions that handle variable names */ +/**************************************************************/ + +/* List of quantified variables in the current input formula. */ +/* This list is used to find symbols that by mistake weren't */ +/* declared in the symbol declaration section */ +/* --> free variables */ +/* This is a list of lists, since each time a quantifier is */ +/* reached, a new list is added to the global list. */ +static LIST ia_VARLIST; +static BOOL ia_VARDECL; + +static void ia_VarStart(void); +static void ia_VarStop(void); +static void ia_VarBacktrack(void); +static void ia_VarCheck(void); +static SYMBOL ia_VarLookup(char*); + +#define YY_INPUT(buf,result,max_size) \ +{ \ + int c = getc(ia_in); \ + result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \ +} + +#define YYERROR_VERBOSE + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#ifndef YYSTYPE +#line 113 "iaparser.y" +typedef union { + int number; + char* string; + SYMBOL symbol; + TERM term; + LIST list; +} yystype; +/* Line 193 of /opt/gnu//share/bison/yacc.c. */ +#line 187 "iaparser.c" +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +#ifndef YYLTYPE +typedef struct yyltype +{ + int first_line; + int first_column; + int last_line; + int last_column; +} yyltype; +# define YYLTYPE yyltype +# define YYLTYPE_IS_TRIVIAL 1 +#endif + +/* Copy the second part of user declarations. */ + + +/* Line 213 of /opt/gnu//share/bison/yacc.c. */ +#line 208 "iaparser.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAX) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 4 +#define YYLAST 83 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 23 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 16 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 36 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 77 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 271 + +#define YYTRANSLATE(X) \ + ((unsigned)(X) <= YYMAXUTOK ? yytranslate[X] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 17, 19, 2, 2, 18, 2, 20, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 21, 2, 22, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned char yyprhs[] = +{ + 0, 0, 3, 4, 14, 16, 20, 22, 24, 26, + 31, 38, 43, 48, 49, 50, 61, 62, 63, 74, + 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, + 96, 100, 102, 107, 110, 114, 116 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ + 24, 0, -1, -1, 13, 17, 26, 18, 37, 18, + 15, 19, 20, -1, 26, -1, 25, 18, 26, -1, + 34, -1, 14, -1, 7, -1, 11, 17, 26, 19, + -1, 31, 17, 26, 18, 26, 19, -1, 32, 17, + 25, 19, -1, 34, 17, 25, 19, -1, -1, -1, + 33, 17, 21, 27, 35, 28, 22, 18, 26, 19, + -1, -1, -1, 34, 17, 21, 29, 35, 30, 22, + 18, 26, 19, -1, 4, -1, 5, -1, 9, -1, + 10, -1, 3, -1, 12, -1, 6, -1, 8, -1, + 16, -1, 15, -1, 36, -1, 35, 18, 36, -1, + 34, -1, 34, 17, 34, 19, -1, 21, 22, -1, + 21, 38, 22, -1, 34, -1, 38, 18, 34, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned char yyrline[] = +{ + 0, 136, 136, 137, 149, 150, 153, 154, 155, 156, + 158, 160, 162, 164, 165, 164, 170, 171, 170, 179, + 180, 181, 182, 185, 186, 189, 190, 193, 194, 197, + 198, 201, 211, 232, 233, 236, 237 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "IA_AND", "IA_EQUAL", "IA_EQUIV", + "IA_EXISTS", "IA_FALSE", "IA_FORALL", "IA_IMPLIED", "IA_IMPLIES", + "IA_NOT", "IA_OR", "IA_PROVE", "IA_TRUE", "IA_NUM", "IA_ID", "'('", + "','", "')'", "'.'", "'['", "']'", "$accept", "proofrequest", + "termlist", "term", "@1", "@2", "@3", "@4", "binsymbol", "nsymbol", + "quantsymbol", "id", "qtermlist", "qterm", "labellistopt", "labellist", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 40, 44, 41, + 46, 91, 93 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 23, 24, 24, 25, 25, 26, 26, 26, 26, + 26, 26, 26, 27, 28, 26, 29, 30, 26, 31, + 31, 31, 31, 32, 32, 33, 33, 34, 34, 35, + 35, 36, 36, 37, 37, 38, 38 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 0, 9, 1, 3, 1, 1, 1, 4, + 6, 4, 4, 0, 0, 10, 0, 0, 10, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 3, 1, 4, 2, 3, 1, 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 2, 0, 0, 0, 1, 23, 19, 20, 25, 8, + 26, 21, 22, 0, 24, 7, 28, 27, 0, 0, + 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 13, 16, 0, 9, 33, + 35, 0, 0, 0, 0, 11, 0, 0, 12, 0, + 34, 0, 0, 5, 31, 14, 29, 17, 36, 0, + 10, 0, 0, 0, 0, 3, 0, 30, 0, 0, + 32, 0, 0, 0, 0, 15, 18 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yysigned_char yydefgoto[] = +{ + -1, 2, 33, 34, 46, 63, 47, 64, 19, 20, + 21, 22, 55, 56, 31, 41 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -29 +static const yysigned_char yypact[] = +{ + -12, 12, 35, 0, -29, -29, -29, -29, -29, -29, + -29, -29, -29, 19, -29, -29, -29, -29, 20, 22, + 40, 41, 42, 0, 31, 0, 0, 43, 39, 18, + 8, 38, 44, 7, -29, -29, -29, 9, -29, -29, + -29, -5, 46, 0, 0, -29, 16, 16, -29, 16, + -29, 47, 48, -29, 53, 45, -29, 45, -29, 51, + -29, 16, 16, 50, 52, -29, 54, -29, 57, 58, + -29, 0, 0, 59, 60, -29, -29 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yysigned_char yypgoto[] = +{ + -29, -29, 37, -3, -29, -29, -29, -29, -29, -29, + -29, -28, 30, 21, -29, -29 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, parse error. */ +#define YYTABLE_NINF -1 +static const unsigned char yytable[] = +{ + 18, 1, 40, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 49, 15, 16, 17, 50, 54, 54, + 29, 58, 32, 16, 17, 44, 45, 44, 48, 3, + 39, 16, 17, 66, 54, 4, 23, 38, 24, 25, + 52, 53, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 30, 15, 16, 17, 42, 26, 27, 28, + 36, 51, 43, 62, 35, 37, 59, 60, 73, 74, + 61, 65, 68, 70, 69, 71, 72, 57, 75, 76, + 0, 0, 0, 67 +}; + +static const yysigned_char yycheck[] = +{ + 3, 13, 30, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 18, 14, 15, 16, 22, 46, 47, + 23, 49, 25, 15, 16, 18, 19, 18, 19, 17, + 22, 15, 16, 61, 62, 0, 17, 19, 18, 17, + 43, 44, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 21, 14, 15, 16, 18, 17, 17, 17, + 21, 15, 18, 18, 21, 28, 19, 19, 71, 72, + 17, 20, 22, 19, 22, 18, 18, 47, 19, 19, + -1, -1, -1, 62 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 13, 24, 17, 0, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 14, 15, 16, 26, 31, + 32, 33, 34, 17, 18, 17, 17, 17, 17, 26, + 21, 37, 26, 25, 26, 21, 21, 25, 19, 22, + 34, 38, 18, 18, 18, 19, 27, 29, 19, 18, + 22, 15, 26, 26, 34, 35, 36, 35, 34, 19, + 19, 17, 18, 28, 30, 20, 34, 36, 22, 22, + 19, 18, 18, 26, 26, 19, 19 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up"); \ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.first_line = Rhs[1].first_line; \ + Current.first_column = Rhs[1].first_column; \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#define YYLEX yylex () + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +#endif /* !YYDEBUG */ + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*-----------------------------. +| Print this symbol on YYOUT. | +`-----------------------------*/ + +static void +#if defined (__STDC__) || defined (__cplusplus) +yysymprint (FILE* yyout, int yytype, YYSTYPE yyvalue) +#else +yysymprint (yyout, yytype, yyvalue) + FILE* yyout; + int yytype; + YYSTYPE yyvalue; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvalue; + + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyout, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyout, yytoknum[yytype], yyvalue); +# endif + } + else + YYFPRINTF (yyout, "nterm %s (", yytname[yytype]); + + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyout, ")"); +} +#endif /* YYDEBUG. */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +#if defined (__STDC__) || defined (__cplusplus) +yydestruct (int yytype, YYSTYPE yyvalue) +#else +yydestruct (yytype, yyvalue) + int yytype; + YYSTYPE yyvalue; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvalue; + + switch (yytype) + { + default: + break; + } +} + + + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +# define YYPARSE_PARAM_DECL +# else +# define YYPARSE_PARAM_ARG YYPARSE_PARAM +# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +# endif +#else /* !YYPARSE_PARAM */ +# define YYPARSE_PARAM_ARG +# define YYPARSE_PARAM_DECL +#endif /* !YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +# ifdef YYPARSE_PARAM +int yyparse (void *); +# else +int yyparse (void); +# endif +#endif + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of parse errors so far. */ +int yynerrs; + + +int +yyparse (YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yychar1 = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + goto yyoverflowlab; + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with. */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more. */ + + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yychar1 = YYTRANSLATE (yychar); + + /* We have to keep this `#if YYDEBUG', since we use variables + which are defined only if `YYDEBUG' is set. */ + YYDPRINTF ((stderr, "Next token is ")); + YYDSYMPRINT ((stderr, yychar1, yylval)); + YYDPRINTF ((stderr, "\n")); + } + + /* If the proper action on seeing token YYCHAR1 is to reduce or to + detect an error, take that action. */ + yyn += yychar1; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yychar1) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %d (%s), ", + yychar, yytname[yychar1])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables which + are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + int yyi; + + YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", + yyn - 1, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyn]; yyrhs[yyi] >= 0; yyi++) + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + switch (yyn) + { + case 2: +#line 136 "iaparser.y" + { YYABORT; } + break; + + case 3: +#line 137 "iaparser.y" + { + ia_VarCheck(); + ia_PROOFREQUEST = list_PairCreate(yyvsp[-6].term,yyvsp[-4].list); + flag_SetFlagValue(ia_FLAGS,flag_TIMELIMIT,yyvsp[-2].number); + YYACCEPT; + } + break; + + case 4: +#line 149 "iaparser.y" + { yyval.list = list_List(yyvsp[0].term); } + break; + + case 5: +#line 150 "iaparser.y" + { yyval.list = list_Nconc(yyvsp[-2].list, list_List(yyvsp[0].term)); } + break; + + case 6: +#line 153 "iaparser.y" + { yyval.term = ia_TermCreate(yyvsp[0].string, list_Nil()); } + break; + + case 7: +#line 154 "iaparser.y" + { yyval.term = term_Create(fol_True(),list_Nil()); } + break; + + case 8: +#line 155 "iaparser.y" + { yyval.term = term_Create(fol_False(),list_Nil()); } + break; + + case 9: +#line 157 "iaparser.y" + { yyval.term = term_Create(fol_Not(),list_List(yyvsp[-1].term)); } + break; + + case 10: +#line 159 "iaparser.y" + { yyval.term = term_Create(yyvsp[-5].symbol, list_Cons(yyvsp[-3].term, list_List(yyvsp[-1].term))); } + break; + + case 11: +#line 161 "iaparser.y" + { yyval.term = term_Create(yyvsp[-3].symbol, yyvsp[-1].list); } + break; + + case 12: +#line 163 "iaparser.y" + { yyval.term = ia_TermCreate(yyvsp[-3].string, yyvsp[-1].list); } + break; + + case 13: +#line 164 "iaparser.y" + { ia_VarStart(); } + break; + + case 14: +#line 165 "iaparser.y" + { ia_VarStop(); } + break; + + case 15: +#line 167 "iaparser.y" + { ia_VarBacktrack(); + yyval.term = ia_CreateQuantifier(yyvsp[-9].symbol,yyvsp[-5].list,yyvsp[-1].term); + } + break; + + case 16: +#line 170 "iaparser.y" + { ia_VarStart(); } + break; + + case 17: +#line 171 "iaparser.y" + { ia_VarStop(); } + break; + + case 18: +#line 173 "iaparser.y" + { misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: SPASS can't handle the quantifier %s.\n", dfg_LINENUMBER, yyvsp[-9].string); + misc_FinishUserErrorReport(); + } + break; + + case 19: +#line 179 "iaparser.y" + { yyval.symbol = fol_Equality(); } + break; + + case 20: +#line 180 "iaparser.y" + { yyval.symbol = fol_Equiv(); } + break; + + case 21: +#line 181 "iaparser.y" + { yyval.symbol = fol_Implied(); } + break; + + case 22: +#line 182 "iaparser.y" + { yyval.symbol = fol_Implies(); } + break; + + case 23: +#line 185 "iaparser.y" + { yyval.symbol = fol_And(); } + break; + + case 24: +#line 186 "iaparser.y" + { yyval.symbol = fol_Or(); } + break; + + case 25: +#line 189 "iaparser.y" + { yyval.symbol = fol_Exist(); } + break; + + case 26: +#line 190 "iaparser.y" + { yyval.symbol = fol_All(); } + break; + + case 27: +#line 193 "iaparser.y" + { yyval.string = yyvsp[0].string; } + break; + + case 28: +#line 194 "iaparser.y" + { yyval.string = string_IntToString(yyvsp[0].number); } + break; + + case 29: +#line 197 "iaparser.y" + { yyval.list = list_List(yyvsp[0].term); } + break; + + case 30: +#line 198 "iaparser.y" + { yyval.list = list_Nconc(yyvsp[-2].list, list_List(yyvsp[0].term)); } + break; + + case 31: +#line 201 "iaparser.y" + { SYMBOL s = ia_Symbol(yyvsp[0].string,0); + if (!symbol_IsVariable(s)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: %s",dfg_LINENUMBER, + symbol_Name(s)); + misc_UserErrorReport(" is not a variable.\n"); + misc_FinishUserErrorReport(); + } + yyval.term = term_Create(s, list_Nil()); + } + break; + + case 32: +#line 211 "iaparser.y" + { SYMBOL p, v; + p = ia_Symbol(yyvsp[-3].string, 1); + if (!symbol_IsPredicate(p)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: %s",dfg_LINENUMBER, + symbol_Name(p)); + misc_UserErrorReport(" is not a predicate.\n"); + misc_FinishUserErrorReport(); + } + v = ia_Symbol(yyvsp[-1].string, 0); + if (!symbol_IsVariable(v)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: %s",dfg_LINENUMBER, + symbol_Name(v)); + misc_UserErrorReport(" is not a variable.\n"); + misc_FinishUserErrorReport(); + } + yyval.term = term_Create(p, list_List(term_Create(v,list_Nil()))); + } + break; + + case 33: +#line 232 "iaparser.y" + { yyval.list = list_Nil(); } + break; + + case 34: +#line 233 "iaparser.y" + { yyval.list = yyvsp[-1].list; } + break; + + case 35: +#line 236 "iaparser.y" + { yyval.list = list_List(yyvsp[0].string); } + break; + + case 36: +#line 237 "iaparser.y" + { yyval.list = list_Nconc(yyvsp[-2].list, list_List(yyvsp[0].string)); } + break; + + + } + +/* Line 1016 of /opt/gnu//share/bison/yacc.c. */ +#line 1290 "iaparser.c" + + yyvsp -= yylen; + yyssp -= yylen; + + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen (yytname[yytype]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("parse error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror ("parse error"); + } + goto yyerrlab1; + + +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action. | +`----------------------------------------------------*/ +yyerrlab1: + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* Return failure if at end of input. */ + if (yychar == YYEOF) + { + /* Pop the error token. */ + YYPOPSTACK; + /* Pop the rest of the stack. */ + while (yyssp > yyss) + { + YYDPRINTF ((stderr, "Error: popping ")); + YYDSYMPRINT ((stderr, + yystos[*yyssp], + *yyvsp)); + YYDPRINTF ((stderr, "\n")); + yydestruct (yystos[*yyssp], *yyvsp); + YYPOPSTACK; + } + YYABORT; + } + + YYDPRINTF ((stderr, "Discarding token %d (%s).\n", + yychar, yytname[yychar1])); + yydestruct (yychar1, yylval); + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + YYDPRINTF ((stderr, "Error: popping ")); + YYDSYMPRINT ((stderr, + yystos[*yyssp], *yyvsp)); + YYDPRINTF ((stderr, "\n")); + + yydestruct (yystos[yystate], *yyvsp); + yyvsp--; + yystate = *--yyssp; + + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "Error: state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + } + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; + + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 240 "iaparser.y" + + + +void yyerror(const char *s) +{ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %i: %s\n", dfg_LINENUMBER, s); + misc_FinishUserErrorReport(); + +} + +LIST ia_GetNextRequest(FILE* Input, FLAGSTORE Flags) +/************************************************************** + INPUT: An input file containing one proof request from KIV. + RETURNS: The proof request as pair (formula, labellist), + list_Nil(), if EOF was reached. + EFFECT: Reads ONE proof request from the file. + <Input> may also be a UNIX pipe. +***************************************************************/ +{ + extern FILE* ia_in; /* defined in kivscanner */ + + ia_in = Input; + ia_PROOFREQUEST = list_Nil(); + ia_FLAGS = Flags; + ia_parse(); + + return ia_PROOFREQUEST; +} + + +/**************************************************************/ +/* Static Functions */ +/**************************************************************/ + +static SYMBOL ia_Symbol(char* Name, NAT Arity) +/************************************************************** + INPUT: The name of a symbol and the actual arity of the symbol. + RETURNS: The corresponding SYMBOL. + EFFECT: This function checks if the <Name> was declared as + symbol or variable. If not, an error message is printed + to stderr. + The <Name> is deleted. +***************************************************************/ +{ + SYMBOL symbol; + + symbol = symbol_Lookup(Name); + if (symbol != 0) { + ia_StringFree(Name); + ia_SymCheck(symbol, Arity); /* Check the arity */ + } else { + /* Variable */ + if (Arity > 0) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %d: Undefined symbol %s.\n",dfg_LINENUMBER,Name); + misc_FinishUserErrorReport(); + } + symbol = ia_VarLookup(Name); + } + return symbol; +} + + +static TERM ia_CreateQuantifier(SYMBOL Symbol, LIST VarTermList, TERM Term) +/************************************************************** + INPUT: A quantifier symbol, a list possibly containing sorts, + and a term. + RETURNS: The created quantifier term.. +***************************************************************/ +{ + LIST varlist, sortlist, scan; + TERM helpterm; + + /* First collect the variable symbols in varlist and the sorts in sortlist */ + varlist = sortlist = list_Nil(); + for ( ; !list_Empty(VarTermList); VarTermList = list_Pop(VarTermList)) { + helpterm = list_Car(VarTermList); + if (term_IsVariable(helpterm)) { + varlist = list_Nconc(varlist, list_List((POINTER)term_TopSymbol(helpterm))); + term_Delete(helpterm); + } else { + SYMBOL var = term_TopSymbol(term_FirstArgument(helpterm)); + varlist = list_Nconc(varlist, list_List((POINTER)var)); + sortlist = list_Nconc(sortlist, list_List(helpterm)); + } + } + + varlist = list_PointerDeleteDuplicates(varlist); + /* Now create terms from the variables */ + for (scan = varlist; !list_Empty(scan); scan = list_Cdr(scan)) + list_Rplaca(scan, term_Create((SYMBOL)list_Car(scan), list_Nil())); + + if (!list_Empty(sortlist)) { + if (symbol_Equal(fol_All(), Symbol)) { + /* The conjunction of all sortterms implies the Term */ + if (symbol_Equal(fol_Or(), term_TopSymbol(Term))) { + /* Special treatment if <Term> is a term with "or" like */ + /* in clauses: add all sort terms negated to the args */ + /* of the "or" */ + for (scan = sortlist; !list_Empty(scan); scan = list_Cdr(scan)) + /* Negate the sort terms */ + list_Rplaca(scan, term_Create(fol_Not(), list_List(list_Car(scan)))); + sortlist = list_Nconc(sortlist, term_ArgumentList(Term)); + term_RplacArgumentList(Term, sortlist); + } else { + /* No "or" term, so build the implication term */ + if (list_Empty(list_Cdr(sortlist))) { + /* Only one sort term */ + list_Rplacd(sortlist, list_List(Term)); + Term = term_Create(fol_Implies(), sortlist); + } else { + /* More than one sort term */ + helpterm = term_Create(fol_And(), sortlist); + Term = term_Create(fol_Implies(), list_Cons(helpterm, list_List(Term))); + } + } + } else if (symbol_Equal(fol_Exist(), Symbol)) { + /* Quantify the conjunction of all sort terms and <Term> */ + if (symbol_Equal(fol_And(), term_TopSymbol(Term))) { + /* Special treatment if <Term> has an "and" as top symbol: */ + /* just add the sort terms to the args of the "and". */ + sortlist = list_Nconc(sortlist, term_ArgumentList(Term)); + term_RplacArgumentList(Term, sortlist); + } else { + sortlist = list_Nconc(sortlist, list_List(Term)); + Term = term_Create(fol_And(), sortlist); + } + } + } + helpterm = fol_CreateQuantifier(Symbol, varlist, list_List(Term)); + return helpterm; +} + + +/**************************************************************/ +/* Functions for the Symbol Table */ +/**************************************************************/ + +static void ia_SymCheck(SYMBOL Symbol, NAT Arity) +/************************************************************** + INPUT: A symbol and the current arity of this symbol. + RETURNS: Nothing. + EFFECT: This function compares the previous arity of 'Symbol' + with the actual 'Arity'. If these values differ + a warning is printed to stderr and the program exits. +***************************************************************/ +{ + /* Check if the specified arity corresponds with the actual arity */ + if (symbol_Arity(Symbol) != symbol_ArbitraryArity() && + symbol_Arity(Symbol) != Arity) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %u: Symbol %s", dfg_LINENUMBER, symbol_Name(Symbol)); + misc_UserErrorReport(" was declared with arity %u.\n", symbol_Arity(Symbol)); + misc_FinishUserErrorReport(); + } +} + + +/**************************************************************/ +/* Functions for the Variable Table */ +/**************************************************************/ + +typedef struct { + char* name; + SYMBOL symbol; +} IA_VARENTRY, *IA_VAR; + +static __inline__ char* ia_VarName(IA_VAR Entry) +{ + return Entry->name; +} + +static __inline__ SYMBOL ia_VarSymbol(IA_VAR Entry) +{ + return Entry->symbol; +} + +static __inline__ IA_VAR ia_VarCreate(void) +{ + return (IA_VAR) memory_Malloc(sizeof(IA_VARENTRY)); +} + +static void ia_VarFree(IA_VAR Entry) +{ + ia_StringFree(Entry->name); + memory_Free(Entry, sizeof(IA_VARENTRY)); +} + +static void ia_VarStart(void) +{ + ia_VARLIST = list_Push(list_Nil(), ia_VARLIST); + ia_VARDECL = TRUE; +} + +static void ia_VarStop(void) +{ + ia_VARDECL = FALSE; +} + +static void ia_VarBacktrack(void) +{ + list_DeleteWithElement(list_Top(ia_VARLIST), (void (*)(POINTER)) ia_VarFree); + ia_VARLIST = list_Pop(ia_VARLIST); +} + +static void ia_VarCheck(void) +/* Should be called after a complete clause or formula was parsed */ +{ + if (!list_Empty(ia_VARLIST)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In ia_VarCheck: List of variables should be empty!\n"); + misc_FinishErrorReport(); + } + symbol_ResetStandardVarCounter(); +} + +static SYMBOL ia_VarLookup(char* Name) +/************************************************************** + INPUT: A variable name. + RETURNS: The corresponding variable symbol. + EFFECT: If the variable name was quantified before, the + corresponding symbol is returned and the <Name> is freed. + If the variable name was not quantified, and <ia_VARDECL> + is TRUE, a new variable is created, else an error + message is printed and the program exits. +***************************************************************/ +{ + LIST scan, scan2; + SYMBOL symbol; + + symbol = symbol_Null(); + + scan = ia_VARLIST; + scan2 = list_Nil(); + while (!list_Empty(scan) && list_Empty(scan2)) { + scan2 = list_Car(scan); + while (!list_Empty(scan2) && + !string_Equal(ia_VarName(list_Car(scan2)), Name)) + scan2 = list_Cdr(scan2); + scan = list_Cdr(scan); + } + + if (!list_Empty(scan2)) { + /* Found variable */ + ia_StringFree(Name); + symbol = ia_VarSymbol(list_Car(scan2)); + } else { + /* Variable not found */ + if (ia_VARDECL) { + IA_VAR newEntry = ia_VarCreate(); + newEntry->name = Name; + newEntry->symbol = symbol_CreateStandardVariable(); + /* Add <newentry> to the first list in ia_VARLIST */ + list_Rplaca(ia_VARLIST, list_Cons(newEntry,list_Car(ia_VARLIST))); + symbol = ia_VarSymbol(newEntry); + } else { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Line %u: Free Variable %s.\n", dfg_LINENUMBER, Name); + misc_FinishUserErrorReport(); + } + } + return symbol; +} + diff --git a/test/spass/iaparser.h b/test/spass/iaparser.h new file mode 100644 index 0000000000000000000000000000000000000000..32fb09369d1cf32aa8d3a023aacd2988092f8f46 --- /dev/null +++ b/test/spass/iaparser.h @@ -0,0 +1,87 @@ +/* A Bison parser, made from iaparser.y, by GNU bison 1.75. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef BISON_IAPARSER_H +# define BISON_IAPARSER_H + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + IA_AND = 258, + IA_EQUAL = 259, + IA_EQUIV = 260, + IA_EXISTS = 261, + IA_FALSE = 262, + IA_FORALL = 263, + IA_IMPLIED = 264, + IA_IMPLIES = 265, + IA_NOT = 266, + IA_OR = 267, + IA_PROVE = 268, + IA_TRUE = 269, + IA_NUM = 270, + IA_ID = 271 + }; +#endif +#define IA_AND 258 +#define IA_EQUAL 259 +#define IA_EQUIV 260 +#define IA_EXISTS 261 +#define IA_FALSE 262 +#define IA_FORALL 263 +#define IA_IMPLIED 264 +#define IA_IMPLIES 265 +#define IA_NOT 266 +#define IA_OR 267 +#define IA_PROVE 268 +#define IA_TRUE 269 +#define IA_NUM 270 +#define IA_ID 271 + + + + +#ifndef YYSTYPE +#line 113 "iaparser.y" +typedef union { + int number; + char* string; + SYMBOL symbol; + TERM term; + LIST list; +} yystype; +/* Line 1281 of /opt/gnu//share/bison/yacc.c. */ +#line 80 "iaparser.h" +# define YYSTYPE yystype +#endif + +extern YYSTYPE ia_lval; + + +#endif /* not BISON_IAPARSER_H */ + diff --git a/test/spass/iascanner.c b/test/spass/iascanner.c new file mode 100644 index 0000000000000000000000000000000000000000..9677a81efe343cb75a39bdf30381d68ac445eb1e --- /dev/null +++ b/test/spass/iascanner.c @@ -0,0 +1,1991 @@ +#define yy_create_buffer ia__create_buffer +#define yy_delete_buffer ia__delete_buffer +#define yy_scan_buffer ia__scan_buffer +#define yy_scan_string ia__scan_string +#define yy_scan_bytes ia__scan_bytes +#define yy_flex_debug ia__flex_debug +#define yy_init_buffer ia__init_buffer +#define yy_flush_buffer ia__flush_buffer +#define yy_load_buffer_state ia__load_buffer_state +#define yy_switch_to_buffer ia__switch_to_buffer +#define yyin ia_in +#define yyleng ia_leng +#define yylex ia_lex +#define yyout ia_out +#define yyrestart ia_restart +#define yytext ia_text + +#line 19 "iascanner.c" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header$ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include <stdio.h> + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include <stdlib.h> +#include <unistd.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define yywrap() 1 +#define YY_SKIP_YYWRAP +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext +static yyconst short yy_nxt[][24] = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 + }, + + { + 3, 4, 5, 6, 7, 8, 9, 10, 9, 11, + 12, 13, 9, 9, 14, 15, 16, 9, 9, 9, + 17, 9, 9, 9 + }, + + { + 3, 4, 5, 6, 7, 8, 9, 10, 9, 11, + 12, 13, 9, 9, 14, 15, 16, 9, 9, 9, + 17, 9, 9, 9 + }, + + { + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + -3, -3, -3, -3 + }, + + { + 3, -4, -4, -4, -4, -4, -4, -4, -4, -4, + -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, + -4, -4, -4, -4 + }, + + { + 3, -5, 18, -5, -5, -5, -5, -5, -5, -5, + -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, + -5, -5, -5, -5 + }, + + { + 3, -6, -6, -6, -6, -6, -6, -6, -6, -6, + -6, -6, -6, -6, -6, -6, -6, -6, -6, -6, + + -6, -6, -6, -6 + }, + + { + 3, -7, -7, -7, -7, -7, -7, -7, -7, -7, + -7, -7, -7, -7, -7, -7, -7, -7, -7, -7, + -7, -7, -7, -7 + }, + + { + 3, -8, -8, -8, -8, 19, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -9, -9, -9, -9, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + + }, + + { + 3, -10, -10, -10, -10, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -11, -11, -11, -11, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 22, 20, 20, + 20, 20, 20, 23 + }, + + { + 3, -12, -12, -12, -12, 20, 20, 24, 20, 20, + 20, 20, 20, 20, 20, 25, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -13, -13, -13, -13, 20, 20, 20, 20, 20, + + 20, 20, 20, 26, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -14, -14, -14, -14, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 27, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -15, -15, -15, -15, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 28, 20, + 20, 20, 20, 20 + }, + + { + 3, -16, -16, -16, -16, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 29, 20, + + 20, 20, 20, 20 + }, + + { + 3, -17, -17, -17, -17, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 30, 20, + 20, 20, 20, 20 + }, + + { + 3, -18, 18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, -18 + }, + + { + 3, -19, -19, -19, -19, 19, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + + }, + + { + 3, -20, -20, -20, -20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -21, -21, -21, -21, 20, 20, 20, 31, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -22, -22, -22, -22, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 32, 20, 20 + }, + + { + 3, -23, -23, -23, -23, 20, 20, 20, 20, 20, + + 20, 33, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -24, -24, -24, -24, 20, 20, 20, 20, 20, + 20, 20, 34, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -25, -25, -25, -25, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 35, 20, + 20, 20, 20, 20 + }, + + { + 3, -26, -26, -26, -26, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 36, 20, 20, 20, + + 20, 20, 20, 20 + }, + + { + 3, -27, -27, -27, -27, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 37, 20, 20, 20 + }, + + { + 3, -28, -28, -28, -28, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -29, -29, -29, -29, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 38, 20, 20, 20, 20, + 20, 20, 20, 20 + + }, + + { + 3, -30, -30, -30, -30, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 39, 20, 20 + }, + + { + 3, -31, -31, -31, -31, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -32, -32, -32, -32, 20, 20, 40, 20, 20, + 20, 41, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -33, -33, -33, -33, 20, 20, 20, 20, 20, + + 20, 20, 20, 20, 20, 20, 20, 20, 20, 42, + 20, 20, 20, 20 + }, + + { + 3, -34, -34, -34, -34, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 43, + 20, 20, 20, 20 + }, + + { + 3, -35, -35, -35, -35, 20, 20, 44, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -36, -36, -36, -36, 20, 20, 20, 20, 20, + 20, 20, 45, 20, 20, 20, 20, 20, 20, 20, + + 20, 20, 20, 20 + }, + + { + 3, -37, -37, -37, -37, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -38, -38, -38, -38, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 46, 20 + }, + + { + 3, -39, -39, -39, -39, 20, 20, 20, 20, 47, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + + }, + + { + 3, -40, -40, -40, -40, 20, 20, 20, 20, 20, + 20, 20, 48, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -41, -41, -41, -41, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 49, 20 + }, + + { + 3, -42, -42, -42, -42, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 50, 20, 20, 20 + }, + + { + 3, -43, -43, -43, -43, 20, 20, 20, 20, 51, + + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -44, -44, -44, -44, 20, 20, 20, 20, 20, + 20, 20, 52, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -45, -45, -45, -45, 20, 20, 20, 20, 20, + 20, 53, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -46, -46, -46, -46, 20, 20, 20, 20, 54, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + + 20, 20, 20, 20 + }, + + { + 3, -47, -47, -47, -47, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -48, -48, -48, -48, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -49, -49, -49, -49, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + + }, + + { + 3, -50, -50, -50, -50, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 55, + 20, 20, 20, 20 + }, + + { + 3, -51, -51, -51, -51, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -52, -52, -52, -52, 20, 20, 20, 20, 20, + 20, 20, 56, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -53, -53, -53, -53, 20, 20, 20, 20, 57, + + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -54, -54, -54, -54, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -55, -55, -55, -55, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -56, -56, -56, -56, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + + 20, 20, 20, 20 + }, + + { + 3, -57, -57, -57, -57, 20, 20, 20, 58, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 59, + 20, 20, 20, 20 + }, + + { + 3, -58, -58, -58, -58, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + }, + + { + 3, -59, -59, -59, -59, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20 + + }, + + } ; + + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 19 +#define YY_END_OF_BUFFER 20 +static yyconst short int yy_accept[60] = + { 0, + 0, 0, 20, 18, 15, 16, 17, 13, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 15, 13, 14, + 14, 14, 14, 14, 14, 14, 14, 10, 14, 14, + 1, 14, 14, 14, 14, 14, 9, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 11, 2, 3, 14, + 5, 14, 14, 12, 4, 6, 14, 7, 8 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 4, + 4, 1, 1, 4, 4, 4, 1, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 1, 1, 1, + 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 4, 1, 4, 1, 6, 1, 7, 6, 6, 8, + + 9, 10, 6, 6, 11, 6, 6, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 6, 23, + 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "iascanner.l" +#define INITIAL 0 +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SCANNER FOR SPASS INTERACTIVE MODULE * */ +/* * * */ +/* * $Module: KIV * */ +/* * * */ +/* * Copyright (C) 1997, 1998, 1999, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ +/* $RCSfile$ */ +#line 49 "iascanner.l" + +#include <ctype.h> /* for isprint */ +#include <errno.h> +#include "misc.h" +#include "memory.h" +#include "symbol.h" +#include "term.h" +#include "ia.h" +#include "iaparser.h" + +extern NAT dfg_LINENUMBER; /* defined in dfgparser.y */ + +/* Force the scanner to read the input character by character */ +#define YY_ALWAYS_INTERACTIVE 1 +#define YY_NO_UNPUT 1 +#line 803 "iascanner.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 68 "iascanner.l" + + +#line 957 "iascanner.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + while ( (yy_current_state = yy_nxt[yy_current_state][yy_ec[YY_SC_TO_UI(*yy_cp)]]) > 0 ) + ++yy_cp; + + yy_current_state = -yy_current_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +YY_RULE_SETUP +#line 70 "iascanner.l" +return IA_AND; + YY_BREAK +case 2: +YY_RULE_SETUP +#line 71 "iascanner.l" +return IA_EQUAL; + YY_BREAK +case 3: +YY_RULE_SETUP +#line 72 "iascanner.l" +return IA_EQUIV; + YY_BREAK +case 4: +YY_RULE_SETUP +#line 73 "iascanner.l" +return IA_EXISTS; + YY_BREAK +case 5: +YY_RULE_SETUP +#line 74 "iascanner.l" +return IA_FALSE; + YY_BREAK +case 6: +YY_RULE_SETUP +#line 75 "iascanner.l" +return IA_FORALL; + YY_BREAK +case 7: +YY_RULE_SETUP +#line 76 "iascanner.l" +return IA_IMPLIED; + YY_BREAK +case 8: +YY_RULE_SETUP +#line 77 "iascanner.l" +return IA_IMPLIES; + YY_BREAK +case 9: +YY_RULE_SETUP +#line 78 "iascanner.l" +return IA_NOT; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 79 "iascanner.l" +return IA_OR; + YY_BREAK +case 11: +YY_RULE_SETUP +#line 80 "iascanner.l" +return IA_TRUE; + YY_BREAK +case 12: +YY_RULE_SETUP +#line 81 "iascanner.l" +return IA_PROVE; + YY_BREAK +case 13: +YY_RULE_SETUP +#line 82 "iascanner.l" +{ unsigned long n; + errno = 0; + n = strtoul(yytext, NULL, 10); + if (errno != 0 || n > INT_MAX) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Number too big in line %d.\n", + dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + ia_lval.number = (int) n; + return IA_NUM; + } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 94 "iascanner.l" +{ ia_lval.string = (char*) memory_Malloc(yyleng+1); + strcpy(ia_lval.string, yytext); + return IA_ID; + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 98 "iascanner.l" +/* ignore */ + YY_BREAK +case 16: +YY_RULE_SETUP +#line 99 "iascanner.l" +dfg_LINENUMBER++; + YY_BREAK +case 17: +YY_RULE_SETUP +#line 100 "iascanner.l" +return yytext[0]; + YY_BREAK +case 18: +YY_RULE_SETUP +#line 101 "iascanner.l" +{ misc_StartUserErrorReport(); + misc_UserErrorReport("\n Illegal character '"); + if (isprint((int)yytext[0])) + misc_UserErrorReport("%c",yytext[0]); + else + misc_UserErrorReport("\\x%x", (unsigned int) yytext[0]); + misc_UserErrorReport("' in line %d.\n", dfg_LINENUMBER); + misc_FinishUserErrorReport(); + } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 111 "iascanner.l" +ECHO; + YY_BREAK +#line 1130 "iascanner.c" + case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + + yy_current_state = yy_nxt[yy_current_state][1]; + yy_is_jam = (yy_current_state <= 0); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 111 "iascanner.l" + diff --git a/test/spass/kbo.c b/test/spass/kbo.c new file mode 100644 index 0000000000000000000000000000000000000000..c598cbe55564d17fafad01f2bd35bf3cfb7ea5df --- /dev/null +++ b/test/spass/kbo.c @@ -0,0 +1,593 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * EXTENDED KNUTH BENDIX ORDERING * */ +/* * * */ +/* * $Module: KBO * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "kbo.h" +#include "order.h" + +const int kbo_MINWEIGHT = 1; + +/**************************************************************/ +/* Functions to implement an order on terms */ +/**************************************************************/ + +static int kbo_ContCompVarCondAndWeightIntern(CONTEXT Context, TERM Term, int Index) +/************************************************************** + INPUT: + EFFECT: +***************************************************************/ +{ + int Weight; + + Weight = 0; + Term = cont_Deref(&Context,Term); + + if (term_IsStandardVariable(Term)) { + ord_VARCOUNT[term_TopSymbol(Term)][Index]++; + Weight += kbo_MINWEIGHT; + } + else { + LIST Scan; + Weight += symbol_Weight(term_TopSymbol(Term)); + for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) + Weight += kbo_ContCompVarCondAndWeightIntern(Context, list_Car(Scan), Index); + } + + return Weight; +} + +static int kbo_ContCompVarCondAndWeight(CONTEXT Context1, TERM Term1, BOOL *VarCond1, + CONTEXT Context2, TERM Term2, BOOL *VarCond2) +/************************************************************** + INPUT: Two contexts, two terms and two pointers to booleans. + EFFECT: Sets the booleans with respect to the kbo variable condition. + Computes the kbo weight difference. + The terms are interpreted with respect to the bindings in the respective + contexts. +***************************************************************/ +{ + SYMBOL MaxVar1,MaxVar2; + int i,Weight; + + *VarCond1 = *VarCond2 = TRUE; + MaxVar1 = cont_TermMaxVar(Context1,Term1); + MaxVar2 = cont_TermMaxVar(Context2,Term2); + + if (MaxVar1 < MaxVar2) + MaxVar1 = MaxVar2; + + for (i = 0; i <= MaxVar1; i++) { + ord_VARCOUNT[i][0] = 0; + ord_VARCOUNT[i][1] = 0; + } + + Weight = kbo_ContCompVarCondAndWeightIntern(Context1, Term1, 0); + Weight = Weight - kbo_ContCompVarCondAndWeightIntern(Context2, Term2, 1); + + for (i = 0; i <= MaxVar1; i++) { + if (ord_VARCOUNT[i][0] < ord_VARCOUNT[i][1]) { + *VarCond1 = FALSE; + if (!*VarCond2) + return Weight; + } + else if (ord_VARCOUNT[i][0] > ord_VARCOUNT[i][1]) { + *VarCond2 = FALSE; + if (!*VarCond1) + return Weight; + } + } + return Weight; +} + + +static int kbo_CompVarCondAndWeight(TERM Term1, BOOL *VarCond1, TERM Term2, BOOL *VarCond2) +/************************************************************** + INPUT: Two terms and two pointers to booleans. + EFFECT: Sets the booleans with respect to the kbo variable condition. + Computes the kbo weight difference. +***************************************************************/ +{ + SYMBOL MaxVar1,MaxVar2; + TERM Term; + LIST Scan; + int i,Stack,Weight; + + *VarCond1 = *VarCond2 = TRUE; + MaxVar1 = term_MaxVar(Term1); + MaxVar2 = term_MaxVar(Term2); + Stack = stack_Bottom(); + Weight = 0; + + if (MaxVar1 < MaxVar2) + MaxVar1 = MaxVar2; + + for (i = 0; i <= MaxVar1; i++) { + ord_VARCOUNT[i][0] = 0; + ord_VARCOUNT[i][1] = 0; + } + + Term = Term1; + if (term_IsStandardVariable(Term)) { + ord_VARCOUNT[term_TopSymbol(Term)][0]++; + Weight += kbo_MINWEIGHT; + } + else { + Weight += symbol_Weight(term_TopSymbol(Term)); + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + } + while (!stack_Empty(Stack)) { + Scan = stack_Top(); + Term = (TERM)list_Car(Scan); + stack_RplacTop(list_Cdr(Scan)); + if (term_IsStandardVariable(Term)) { + Weight += kbo_MINWEIGHT; + ord_VARCOUNT[term_TopSymbol(Term)][0]++; + } + else { + Weight += symbol_Weight(term_TopSymbol(Term)); + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + } + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + } + + Term = Term2; + if (term_IsStandardVariable(Term)) { + Weight -= kbo_MINWEIGHT; + ord_VARCOUNT[term_TopSymbol(Term)][1]++; + } + else { + Weight -= symbol_Weight(term_TopSymbol(Term)); + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + } + while (!stack_Empty(Stack)) { + Scan = stack_Top(); + Term = (TERM)list_Car(Scan); + stack_RplacTop(list_Cdr(Scan)); + if (term_IsStandardVariable(Term)) { + Weight -= kbo_MINWEIGHT; + ord_VARCOUNT[term_TopSymbol(Term)][1]++; + } + else { + Weight -= symbol_Weight(term_TopSymbol(Term)); + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + } + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + } + + for (i = 0; i <= MaxVar1; i++) { + if (ord_VARCOUNT[i][0] < ord_VARCOUNT[i][1]) { + *VarCond1 = FALSE; + if (!*VarCond2) + return Weight; + } + if (ord_VARCOUNT[i][0] > ord_VARCOUNT[i][1]) { + *VarCond2 = FALSE; + if (!*VarCond1) + return Weight; + } + } + return Weight; +} + + +static ord_RESULT kbo_CompareStruc(TERM Term1, TERM Term2, int WeightDiff) +/************************************************************** + INPUT: Two terms where the kbo-variable condition for <Term1> and + <Term2> is satisfied and <WeightDiff> is the kbo weight difference + between <Term1> and <Term2> + RETURNS: ord_UNCOMPARABLE, if Term1 and Term2 are uncomparable + ord_EQUAL, if Term1 and Term2 are equal + ord_GREATER_THAN, if Term1 is greater than Term2 + CAUTION: The precedence from the order module is used to determine + the precedence of symbols! +***************************************************************/ +{ + LIST Scan1,Scan2; + SYMBOL Top1,Top2; + + Top1 = term_TopSymbol(Term1); + Top2 = term_TopSymbol(Term2); + + if (WeightDiff > 0) + return ord_GREATER_THAN; + else + if (WeightDiff == 0) { + if (symbol_IsStandardVariable(Top1)) { + if (symbol_IsStandardVariable(Top2)) + return ord_EQUAL; + else + return ord_UNCOMPARABLE; + } + else + if (symbol_IsStandardVariable(Top2) || + symbol_PrecedenceGreater(ord_PRECEDENCE, Top1, Top2)) + return ord_GREATER_THAN; + else + if (Top1 == Top2) { + int RecWeightDiff; + BOOL T1VarCond, T2VarCond; + TERM RecTerm1,RecTerm2; + Scan1 = term_ArgumentList(Term1); + Scan2 = term_ArgumentList(Term2); + if (symbol_HasProperty(Top1,ORDRIGHT)) { + int i; + for (i = symbol_Arity(Top1); + i > 0 && term_Equal(list_NthElement(Scan1,i),list_NthElement(Scan2,i)); + i--); + if (i > 0) { + RecTerm1 = (TERM)list_NthElement(Scan1,i); + RecTerm2 = (TERM)list_NthElement(Scan2,i); + } + else + return ord_EQUAL; + } + else { + while (!list_Empty(Scan1) && term_Equal(list_Car(Scan1),list_Car(Scan2))) { + Scan1 = list_Cdr(Scan1); + Scan2 = list_Cdr(Scan2); + } + if (list_Empty(Scan1)) /* Implies that list_Empty(Scan2) */ + return ord_EQUAL; + else { + RecTerm1 = (TERM)list_Car(Scan1); + RecTerm2 = (TERM)list_Car(Scan2); + } + } + RecWeightDiff = kbo_CompVarCondAndWeight(RecTerm1,&T1VarCond,RecTerm2,&T2VarCond); + if (RecWeightDiff >= 0 && T1VarCond) + return kbo_CompareStruc(RecTerm1, RecTerm2, RecWeightDiff); + else + return ord_UNCOMPARABLE; + } + else + return ord_UNCOMPARABLE; + } + else + return ord_UNCOMPARABLE; + + return ord_UNCOMPARABLE; +} + + +ord_RESULT kbo_Compare(TERM Term1, TERM Term2) +/************************************************************** + INPUT: Two terms. + RETURNS: ord_UNCOMPARABLE, if Term1 and Term2 are uncomparable because of + different variables, + ord_EQUAL, if Term1 and Term2 are comparable and have the + same weight, + ord_GREATER_THAN, if Term1 is greater than Term2 wrt the kbo with + the actual precedence and the given symbol weights, + ord_SMALLER_THAN, else. + CAUTION: The precedence from the order module is used to determine + the precedence of symbols! +***************************************************************/ +{ + int WeightDiff; + BOOL T1VarCond, T2VarCond; + ord_RESULT Result; + +#ifdef CHECK + if (!term_IsTerm(Term1) || !term_IsTerm(Term2)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In kbo_Compare:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + + WeightDiff = kbo_CompVarCondAndWeight(Term1,&T1VarCond,Term2,&T2VarCond); + + if (T1VarCond && !T2VarCond) + return kbo_CompareStruc(Term1,Term2,WeightDiff); + + if (!T1VarCond && T2VarCond) + return ord_Not(kbo_CompareStruc(Term2,Term1,-WeightDiff)); + + if (T1VarCond && T2VarCond) { + Result = kbo_CompareStruc(Term1,Term2,WeightDiff); + if (Result == ord_UNCOMPARABLE) + return ord_Not(kbo_CompareStruc(Term2,Term1,-WeightDiff)); + else + return Result; + } + + return ord_UNCOMPARABLE; +} + +static ord_RESULT kbo_ContCompareStruc(CONTEXT Context1, TERM Term1, + CONTEXT Context2, TERM Term2, + int WeightDiff) +/************************************************************** + INPUT: Two contexts and two terms where the kbo-variable condition + for <Term1> and <Term2> is satisfied and <WeightDiff> is the + kbo weight difference between <Term1> and <Term2>. + RETURNS: ord_UNCOMPARABLE, if Term1 and Term2 are uncomparable + ord_EQUAL, if Term1 and Term2 are equal + ord_GREATER_THAN, if Term1 is greater than Term2 + The Terms are interpreted with respect to the contexts. + CAUTION: The precedence from the order module is used to determine + the precedence of symbols! +***************************************************************/ +{ + LIST Scan1,Scan2; + SYMBOL Top1,Top2; + + Term1 = cont_Deref(&Context1,Term1); + Term2 = cont_Deref(&Context2,Term2); + Top1 = term_TopSymbol(Term1); + Top2 = term_TopSymbol(Term2); + + if (WeightDiff > 0) + return ord_GREATER_THAN; + else + if (WeightDiff == 0) { + if (symbol_IsStandardVariable(Top1)) { + if (symbol_IsStandardVariable(Top2)) + return ord_EQUAL; + else + return ord_UNCOMPARABLE; + } + else + if (symbol_IsStandardVariable(Top2) || + symbol_PrecedenceGreater(ord_PRECEDENCE, Top1,Top2)) + return ord_GREATER_THAN; + else + if (Top1 == Top2) { + int RecWeightDiff; + BOOL T1VarCond, T2VarCond; + TERM RecTerm1,RecTerm2; + Scan1 = term_ArgumentList(Term1); + Scan2 = term_ArgumentList(Term2); + if (symbol_HasProperty(Top1,ORDRIGHT)) { + int i; + for (i = symbol_Arity(Top1); + i > 0 && cont_TermEqual(Context1,list_NthElement(Scan1,i), + Context2,list_NthElement(Scan2,i)); + i--); + if (i > 0) { + RecTerm1 = cont_Deref(&Context1,list_NthElement(Scan1,i)); + RecTerm2 = cont_Deref(&Context2,list_NthElement(Scan2,i)); + } + else + return ord_EQUAL; + } + else { + while (!list_Empty(Scan1) && cont_TermEqual(Context1,list_Car(Scan1),Context2,list_Car(Scan2))) { + Scan1 = list_Cdr(Scan1); + Scan2 = list_Cdr(Scan2); + } + if (list_Empty(Scan1)) /* Implies that list_Empty(Scan2) */ + return ord_EQUAL; + else { + RecTerm1 = cont_Deref(&Context1,list_Car(Scan1)); + RecTerm2 = cont_Deref(&Context2,list_Car(Scan2)); + } + } + RecWeightDiff = kbo_ContCompVarCondAndWeight(Context1,RecTerm1,&T1VarCond, + Context2,RecTerm2,&T2VarCond); + if (RecWeightDiff >= 0 && T1VarCond) + return kbo_ContCompareStruc(Context1, RecTerm1, Context2, RecTerm2, RecWeightDiff); + else + return ord_UNCOMPARABLE; + } + else + return ord_UNCOMPARABLE; + } + else + return ord_UNCOMPARABLE; + + return ord_UNCOMPARABLE; +} + + +ord_RESULT kbo_ContCompare(CONTEXT Context1, TERM Term1, CONTEXT Context2, TERM Term2) +/************************************************************** + INPUT: Two contexts and two terms. + RETURNS: ord_UNCOMPARABLE, if Term1 and Term2 are uncomparable because of + different variables, + ord_EQUAL, if Term1 and Term2 are comparable and have the + same weight, + ord_GREATER_THAN, if Term1 is greater than Term2 wrt the kbo with + the actual precedence kbo_Prec and the given + symbol_Weights, + ord_SMALLER_THAN, else. + The Terms are interpreted with respect to the contexts. + CAUTION: The precedence from the order module is used to determine + the precedence of symbols! +***************************************************************/ +{ + int WeightDiff; + BOOL T1VarCond, T2VarCond; + ord_RESULT Result; + +#ifdef CHECK + if (!term_IsTerm(Term1) || !term_IsTerm(Term2)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In kbo_Compare:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + + WeightDiff = kbo_ContCompVarCondAndWeight(Context1, Term1, &T1VarCond, Context2, Term2, &T2VarCond); + + if (T1VarCond && !T2VarCond) + return kbo_ContCompareStruc(Context1,Term1,Context2,Term2,WeightDiff); + + if (!T1VarCond && T2VarCond) + return ord_Not(kbo_ContCompareStruc(Context2,Term2,Context1,Term1,-WeightDiff)); + + if (T1VarCond && T2VarCond) { + Result = kbo_ContCompareStruc(Context1,Term1,Context2,Term2,WeightDiff); + if (Result == ord_UNCOMPARABLE) + return ord_Not(kbo_ContCompareStruc(Context2,Term2,Context1,Term1,-WeightDiff)); + else + return Result; + } + + return ord_UNCOMPARABLE; +} + +static BOOL kbo_ContGreaterCompareStruc(CONTEXT Context1, TERM Term1, + CONTEXT Context2, TERM Term2) +/************************************************************** + INPUT: Two contexts and two terms where the kbo-variable condition + for <Term1> and <Term2> is satisfied as well as the + weight difference between the terms is zero. + RETURNS: TRUE if Term1 is greater than Term2. + The Terms are interpreted with respect to the contexts. + CAUTION: The precedence from the order module is used to determine + the precedence of symbols! +***************************************************************/ +{ + LIST Scan1,Scan2; + SYMBOL Top1,Top2; + + Term1 = cont_Deref(&Context1,Term1); + Term2 = cont_Deref(&Context2,Term2); + Top1 = term_TopSymbol(Term1); + Top2 = term_TopSymbol(Term2); + + if (symbol_IsStandardVariable(Top1)) { + if (symbol_IsStandardVariable(Top2)) + return FALSE; + else + return FALSE; + } + else + if (symbol_IsStandardVariable(Top2) || + symbol_PrecedenceGreater(ord_PRECEDENCE, Top1, Top2)) + return TRUE; + else + if (Top1 == Top2) { + int RecWeightDiff; + BOOL T1VarCond, T2VarCond; + TERM RecTerm1,RecTerm2; + Scan1 = term_ArgumentList(Term1); + Scan2 = term_ArgumentList(Term2); + if (symbol_HasProperty(Top1,ORDRIGHT)) { + int i; + for (i = symbol_Arity(Top1); + i > 0 && cont_TermEqual(Context1,list_NthElement(Scan1,i), + Context2,list_NthElement(Scan2,i)); + i--); + if (i > 0) { + RecTerm1 = cont_Deref(&Context1,list_NthElement(Scan1,i)); + RecTerm2 = cont_Deref(&Context2,list_NthElement(Scan2,i)); + } + else + return FALSE; + } + else { + while (!list_Empty(Scan1) && cont_TermEqual(Context1,list_Car(Scan1),Context2,list_Car(Scan2))) { + Scan1 = list_Cdr(Scan1); + Scan2 = list_Cdr(Scan2); + } + if (list_Empty(Scan1)) /* Implies that list_Empty(Scan2) */ + return FALSE; + else { + RecTerm1 = cont_Deref(&Context1,list_Car(Scan1)); + RecTerm2 = cont_Deref(&Context2,list_Car(Scan2)); + } + } + RecWeightDiff = kbo_ContCompVarCondAndWeight(Context1,RecTerm1,&T1VarCond, + Context2,RecTerm2,&T2VarCond); + + if (T1VarCond) { + if (RecWeightDiff > 0) + return TRUE; + else + if (RecWeightDiff == 0) + return kbo_ContGreaterCompareStruc(Context1, RecTerm1, Context2, RecTerm2); + } + } + + return FALSE; +} + + +BOOL kbo_ContGreater(CONTEXT Context1, TERM Term1, CONTEXT Context2, TERM Term2) +/************************************************************** + INPUT: Two contexts and two terms. + RETURNS: TRUE, if Term1 is greater than Term2 wrt the kbo with + the actual precedence kbo_Prec and the given symbol_Weights + CAUTION: The precedence from the order module is used to determine + the precedence of symbols! +***************************************************************/ +{ + int WeightDiff; + BOOL T1VarCond, T2VarCond; + +#ifdef CHECK + if ((!term_IsTerm(Term1)) || (!term_IsTerm(Term2)) ) { + misc_StartErrorReport(); + misc_ErrorReport("\n In kbo_ContGreater:"); + misc_ErrorReport("\n Illegal input."); + misc_FinishErrorReport(); + } +#endif + + + WeightDiff = kbo_ContCompVarCondAndWeight(Context1, Term1, &T1VarCond, Context2, Term2, &T2VarCond); + + if (T1VarCond) { + if (WeightDiff > 0) + return TRUE; + else + if (WeightDiff == 0) + return kbo_ContGreaterCompareStruc(Context1,Term1,Context2,Term2); + } + return FALSE; +} diff --git a/test/spass/kbo.h b/test/spass/kbo.h new file mode 100644 index 0000000000000000000000000000000000000000..00db284e8b9cca7478b1fba29fff7d3c3b8bc295 --- /dev/null +++ b/test/spass/kbo.h @@ -0,0 +1,67 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * EXTENDED KNUTH BENDIX ORDERING * */ +/* * * */ +/* * $Module: KBO * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _KBO_ +#define _KBO_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "term.h" +#include "context.h" +#include "foldfg.h" +#include "order.h" + +/**************************************************************/ +/* FUNCTIONS */ +/**************************************************************/ + +ord_RESULT kbo_Compare(TERM, TERM); +ord_RESULT kbo_ContCompare(CONTEXT, TERM, CONTEXT, TERM); +BOOL kbo_ContGreater(CONTEXT, TERM, CONTEXT, TERM); + +#endif diff --git a/test/spass/list.c b/test/spass/list.c new file mode 100644 index 0000000000000000000000000000000000000000..c956e1e1b7424de826781c8a0ef79cd746cb3fc5 --- /dev/null +++ b/test/spass/list.c @@ -0,0 +1,1660 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * LISTS * */ +/* * * */ +/* * $Module: LIST * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "list.h" + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * MEMORY MANAGEMENT * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +LIST list_Copy(const LIST List) +/************************************************************** + INPUT: A List. + RETURNS: The copy of the list. + CAUTION: The entries of the list are NOT copied ! + the function needs time O(n), where <n> is the length + of the list. +***************************************************************/ +{ + LIST Copy; + LIST Scan1,Scan2; + + + if (list_Empty(List)) + return list_Nil(); + + Copy = list_List(list_Car(List)); + Scan1 = Copy; + Scan2 = list_Cdr(List); + + while (!list_Empty(Scan2)) { + list_Rplacd(Scan1, list_List(list_Car(Scan2))); + Scan1 = list_Cdr(Scan1); + Scan2 = list_Cdr(Scan2); + } + return Copy; +} + + +LIST list_CopyWithElement(const LIST List, POINTER (*CopyElement)(POINTER)) +/************************************************************** + INPUT: A List and a copy function for the elements. + RETURNS: The copy of the list. + CAUTION: The entries of the list are NOT copied ! + The function needs time O(n*c), where <n> is the length + of the list and <c> is the time for a call of the + element copy function. +***************************************************************/ +{ + LIST Copy; + LIST Scan1,Scan2; + + if (list_Empty(List)) + return list_Nil(); + + Copy = list_List(CopyElement(list_Car(List))); + Scan1 = Copy; + Scan2 = list_Cdr(List); + + while (!list_Empty(Scan2)) { + list_Rplacd(Scan1, list_List(CopyElement(list_Car(Scan2)))); + Scan1 = list_Cdr(Scan1); + Scan2 = list_Cdr(Scan2); + } + return Copy; +} + + +void list_InsertNext(LIST List, POINTER Pointer) +/************************************************************** + INPUT: A list and a pointer to anything. + RETURNS: A list with Pointer being added at the position that + follows List. + SUMMARY: We enqueue the element at position list_Cdr(List); + The function needs time O(1). +***************************************************************/ +{ +#ifdef CHECK + if (Pointer == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In list_InsertNext: NULL Pointer. "); + misc_FinishErrorReport(); + } +#endif + + list_Rplacd(List, list_Cons(Pointer, list_Cdr(List))); +} + + +void list_NMapCar(LIST List, POINTER (*ElementFunc)(POINTER)) +/************************************************************** + INPUT: A List and a function for the elements. + RETURNS: The List where all elements are replaced by the result of + the function calls of <ElementFunc> to the elements + CAUTION: The List is not copied ! + The function needs time O(n*f), where <n> is the length + of the list and <f> is the time for a call of the + element function. +***************************************************************/ +{ + LIST Scan; + + for (Scan = List; !list_Empty(Scan); Scan = list_Cdr(Scan)) + list_Rplaca(Scan, ElementFunc(list_Car(Scan))); +} + + +void list_Apply(void (*Function)(POINTER), LIST List) +/************************************************************** + INPUT: A non-resulting function and a list. + SUMMARY: Apply the function to all members of the list. + The function needs time O(n*f), where <n> is the length + of the list and <f> is the time for a call of the + element function. +***************************************************************/ +{ + while (!list_Empty(List)) { + Function(list_Car(List)); + List = list_Cdr(List); + } +} + + +LIST list_Reverse(const LIST List) +/************************************************************** + INPUT: A list. + RETURNS: A new list where the order of the elements is reversed. + EFFECT: The function needs time O(n), where <n> is the length + of the list. +***************************************************************/ +{ + LIST ReverseList; + LIST Scan; + + ReverseList = list_Nil(); + + for (Scan=List;!list_Empty(Scan);Scan=list_Cdr(Scan)) + ReverseList = list_Cons(list_Car(Scan), ReverseList); + + return ReverseList; +} + + +LIST list_NReverse(LIST List) +/************************************************************** + INPUT: A list + RETURNS: The same list with reversed order of items. + CAUTION: Destructive. + The function needs time O(n), where <n> is the length + of the list. +***************************************************************/ +{ + LIST ReverseList; + LIST Scan1; + LIST Scan2; + + ReverseList = list_Nil(); + + for (Scan1=List; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) + ReverseList = list_Cons(list_Car(Scan1),ReverseList); + + for (Scan1=List, Scan2=ReverseList; + !list_Empty(Scan1); + Scan1=list_Cdr(Scan1), Scan2=list_Cdr(Scan2)) + list_Rplaca(Scan1, list_Car(Scan2)); + + list_Delete(ReverseList); + return List; +} + + +static __inline__ BOOL list_PointerLower (POINTER A, POINTER B) +{ + return (NAT) A < (NAT) B; +} + +LIST list_PointerSort(LIST List) +/************************************************************** + INPUT: A list + RETURNS: The same list where the elements are sorted as pointers. + EFFECT: The function needs time O(n log n), where <n> is the length + of the list. + CAUTION: Destructive. +***************************************************************/ +{ + return list_Sort(List, list_PointerLower); +} + + +BOOL list_SortedInOrder(LIST L, BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: A list, and an ordering function. + RETURNS: TRUE, if the list is ordered with respect to the + ordering function, FALSE otherwise. + EFFECT: The function needs time O(n), where <n> is the + length of the list. +***************************************************************/ +{ + LIST Scan1, Scan2; + + if (!(list_Empty(L) || list_Empty(list_Cdr(L)))) { + Scan1 = L; + Scan2 = list_Cdr(Scan1); + + /* Scan the list. */ + do { + /* If all elements are ordered, then every element */ + /* is <= its successor with respect to the ordering */ + /* function. */ + /* We might have a strictly ordering Test function, */ + /* which implements < instead of <=, so let's test */ + /* for equality first. */ + if (!Test(list_Car(Scan1), list_Car(Scan2)) && + Test(list_Car(Scan2), list_Car(Scan1))) + /* It is really strictly greater, so return FALSE. */ + return FALSE; + + Scan1 = list_Cdr(Scan1); + Scan2 = list_Cdr(Scan1); + } while (!list_Empty(Scan2)); + } + + return TRUE; +} + + +LIST list_Merge(LIST List1, LIST List2, BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: Two sorted lists List1 and List2, and an ordering function. + RETURNS: The merged list ordered with respect to the ordering function. + EFFECT: The function needs time O(n), where <n> is the length of the list. +***************************************************************/ +{ + + LIST Scan1, Scan2, Result, ResultStart; + +#ifdef CHECK + if (!list_SortedInOrder(List1, Test)) { + /* print an error message and exit */ + misc_StartErrorReport(); + misc_ErrorReport("\n In list_Merge: First argument is not sorted."); + misc_FinishErrorReport(); + } + else if (!list_SortedInOrder (List2, Test)) { + /* print an error message and exit */ + misc_StartErrorReport(); + misc_ErrorReport("\n In list_Merge: Second argument is not sorted."); + misc_FinishErrorReport(); + } +#endif + + if (list_Empty(List1)) + return List2; + + if (list_Empty(List2)) + return List1; + + /* This version is derived from list_NNumberMerge, but it doesn't need */ + /* to allocate and deallocate memory, so it should be more efficient. */ + + /* Use the list with the least element as result list. */ + if (Test(list_Car(List1), list_Car(List2))) { + ResultStart = List1; + Scan1 = list_Cdr(List1); + Scan2 = List2; + } + else { + ResultStart = List2; + Scan1 = List1; + Scan2 = list_Cdr(List2); + } + + /* Result is the last element of the merged list. */ + + Result = ResultStart; + + while (!list_Empty(Scan1) && !list_Empty(Scan2)) { + /* This function doesn't implement stable merging. */ + /* Add another test if you need it. */ + + if (Test(list_Car(Scan1), list_Car(Scan2))) { + list_Rplacd(Result,Scan1); + Scan1 = list_Cdr(Scan1); + } + else { + list_Rplacd(Result,Scan2); + Scan2 = list_Cdr(Scan2); + } + Result = list_Cdr(Result); + } + + if (list_Empty(Scan1)) + list_Rplacd(Result, Scan2); + else + list_Rplacd(Result, Scan1); + + return ResultStart; +} + + +void list_Split(LIST L, LIST *Half1, LIST *Half2) +/************************************************************** + INPUT: A list, and two pointers to lists. + RETURNS: Nothing. + EFFECT: The input list is split in two. <Half1> and + <Half2> point to the resulting halves. + The input list is destructively changed! + If the list length is odd, <Half2> is assigned the + bigger part. + The function needs time O(n), where <n> is the + length of the input list. +***************************************************************/ +{ + /* Adapted code from proofcheck ... MergeSort. */ + + LIST SingleStep, DoubleStep, Prev; + + if (list_Empty(L) || list_Empty(list_Cdr(L))) { + *Half1 = list_Nil(); + *Half2 = L; + } + else { + /* divide list in two halves */ + Prev = L; + SingleStep = list_Cdr(L); + DoubleStep = list_Cdr(SingleStep); + + while (!list_Empty(DoubleStep) && !list_Empty(list_Cdr(DoubleStep))) { + Prev = SingleStep; + SingleStep = list_Cdr(SingleStep); + DoubleStep = list_Cdr(list_Cdr(DoubleStep)); + } + + *Half1 = L; + *Half2 = SingleStep; + list_Rplacd(Prev, list_Nil()); + } +} + + +LIST list_MergeSort (LIST L, BOOL (*Test) (POINTER, POINTER)) +/************************************************************** + INPUT: A list, and an ordering function. + RETURNS: The list sorted with respect to the ordering function. + EFFECT: The function needs time O((n log n) * t), where + <n> is the length of the input list and <t> is the + execution time of the ordering function. +***************************************************************/ +{ + LIST Result; +#ifdef CHECK + NAT originallength; + + originallength = list_Length(L); +#endif + + /* Only sort if list has more than one element */ + if (!list_Empty(L) && !list_Empty(list_Cdr(L))) { + LIST lowerhalf; + LIST greaterhalf; + + LIST *lowerhalfptr; + LIST *greaterhalfptr; + + lowerhalfptr = &lowerhalf; + greaterhalfptr = &greaterhalf; + + list_Split(L, lowerhalfptr, greaterhalfptr); + +#ifdef CHECK + if((list_Length(lowerhalf) + list_Length(greaterhalf)) + != originallength) { + /* output an error message and exit */ + misc_StartErrorReport(); + misc_ErrorReport("\n In list_MergeSort: Split lists' total sizes"); + misc_ErrorReport("\n don't match original list's size."); + misc_FinishErrorReport(); + } +#endif + + lowerhalf = list_MergeSort(lowerhalf, Test); + + greaterhalf = list_MergeSort(greaterhalf, Test); + +#ifdef CHECK + if((list_Length(lowerhalf) + list_Length(greaterhalf)) + != originallength) { + /* output an error message and exit */ + misc_StartErrorReport(); + misc_ErrorReport("\n In list_MergeSort: Mergesorted lists' total sizes"); + misc_ErrorReport("\n don't match original list's size."); + misc_FinishErrorReport(); + } +#endif + + Result = list_Merge(lowerhalf, greaterhalf, Test); + +#ifdef CHECK + if(list_Length(Result) != originallength) { + /* output an error message and exit */ + misc_StartErrorReport(); + misc_ErrorReport("\n In list_MergeSort: Merged list's size doesn't match "); + misc_ErrorReport("\n original list's size."); + misc_FinishErrorReport(); + } +#endif + + } + else { + Result = L; + } + + return Result; +} + + +LIST list_InsertionSort(LIST List, BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: A list and a 'less' function on the elements. + RETURNS: The same list where the elements are sorted with + respect to Test. + EFFECT: The function needs time O(n^2*t), where <n> is the + length of the list and <t> is the time for the test + function. + CAUTION: Destructive. +***************************************************************/ +{ + LIST Scan1,Scan2,Min; + POINTER Exchange; + + for (Scan1=List; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { + Min = Scan1; + for (Scan2 = list_Cdr(Scan1); !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) + if (Test(list_Car(Scan2), list_Car(Min))) { + Exchange = list_Car(Min); + list_Rplaca(Min, list_Car(Scan2)); + list_Rplaca(Scan2, Exchange); + } + } + + return List; +} + + +LIST list_Sort(LIST List, BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: A list and a 'less' function on the elements. + RETURNS: The same list where the elements are sorted with + respect to Test. + EFFECT: The function needs time O((n log n) *t), where <n> + is the length of the list and <t> is the time for + the test function. + CAUTION: Destructive. +***************************************************************/ +{ + LIST Result; + +#ifdef CHECK + NAT originallength; + + originallength = list_Length(List); +#endif + + Result = list_MergeSort(List, Test); + +#ifdef CHECK + if (!list_SortedInOrder(Result, Test)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In list_Sort: list_MergeSort did not sort properly."); + misc_FinishErrorReport(); + } + if (list_Length(Result) != originallength) { + misc_StartErrorReport(); + misc_ErrorReport("\n In list_Sort: list_MergeSort lost elements. "); + misc_FinishErrorReport(); + } +#endif + + return Result; +} + + +/* Help Variable used to store a pointer to the numbering function to use + in element comparisons. +*/ +static NAT (*NumberFunction)(POINTER) = NULL; + +static __inline__ BOOL list_PointerNumberedLower(POINTER A, POINTER B) +{ + return (BOOL) (NumberFunction(A) < NumberFunction(B)); +} + +static __inline__ BOOL list_PointerNumberedLowerOrEqual(POINTER A, POINTER B) +{ + return (BOOL) (NumberFunction(A) <= NumberFunction(B)); +} + +static __inline__ BOOL list_PointerNumberedGreater(POINTER A, POINTER B) +{ + return (BOOL) (NumberFunction(A) > NumberFunction(B)); +} + +LIST list_NumberSort(LIST List, NAT (*Number)(POINTER)) +/************************************************************** + INPUT: A list and function mapping elements to numbers. + RETURNS: The same list where the elements are sorted with + respect to < and the Number function. + EFFECT: The function needs time O((n log n) * f), where <n> + is the length of the list and <f> is the time for a + call of the <Number> function. + CAUTION: Destructive. +***************************************************************/ +{ + /* Use number function as temporary variable. It is used as + an implicit parameter in list_PointerLower. + We can't make it an explicit parameter, because of the + prototype of list_Sort. + */ + + NumberFunction = Number; + + return list_Sort(List, list_PointerNumberedLower); + +} + + +LIST list_GreaterNumberSort(LIST List, NAT (*Number)(POINTER)) +/************************************************************** + INPUT: A list and function mapping elements to numbers. + RETURNS: The same list where the elements are sorted with + respect to > and the Number function. + EFFECT: The function needs time O((n log n) * f), where <n> + is the length of the list and <f> is the time for a + call of the <Number> function. + CAUTION: Destructive. +***************************************************************/ +{ + /* Use number function as temporary variable. It is used as + an implicit parameter in list_PointerLower. + We can't make it an explicit parameter, because of the + prototype of list_Sort. + */ + + NumberFunction = Number; + + return list_Sort(List, list_PointerNumberedGreater); +} + + +LIST list_NNumberMerge(LIST List1, LIST List2, NAT (*Number)(POINTER)) +/************************************************************** + INPUT: Two sorted lists and function mapping elements to + numbers. + RETURNS: The merge of the lists where the elements are sorted + with respect to < and the Number function. + CAUTION: Destructive on both lists. +***************************************************************/ +{ + NumberFunction = Number; + + return list_Merge(List1, List2, list_PointerNumberedLowerOrEqual); +} + + +POINTER list_DequeueNext(LIST List) +/************************************************************** + INPUT: A list + RETURNS: A pointer to a dequeued element. + SUMMARY: We dequeue the element pointed to by list_Cdr(List). + The function needs time O(1). +***************************************************************/ +{ + POINTER Pointer; + LIST Memo; + + if (list_Empty(List)) + return NULL; + + Memo = list_Cdr(List); + if (list_Empty(Memo)) + return NULL; + + Pointer = list_Car(Memo); + list_Rplacd(List, Memo->cdr); + list_Free(Memo); + return Pointer; +} + + +POINTER list_NthElement(LIST List, NAT Number) +/************************************************************** + INPUT: A List and a natural number. + RETURNS: The <Number>th element of the list, NULL otherwise. + EFFECT: The function needs time O(Number). +***************************************************************/ +{ + while (!list_Empty(List) && --Number > 0) + List = list_Cdr(List); + + if (list_Empty(List)) + return NULL; + else + return list_Car(List); +} + + +void list_DeleteWithElement(LIST List, void (*ElementDelete)(POINTER)) +/************************************************************** + INPUT: A list and a delete function for the elements. + RETURNS: Nothing. + EFFECT: The list and all its elements are deleted. + The function needs time O(n*d), where <n> is the length + of the list and <d> is the time for the delete function. +***************************************************************/ +{ + LIST Scan; + + while (!list_Empty(List)) { + Scan = list_Cdr(List); + ElementDelete(list_Car(List)); + list_Free(List); + List = Scan; + } +} + + +NAT list_DeleteWithElementCount(LIST List, void (*ElementDelete)(POINTER)) +/************************************************************** + INPUT: A List and a delete function for the elements. + RETURNS: The number of deleted elements. + EFFECT: The List and all its elements are deleted. + The function needs time O(n*d), where <n> is the length + of the list and <d> is the time for the delete function. +***************************************************************/ +{ + int Result; + LIST Scan; + + Result = 0; + + while (!list_Empty(List)) { + Scan = list_Cdr(List); + ElementDelete(list_Car(List)); + list_Free(List); + List = Scan; + Result++; + } + + return Result; +} + + +LIST list_DeleteElement(LIST List, POINTER Element, BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: A list, an element pointer, an equality test for + elements + RETURNS: The list where Element is deleted from List with + respect to Test. + EFFECTS: If List contains Element with respect to EqualityTest, + Element is deleted from List + CAUTION: Destructive. Be careful, the first element of a + list cannot be changed destructively by call by + reference. +***************************************************************/ +{ + LIST Scan1,Scan2; + + while (!list_Empty(List) && Test(Element, list_Car(List))) { + Scan1 = list_Cdr(List); + list_Free(List); + List = Scan1; + } + + if (list_Empty(List)) + return list_Nil(); + + Scan2 = List; + Scan1 = list_Cdr(List); + + while (!list_Empty(Scan1)) { + if (Test(Element, list_Car(Scan1))) { + list_Rplacd(Scan2, list_Cdr(Scan1)); + list_Free(Scan1); + Scan1 = list_Cdr(Scan2); + } + else { + Scan2 = Scan1; + Scan1 = list_Cdr(Scan1); + } + } + return List; +} + + +LIST list_DeleteElementIf(LIST List, BOOL (*Test)(POINTER)) +/************************************************************** + INPUT: A list and a test for elements. + RETURNS: The list where an element is deleted if <Test> on it + succeeds. + CAUTION: Destructive. Be careful, the first element of a list + cannot be changed destructively by call by + reference. +***************************************************************/ +{ + LIST Scan1,Scan2; + + while (!list_Empty(List) && Test(list_Car(List))) { + Scan1 = list_Cdr(List); + list_Free(List); + List = Scan1; + } + + if (list_Empty(List)) + return list_Nil(); + + Scan2 = List; + Scan1 = list_Cdr(List); + + while (!list_Empty(Scan1)) { + if (Test(list_Car(Scan1))) { + list_Rplacd(Scan2, list_Cdr(Scan1)); + list_Free(Scan1); + Scan1 = list_Cdr(Scan2); + } + else { + Scan2 = Scan1; + Scan1 = list_Cdr(Scan1); + } + } + return List; +} + + +LIST list_DeleteElementIfFree(LIST List, BOOL (*Test)(POINTER), + void (*Delete)(POINTER)) +/************************************************************** + INPUT: A list, a test for elements and a delete function + for elements. + RETURNS: The list where an element is deleted if <Test> on it + succeeds. + The element is deleted with <Delete>. + CAUTION: Destructive. Be careful, the first element of a list + cannot be changed destructively by call by reference. +***************************************************************/ +{ + LIST Scan1,Scan2; + + while (!list_Empty(List) && Test(list_Car(List))) { + Scan1 = list_Cdr(List); + Delete(list_Car(List)); + list_Free(List); + List = Scan1; + } + + if (list_Empty(List)) + return list_Nil(); + + Scan2 = List; + Scan1 = list_Cdr(List); + + while (!list_Empty(Scan1)) { + if (Test(list_Car(Scan1))) { + Delete(list_Car(Scan1)); + list_Rplacd(Scan2, list_Cdr(Scan1)); + list_Free(Scan1); + Scan1 = list_Cdr(Scan2); + } + else { + Scan2 = Scan1; + Scan1 = list_Cdr(Scan1); + } + } + return List; +} + + + +LIST list_DeleteElementFree(LIST List, POINTER Element, + BOOL (*Test)(POINTER, POINTER), + void (*Free)(POINTER)) +/************************************************************** + INPUT: A list, an element pointer, an equality test for + elements and a free function for elements. + RETURNS: The list where Element is deleted from List with + respect to Test. + EFFECTS: If the list contains <Element> with respect to <Test>, + <Element> is deleted from the list and freed. + CAUTION: Destructive. Be careful, the first element of a list + cannot be changed destructively by call by reference. +***************************************************************/ +{ + LIST Scan1,Scan2; + + while (!list_Empty(List) && Test(Element, list_Car(List))) { + Scan1 = list_Cdr(List); + Free(list_Car(List)); + list_Free(List); + List = Scan1; + } + + if (list_Empty(List)) + return list_Nil(); + + Scan2 = List; + Scan1 = list_Cdr(List); + + while (!list_Empty(Scan1)) { + if (Test(Element, list_Car(Scan1))) { + list_Rplacd(Scan2, list_Cdr(Scan1)); + Free(list_Car(Scan1)); + list_Free(Scan1); + Scan1 = list_Cdr(Scan2); + } + else { + Scan2 = Scan1; + Scan1 = list_Cdr(Scan1); + } + } + return List; +} + + +LIST list_DeleteOneElement(LIST List, POINTER Element, BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: A list, an element pointer and an equality test for + elements. + RETURNS: The list where at most one element was deleted from + <List> if the Test between <Element> and the element + succeeds. + EFFECT: The function needs time O(n*t) in the worst case, and + time O(t) in the best case, where <n> is the length of + the list and t is the time for a call of the test function. + CAUTION: Destructive. Be careful, the first element of a list + cannot be changed destructively by call by + reference. + The memory of the deleted element is not freed. +***************************************************************/ +{ + LIST scan1, scan2; + + if (list_Empty(List)) + return List; + else { + if (Test(Element, list_Car(List))) + return list_Pop(List); + } + + for (scan2 = List, scan1 = list_Cdr(List); !list_Empty(scan1); + scan2 = scan1, scan1 = list_Cdr(scan1)) { + if (Test(Element, list_Car(scan1))) { + list_Rplacd(scan2, list_Cdr(scan1)); + list_Free(scan1); + scan1 = list_Cdr(scan2); + return List; + } + } + return List; +} + + +LIST list_PointerDeleteElement(LIST List, POINTER Element) +/************************************************************** + INPUT: A list and an element pointer + RETURNS: The list where Element is deleted from List with respect to + pointer equality. + EFFECTS: If <List> contains <Element> with respect to pointer equality, + <Element> is deleted from <List>. + This function needs time O(n), where <n> is the length of the list. + CAUTION: Destructive. Be careful, the first element of a list cannot + be changed destructively by call by reference. +***************************************************************/ +{ + LIST Scan1,Scan2; + + while (!list_Empty(List) && Element == list_Car(List)) { + Scan1 = list_Cdr(List); + list_Free(List); + List = Scan1; + } + + if (list_Empty(List)) + return list_Nil(); + + Scan2 = List; + Scan1 = list_Cdr(List); + + while (!list_Empty(Scan1)) { + if (Element == list_Car(Scan1)) { + list_Rplacd(Scan2, list_Cdr(Scan1)); + list_Free(Scan1); + Scan1 = list_Cdr(Scan2); + } + else { + Scan2 = Scan1; + Scan1 = list_Cdr(Scan1); + } + } + return List; +} + +LIST list_PointerDeleteElementFree(LIST List, POINTER Element, + void (*Free)(POINTER)) +/************************************************************** + INPUT: A list, an element pointer and a free function for + elements. + RETURNS: The list where Element is deleted from List with + respect to pointer equality and freed. + EFFECTS: If List contains Element with respect to pointer + equality, Element is deleted from List + CAUTION: Destructive. Be careful, the first element of a list + cannot be changed destructively by call by + reference. +***************************************************************/ +{ + LIST Scan1,Scan2; + + while (!list_Empty(List) && Element == list_Car(List)) { + Scan1 = list_Cdr(List); + Free(list_Car(List)); + list_Free(List); + List = Scan1; + } + + if (list_Empty(List)) + return list_Nil(); + + Scan2 = List; + Scan1 = list_Cdr(List); + + while (!list_Empty(Scan1)) { + if (Element == list_Car(Scan1)) { + list_Rplacd(Scan2, list_Cdr(Scan1)); + Free(list_Car(Scan1)); + list_Free(Scan1); + Scan1 = list_Cdr(Scan2); + } + else { + Scan2 = Scan1; + Scan1 = list_Cdr(Scan1); + } + } + return List; +} + + +LIST list_PointerDeleteOneElement(LIST List, POINTER Element) +/************************************************************** + INPUT: A list and an element pointer. + RETURNS: The list where one occurrence of Element is deleted from List + with respect to pointer equality. + EFFECTS: If List contains Element with respect to pointer equality, + Element is deleted from List. + CAUTION: Destructive. Be careful, the first element of a list cannot + be changed destructively by call by reference. +***************************************************************/ +{ + LIST Scan1,Scan2; + + if (list_Empty(List)) + return List; + else { + if (Element == list_Car(List)) + return list_Pop(List); + } + + Scan2 = List; + Scan1 = list_Cdr(List); + + while (!list_Empty(Scan1)) { + if (Element == list_Car(Scan1)) { + list_Rplacd(Scan2, list_Cdr(Scan1)); + list_Free(Scan1); + Scan1 = list_Cdr(Scan2); + return List; + } + else { + Scan2 = Scan1; + Scan1 = list_Cdr(Scan1); + } + } + return List; +} + + +BOOL list_DeleteFromList(LIST* List, POINTER Element) +/************************************************************** + INPUT: A list and an element pointer + RETURNS: TRUE, if Element was deleted; FALSE, otherwise. + EFFECTS: If List contains Element with respect to pointer equality, + all occurrences of Element are deleted from List. + CAUTION: Destructive. Be careful, the first element of a list cannot + be changed destructively by call by reference. +***************************************************************/ +{ + BOOL Found; + LIST Scan1; + + Found = FALSE; + + while (list_Exist(*List) && Element == list_Car(*List)) { + Scan1 = list_Cdr(*List); + list_Free(*List); + *List = Scan1; + Found = TRUE; + } + + if (list_Exist(*List)) { + LIST Scan2; + + Scan2 = *List; + Scan1 = list_Cdr(*List); + + while (list_Exist(Scan1)) { + if (Element == list_Car(Scan1)) { + list_Rplacd(Scan2, list_Cdr(Scan1)); + list_Free(Scan1); + Scan1 = list_Cdr(Scan2); + Found = TRUE; + } else { + Scan2 = Scan1; + Scan1 = list_Cdr(Scan1); + } + } + } + + return Found; +} + + +BOOL list_DeleteOneFromList(LIST* List, POINTER Element) +/************************************************************** + INPUT: A list and an element pointer + RETURNS: TRUE, if <Element> was deleted; FALSE, otherwise. + EFFECTS: If <List> contains <Element> with respect to pointer equality, + the first occurrence of <Element> is deleted from <List>. + CAUTION: Destructive. +***************************************************************/ +{ + if (list_Exist(*List)) { + LIST Scan1; + + /* special treatment for the first element */ + if (Element == list_Car(*List)) { + Scan1 = list_Cdr(*List); + list_Free(*List); + *List = Scan1; + return TRUE; + } else { + LIST Scan2; + + for (Scan2 = *List, Scan1 = list_Cdr(*List); list_Exist(Scan1); ) { + if (Element == list_Car(Scan1)) { + list_Rplacd(Scan2, list_Cdr(Scan1)); + list_Free(Scan1); + Scan1 = list_Cdr(Scan2); + return TRUE; + } else { + Scan2 = Scan1; + Scan1 = list_Cdr(Scan1); + } + } + } + } + return FALSE; +} + + +BOOL list_IsSetOfPointers(LIST L) +/************************************************************** + INPUT: A list. + RETURNS: TRUE, if <L> is a set of pointers (without duplicates), + FALSE, otherwise. + EFFECT: The function needs n(n-1)/2 comparisons in the worst case, + where n is the length of the list. So its time complexity + is O(n^2). +***************************************************************/ +{ + for ( ; !list_Empty(L); L = list_Cdr(L)) { + if (list_PointerMember(list_Cdr(L), list_Car(L))) + return FALSE; + } + return TRUE; +} + + +LIST list_DeleteDuplicates(LIST List, BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: A list, an equality test for elements + RETURNS: The list where multiple occurrences are deleted. + CAUTION: Destructive. +***************************************************************/ +{ + LIST Scan; + + Scan = List; + + while (!list_Empty(Scan)) { + list_Rplacd(Scan, + list_DeleteElement(list_Cdr(Scan), list_Car(Scan), Test)); + Scan = list_Cdr(Scan); + } + return List; +} + + +LIST list_DeleteDuplicatesFree(LIST List, BOOL (*Test)(POINTER, POINTER), + void (*Free)(POINTER)) +/************************************************************** + INPUT: A list, an equality test for elements, and a free + function for elements. + RETURNS: The list where multiple occurrences are deleted. + CAUTION: Destructive and frees all duplicates. +***************************************************************/ +{ + LIST Scan; + + Scan = List; + + while (!list_Empty(Scan)) { + list_Rplacd(Scan, list_DeleteElementFree(list_Cdr(Scan), list_Car(Scan), Test, Free)); + Scan = list_Cdr(Scan); + } + return List; +} + + +LIST list_PointerDeleteDuplicates(LIST List) +/************************************************************** + INPUT: A list + RETURNS: The list where multiple occurrences are deleted. + CAUTION: Destructive. + EFFECT: The function needs +***************************************************************/ +{ + LIST Scan; + + Scan = List; + + while (!list_Empty(Scan)) { + list_Rplacd(Scan, list_PointerDeleteElement(list_Cdr(Scan), + list_Car(Scan))); + Scan = list_Cdr(Scan); + } + return List; +} + + +LIST list_NPointerUnion(LIST List1, LIST List2) +/************************************************************** + INPUT: Two lists. + RETURNS: Regarding both lists as sets, the union of the sets. + CAUTION: Destructive. +***************************************************************/ +{ + return list_PointerDeleteDuplicates(list_Nconc(List1,List2)); +} + + +LIST list_NUnion(LIST List1, LIST List2, BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: Two lists and an equality test for the elements. + RETURNS: Regarding both lists as sets, the union of the sets. + CAUTION: Destructive. +***************************************************************/ +{ + return list_DeleteDuplicates(list_Nconc(List1,List2), Test); +} + + +LIST list_NListTimes(LIST List1, LIST List2) +/************************************************************** + INPUT: Two lists of lists. + RETURNS: The list of combinations of element lists. + CAUTION: Destroys List1 and List2. +***************************************************************/ +{ + LIST Result, Scan1, Scan2; + + Result = list_Nil(); + + if (!list_Empty(List2)) { + for (Scan1=List1; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) + for (Scan2=List2; !list_Empty(Scan2); Scan2=list_Cdr(Scan2)) + Result = list_Cons(list_Append(((LIST)list_Car(Scan1)), + list_Copy((LIST)list_Car(Scan2))), + Result); + } + list_DeleteWithElement(List1, (void (*)(POINTER))list_Delete); + list_DeleteWithElement(List2, (void (*)(POINTER))list_Delete); + + return Result; +} + + +LIST list_NIntersect(LIST List1, LIST List2, BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: Two lists and an equality test for the elements. + RETURNS: Regarding both lists as sets, the intersection of the sets. + CAUTION: Destructive on List1 +***************************************************************/ +{ + LIST Scan1, Scan2; + + while (!list_Empty(List1) && !list_Member(List2, list_Car(List1), Test)) { + Scan1 = list_Cdr(List1); + list_Free(List1); + List1 = Scan1; + } + + if (list_Empty(List1)) + return List1; + + Scan1 = List1; + Scan2 = list_Cdr(List1); + + while (!list_Empty(Scan2)) { + if (list_Member(List2, list_Car(Scan2), Test)) { + Scan2 = list_Cdr(Scan2); + Scan1 = list_Cdr(Scan1); + } + else { + list_Rplacd(Scan1, list_Cdr(Scan2)); + list_Free(Scan2); + Scan2 = list_Cdr(Scan1); + } + } + return List1; +} + + +LIST list_NPointerIntersect(LIST List1, LIST List2) +/************************************************************** + INPUT: Two lists. + RETURNS: Regarding both lists as sets, the intersection of the sets. + CAUTION: Destructive on List1 +***************************************************************/ +{ + LIST Scan1, Scan2; + + while (!list_Empty(List1) && !list_PointerMember(List2, list_Car(List1))) { + Scan1 = list_Cdr(List1); + list_Free(List1); + List1 = Scan1; + } + + if (list_Empty(List1)) + return List1; + + Scan1 = List1; + Scan2 = list_Cdr(List1); + + while (!list_Empty(Scan2)) { + if (list_PointerMember(List2, list_Car(Scan2))) { + Scan2 = list_Cdr(Scan2); + Scan1 = list_Cdr(Scan1); + } + else { + list_Rplacd(Scan1, list_Cdr(Scan2)); + list_Free(Scan2); + Scan2 = list_Cdr(Scan1); + } + } + return List1; +} + + +void list_NInsert(LIST List1, LIST List2) +/************************************************************** + INPUT: Two lists where <List1> must not be empty. + EFFECT: <List2> is destructively concatenated after + the first element of <List1>. + RETURNS: void. + CAUTION: Destructive on List1 and List2. +***************************************************************/ +{ + LIST Help; + +#ifdef CHECK + if (list_Empty(List1)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In list_NInsert: Empty list argument."); + misc_FinishErrorReport(); + } +#endif + + Help = list_Cdr(List1); + list_Rplacd(List1,List2); + List2 = List1; + + while (!list_Empty(list_Cdr(List2))) + List2 = list_Cdr(List2); + + list_Rplacd(List2,Help); +} + + +BOOL list_HasIntersection(LIST List1, LIST List2) +/************************************************************** + INPUT: Two lists . + RETURNS: TRUE iff List1 and List2 have a common element. + EFFECT: The function needs time O(n*m), where n and m are the + lengths of the lists. +***************************************************************/ +{ + LIST Scan; + + if (!list_Empty(List2)) { + for (Scan=List1; !list_Empty(Scan); Scan=list_Cdr(Scan)) + if (list_PointerMember(List2, list_Car(Scan))) + return TRUE; + } + return FALSE; +} + + +LIST list_NPointerDifference(LIST List1, LIST List2) +/************************************************************** + INPUT: Two lists. + RETURNS: The list List1-List2. + CAUTION: Destructive on List1. +***************************************************************/ +{ + LIST Scan; + + if (!list_Empty(List1)) { + for (Scan=List2; !list_Empty(Scan); Scan=list_Cdr(Scan)) + List1 = list_PointerDeleteElement(List1, list_Car(Scan)); + } + return List1; +} + + +LIST list_NDifference(LIST List1, LIST List2, BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: Two lists and an equality test for elements. + RETURNS: The list List1-List2 wrt. <Test>. + CAUTION: Destructive on List1. +***************************************************************/ +{ + LIST Scan; + + if (!list_Empty(List1)) { + for (Scan=List2; !list_Empty(Scan); Scan=list_Cdr(Scan)) + List1 = list_DeleteElement(List1, list_Car(Scan), Test); + } + return List1; +} + + +LIST list_NMultisetDifference(LIST List1, LIST List2, BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: Two lists representing multisets and an equality + test for elements. + RETURNS: The multiset difference List1-List2 wrt. <Test>. + CAUTION: Destructive on List1. The memory of deleted + elements is not freed. +***************************************************************/ +{ + LIST scan; + /* Delete equal arguments */ + if (!list_Empty(List1)) { + for (scan = List2; !list_Empty(scan); scan = list_Cdr(scan)) + /* Delete at most one element from List1 equal to */ + /* the actual element of List2. */ + List1 = list_DeleteOneElement(List1, list_Car(scan), Test); + } + return List1; +} + + +BOOL list_PointerReplaceMember(LIST List, POINTER Old, POINTER New) +/************************************************************** + INPUT: A list, a pointer to an old element, a pointer to a new element + RETURNS: TRUE iff <Old> was replaced. + EFFECT: The first occurrence of <Old> in the list is replaced by <New>. +***************************************************************/ +{ + while (!list_Empty(List)) { + if (Old == list_Car(List)) { + list_Rplaca(List, New); + return TRUE; + } + List = list_Cdr(List); + } + return FALSE; +} + + +void list_DeleteAssocListWithValues(LIST List, void (*ValueDelete)(POINTER)) +/************************************************************** + INPUT: An association list and a delete function for the values. + RETURNS: void. + EFFECT: The assoc list and its values are deleted. +***************************************************************/ +{ + LIST Scan; + + for (Scan=List;!list_Empty(Scan);Scan = list_Cdr(Scan)) { + ValueDelete(list_PairSecond(list_Car(Scan))); + list_PairFree(list_Car(Scan)); + } + + list_Delete(List); +} + + +POINTER list_AssocListValue(LIST List, POINTER Key) +/************************************************************** + INPUT: An association list and a key. + RETURNS: The value for <key> in the list. If <key> is not + contained, NULL. +***************************************************************/ +{ + LIST Scan; + + for (Scan=List;!list_Empty(Scan);Scan = list_Cdr(Scan)) + if (Key == list_PairFirst(list_Car(Scan))) + return list_PairSecond(list_Car(Scan)); + + return NULL; +} + + +LIST list_AssocListPair(LIST List, POINTER Key) +/************************************************************** + INPUT: An association list and a key. + RETURNS: The (<key>.<value) in the list. If <key> is not + contained, the NULL pair. +***************************************************************/ +{ + LIST Scan; + + for (Scan=List;!list_Empty(Scan);Scan = list_Cdr(Scan)) + if (Key == list_PairFirst(list_Car(Scan))) + return list_Car(Scan); + + return list_PairNull(); +} + + +LIST list_MultisetDistribution(LIST Multiset) +/************************************************************** + INPUT: A list representing a multiset. + RETURNS: The associative list of pairs (<element>.<occurrences>) + representing the distribution of elements in the list. + If the input multiset is empty, the NULL pair. +***************************************************************/ +{ + LIST Distribution; + LIST Scan; + + Distribution = list_PairNull(); + + for (Scan = Multiset; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + LIST Count; + POINTER Element; + int Occurences; + + Element = list_Car(Scan); + Count = list_AssocListPair(Distribution, Element); + + if (Count != list_PairNull()) { + Occurences = (int) list_PairSecond(Count); + list_PairRplacSecond(Count, (POINTER) (Occurences + 1)); + } + else { + Distribution = list_AssocCons(Distribution, Element, (POINTER) 1); + } + } + + return Distribution; +} + + +int list_CompareElementDistribution(LIST LeftPair, LIST RightPair) +/************************************************************** + INPUT: Two lists, representing single element frequency + counts. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two element frequencies. +***************************************************************/ +{ + if ((int) list_PairSecond(LeftPair) < (int) list_PairSecond(RightPair)) { + return -1; + } + else if ((int) list_PairSecond(LeftPair) > (int) list_PairSecond(RightPair)) { + return 1; + } + + return 0; +} + + +BOOL list_CompareElementDistributionLEQ(LIST LeftPair, LIST RightPair) { +/************************************************************** + INPUT: Two lists, representing single element frequency + counts. + RETURNS: TRUE if left <= right, FALSE otherwise. + EFFECT: Compares two element frequencies. +***************************************************************/ + return (list_CompareElementDistribution(LeftPair, RightPair) <= 0); +} + + +static int list_CompareDistributions(LIST Left, LIST Right) +/************************************************************** + INPUT: Two lists, representing element distributions. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares the two distributions by comparing the + element frequencies from left to right. + CAUTION: Expects the distributions to be sorted. +***************************************************************/ +{ + LIST scan, scan2; + int result; + + result = 0; + + scan = Left; + scan2 = Right; + + /* Compare distributions. */ + + while ( !(list_Empty(scan) || list_Empty(scan2))) { + result = list_CompareElementDistribution(list_Car(scan), list_Car(scan2)); + if (result != 0) { + break; + } + + scan = list_Cdr(scan); + scan2 = list_Cdr(scan2); + } + + /* If the result is 0, and a distribution still + has elements left, it is declared to be greater. + */ + if (result == 0) { + if (list_Empty(scan) && !list_Empty(scan2)) + result = -1; + else if (!list_Empty(scan) && list_Empty(scan2)) + result = 1; + } + + return result; +} + + +int list_CompareMultisetsByElementDistribution(LIST Left, LIST Right) +/************************************************************** + INPUT: Two lists, representing multisets. + RETURNS: 1 if left > right, -1 if left < right, 0 otherwise. + EFFECT: Compares two multisets by counting their element + frequencies, sorting them, and comparing the + resulting multisets over natural numbers. +***************************************************************/ +{ + LIST lmsd, rmsd; /* multiset distributions. */ + int result; + + /* Convert multiset of elements into a + multiset of pairs (element, occurrences). + */ + + lmsd = list_MultisetDistribution(Left); + rmsd = list_MultisetDistribution(Right); + + /* Sort multiset distributions in order + to make them comparable. + */ + + lmsd = list_Sort(lmsd, (BOOL (*) (POINTER, POINTER)) list_CompareElementDistributionLEQ); + rmsd = list_Sort(rmsd, (BOOL (*) (POINTER, POINTER)) list_CompareElementDistributionLEQ); + + result = list_CompareDistributions(lmsd, rmsd); + + list_DeleteDistribution(lmsd); + list_DeleteDistribution(rmsd); + + return result; +} + + +NAT list_Length(LIST List) +/************************************************************** + INPUT: A List. + RETURNS: The number of elements.. + EFFECT: The function needs time O(n), where <n> is the length + of the list. +***************************************************************/ +{ + NAT Result; + + Result = 0; + + while (!list_Empty(List)) { + Result++; + List = list_Cdr(List); + } + + return Result; +} + + +NAT list_Bytes(LIST List) +/************************************************************** + INPUT: A List. + RETURNS: The number of Bytes occupied by the list structure of <List> + EFFECT: the function needs time O(n), where <n> is the length + of the list. +***************************************************************/ +{ + return (list_Length(List)*sizeof(LIST_NODE)); +} diff --git a/test/spass/list.h b/test/spass/list.h new file mode 100644 index 0000000000000000000000000000000000000000..fa390a3476151b24836155ac6f814b059246251e --- /dev/null +++ b/test/spass/list.h @@ -0,0 +1,433 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * LISTS * */ +/* * * */ +/* * $Module: LIST * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _LIST_ +#define _LIST_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "memory.h" +#include "misc.h" + +/**************************************************************/ +/* Structures */ +/**************************************************************/ + +typedef struct LIST_HELP { + struct LIST_HELP *cdr; + POINTER car; +} LIST_NODE; + +typedef LIST_NODE *LIST; + +/**************************************************************/ +/* Macros */ +/**************************************************************/ + +static __inline__ void list_Free(LIST L) +{ + memory_Free(L, sizeof(LIST_NODE)); +} + +static __inline__ LIST list_Nil(void) +{ + return NULL; +} + +static __inline__ BOOL list_Empty(LIST L) +{ + return L == NULL; +} + +static __inline__ BOOL list_Exist(LIST L) +{ + return L != NULL; +} + +static __inline__ POINTER list_Car(LIST L) +{ + return L->car; +} + +static __inline__ POINTER list_NCar(LIST *L) +{ + POINTER Result; + LIST Help; + + Result = (*L)->car; + Help = (*L)->cdr; + list_Free(*L); + *L = Help; + return Result; +} + +static __inline__ LIST list_Cdr(LIST L) +{ + return L->cdr; +} + +static __inline__ POINTER list_First(LIST L) +{ + return list_Car(L); +} + +static __inline__ POINTER list_Second(LIST L) +{ + return list_Car(list_Cdr(L)); +} + +static __inline__ POINTER list_Third(LIST L) +{ + return list_Car(list_Cdr(list_Cdr(L))); +} + +static __inline__ POINTER list_Fourth(LIST L) +{ + return(list_Third(list_Cdr(L))); +} + +static __inline__ POINTER list_Fifth(LIST L) +{ + return(list_Fourth(list_Cdr(L))); +} + +static __inline__ void list_Rplacd(LIST L1, LIST L2) +{ + L1->cdr = L2; +} + +static __inline__ void list_Rplaca(LIST L, POINTER P) +{ + L->car = P; +} + +static __inline__ void list_RplacSecond(LIST L, POINTER P) +{ + list_Rplaca(list_Cdr(L), P); +} + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +LIST list_Copy(const LIST); +LIST list_CopyWithElement(const LIST, POINTER (*)(POINTER)); +void list_InsertNext(LIST, POINTER); + +void list_NMapCar(LIST, POINTER (*)(POINTER)); +void list_Apply(void (*)(POINTER), LIST); + +LIST list_Reverse(const LIST); +LIST list_NReverse(LIST); + +void list_Split(LIST, LIST *, LIST *); +LIST list_PointerSort(LIST); +LIST list_Merge(LIST, LIST, BOOL (*)(POINTER, POINTER)); +LIST list_MergeSort(LIST, BOOL (*)(POINTER, POINTER)); +LIST list_InsertionSort(LIST, BOOL (*)(POINTER, POINTER)); +LIST list_Sort(LIST, BOOL (*)(POINTER, POINTER)); +BOOL list_SortedInOrder(LIST, BOOL (*)(POINTER, POINTER)); +LIST list_NumberSort(LIST , NAT (*)(POINTER)); +LIST list_GreaterNumberSort(LIST , NAT (*)(POINTER)); +LIST list_NNumberMerge(LIST , LIST, NAT (*)(POINTER)); + +POINTER list_DequeueNext(LIST); +POINTER list_NthElement(LIST, NAT); +void list_DeleteWithElement(LIST, void (*)(POINTER)); +NAT list_DeleteWithElementCount(LIST, void (*)(POINTER)); +LIST list_DeleteElement(LIST, POINTER, BOOL (*)(POINTER, POINTER)); +LIST list_DeleteElementIf(LIST, BOOL (*)(POINTER)); +LIST list_DeleteElementIfFree(LIST, BOOL (*)(POINTER), void (*)(POINTER)); +LIST list_DeleteElementFree(LIST, POINTER, BOOL (*)(POINTER, POINTER), void (*)(POINTER)); +LIST list_DeleteOneElement(LIST, POINTER, BOOL (*)(POINTER, POINTER)); +LIST list_PointerDeleteElement(LIST, POINTER); +LIST list_PointerDeleteElementFree(LIST, POINTER, void (*)(POINTER)); +LIST list_PointerDeleteOneElement(LIST, POINTER); +BOOL list_DeleteFromList(LIST*, POINTER); +BOOL list_DeleteOneFromList(LIST*, POINTER); +LIST list_DeleteDuplicates(LIST, BOOL (*)(POINTER, POINTER)); +LIST list_DeleteDuplicatesFree(LIST, BOOL (*)(POINTER, POINTER), void (*)(POINTER)); +LIST list_PointerDeleteDuplicates(LIST); + +BOOL list_IsSetOfPointers(LIST); +LIST list_NPointerUnion(LIST, LIST); +LIST list_NUnion(LIST, LIST, BOOL (*)(POINTER, POINTER)); +LIST list_NListTimes(LIST, LIST); +LIST list_NIntersect(LIST, LIST, BOOL (*)(POINTER, POINTER)); +void list_NInsert(LIST, LIST); +LIST list_NPointerIntersect(LIST, LIST); +BOOL list_HasIntersection(LIST, LIST); +LIST list_NPointerDifference(LIST, LIST); +LIST list_NDifference(LIST, LIST, BOOL (*)(POINTER, POINTER)); +LIST list_NMultisetDifference(LIST, LIST, BOOL (*)(POINTER, POINTER)); +BOOL list_PointerReplaceMember(LIST, POINTER, POINTER); + +void list_DeleteAssocListWithValues(LIST, void (*)(POINTER)); +POINTER list_AssocListValue(LIST, POINTER); +LIST list_AssocListPair(LIST, POINTER); + +LIST list_MultisetDistribution(LIST); +int list_CompareMultisetsByElementDistribution(LIST, LIST); + +NAT list_Length(LIST); +NAT list_Bytes(LIST); + +/**************************************************************/ +/* Functional Inline Functions */ +/**************************************************************/ + +static __inline__ LIST list_Cons(POINTER Ptr, const LIST List) +{ + LIST Cell; + + Cell = (LIST)memory_Malloc(sizeof(LIST_NODE)); + Cell->car = Ptr; + Cell->cdr = List; + return Cell; +} + + +static __inline__ LIST list_Nconc(LIST List1, LIST List2) +{ + LIST Result; + + if (list_Empty(List1)) + return List2; + + if (list_Empty(List2)) + return List1; + + Result = List1; + for (List1 = Result; !list_Empty(list_Cdr(List1)); List1 = list_Cdr(List1)) + /* empty */; + List1->cdr = List2; + return Result; +} + + +static __inline__ LIST list_List(POINTER P) +{ + return list_Cons(P,list_Nil()); +} + + +static __inline__ LIST list_Append(LIST List1, LIST List2) +{ + LIST Result; + + if (list_Empty(List1)) + return List2; + if (list_Empty(List2)) + return list_Copy(List1); + + Result = list_Copy(List1); + for (List1 = Result; !list_Empty(list_Cdr(List1)); List1 = list_Cdr(List1)) + /* empty */; + List1->cdr = List2; + return Result; +} + + +static __inline__ void list_Delete(LIST L) +{ + LIST Current; + + Current = L; + while (!list_Empty(Current)) { + L = list_Cdr(L); + list_Free(Current); + Current = L; + } +} + +static __inline__ BOOL list_Member(LIST List, POINTER Element, + BOOL (*Test)(POINTER, POINTER)) +/************************************************************** + INPUT: A list and an element pointer and an equality test for two elements. + RETURNS: TRUE iff Element is in List with respect to Test +***************************************************************/ +{ + while (!list_Empty(List)) { + if (Test(Element, list_Car(List))) + return TRUE; + List = list_Cdr(List); + } + + return FALSE; +} + + +static __inline__ BOOL list_PointerMember(LIST List, POINTER Element) +/************************************************************** + INPUT: A list and an element pointer. + RETURNS: TRUE iff Element is in List with respect to pointer equality. +***************************************************************/ +{ + while (!list_Empty(List)) { + if (Element == list_Car(List)) + return TRUE; + List = list_Cdr(List); + } + + return FALSE; +} + +/**************************************************************/ +/* Stack Macros */ +/**************************************************************/ + +static __inline__ LIST list_StackBottom(void) +{ + return list_Nil(); +} + + +static __inline__ BOOL list_StackEmpty(LIST S) +{ + return list_Empty(S); +} + + +static __inline__ LIST list_Push(POINTER I, LIST L) +{ + return list_Cons(I, L); +} + + +static __inline__ POINTER list_Top(LIST L) +{ + return list_Car(L); +} + + +static __inline__ LIST list_Pop(LIST L) +{ + LIST Aux = L; + + L = list_Cdr(L); + list_Free(Aux); + return L; +} + + +static __inline__ void list_RplacTop(LIST L, POINTER P) +{ + list_Rplaca(L, P); +} + + +static __inline__ LIST list_StackFree(LIST L) +{ + while (!list_StackEmpty(L)) + L = list_Pop(L); + return list_Nil(); +} + + +/**************************************************************/ +/* Pair Macros */ +/**************************************************************/ + +static __inline__ LIST list_PairNull(void) +{ + return list_Nil(); +} + + +static __inline__ LIST list_PairCreate(POINTER P1, POINTER P2) +{ + return list_Cons(P1, P2); +} + + +static __inline__ void list_PairFree(LIST L) +{ + list_Free(L); +} + + +static __inline__ POINTER list_PairFirst(LIST L) +{ + return list_Car(L); +} + + +static __inline__ POINTER list_PairSecond(LIST L) +{ + return (POINTER)list_Cdr(L); +} + +static __inline__ void list_PairRplacSecond(LIST L, POINTER P) +{ + list_Rplacd(L,P); +} + +static __inline__ void list_DeletePairList(LIST L) + /* Delete a list of pairs */ +{ + list_DeleteWithElement(L, (void (*)(POINTER))list_PairFree); +} + +static __inline__ void list_DeleteDistribution(LIST L) +{ + list_DeletePairList(L); +} + +/**************************************************************/ +/* Assoc Lists */ +/**************************************************************/ + + +static __inline__ LIST list_AssocCons(LIST L, POINTER Key, POINTER Value) +{ + return list_Cons(list_PairCreate(Key, Value), L); +} + +#endif diff --git a/test/spass/memory.c b/test/spass/memory.c new file mode 100644 index 0000000000000000000000000000000000000000..a785515d302e5d686bc0f384e3195805b18b2057 --- /dev/null +++ b/test/spass/memory.c @@ -0,0 +1,1595 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * DYNAMIC MEMORY MANAGEMENT MODULE * */ +/* * * */ +/* * $Module: MEMORY * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "memory.h" + +unsigned int memory_PAGESIZE; /* size of a page */ +long memory_MAXMEM; /* amount of memory available for allocation */ +static int memory__EOF = EOF; /* internal "End Of Memory" marker */ +unsigned long memory_NEWBYTES; /* number of allocated bytes */ +unsigned long memory_FREEDBYTES; /* number of freed bytes */ + +const unsigned int memory_ALIGN = sizeof(POINTER); +/* Crucial: hardware must support access to words + of size POINTER. +*/ + +#ifdef CHECK +unsigned int memory_LEFTTAG; /* size of left debug mark */ +unsigned int memory_OFFSET; /* alignment-correct size of left debug mark */ +unsigned int memory_MARKSIZE; /* total size of debug marks */ + +BOOL memory_MANAGEMENT_INITIALIZED = FALSE; + +#else /* CHECK not defined */ +unsigned int memory_MARKSIZE = 0; +unsigned int memory_OFFSET = 0; +#endif /* CHECK */ + +const unsigned int memory_MAGICMALLOC = 1; /* "block allocated" marker */ +const unsigned int memory_MAGICFREE = 2; /* "block freed" marker */ + +/* Internal array of resources for different block sizes */ +/* ... + 1 to support odd values for memory__SHAREDPAGES like 7 */ +static MEMORY_RESOURCE memory_PAGES[memory__DYNMAXSIZE/memory__SHAREDPAGES + 1]; + + +/* Resources for all administrated block sizes */ +MEMORY_RESOURCE * memory_ARRAY[memory__DYNMAXSIZE]; + +/* double linked list for administering blocks of memory + whose size is greater or equal to memory__DYNMAXSIZE. +*/ +MEMORY_BIGBLOCKHEADER memory_BIGBLOCKS = NULL; + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INITIALIZATION * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +#ifdef CHECK +static BOOL memory_ManagementInitialized(void) +/********************************************************** + INPUT : None. + RETURNS: TRUE if memory management is already initialized, + else FALSE. + SUMMARY: Checks if memory_Init was called. +**********************************************************/ +{ + return memory_MANAGEMENT_INITIALIZED; +} +#endif /* CHECK */ + +void memory_Init(long Maxmem) +/************************************************************* + INPUT : The maximal amount of memory available in bytes + for the memory module; if Maxmem < 0 the module + allocates as much memory as available from the + system. + RETURNS: None. + SUMMARY: Initializes the memory management. It has to be + called before you can perform any module operation. + This function automatically increases the default + page size if it is too small for two objects of + size memory__DYNMAXSIZE. +*************************************************************/ +{ + int i; + int extra; /* size of internally used space on each page */ + + memory_FREEDBYTES = 0; /* set total number of freed bytes to zero */ + memory_NEWBYTES = 0; /* set total number of allocated bytes to zero */ + + /* set the size of a page we allocate from the operating system */ + memory_PAGESIZE = memory__DEFAULTPAGESIZE; + +#ifdef CHECK + + /* Test if memory management has already been initialized */ + + if (!memory_ManagementInitialized()) { + /* if that is not the case, set check variable to TRUE */ + memory_MANAGEMENT_INITIALIZED = TRUE; + } + else { + /* otherwise the user is trying initialize it for a + second time, so print an error and exit. + */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_Init:"); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Trying to initialize memory management"); + misc_UserErrorReport(" for a second time.\n"); + misc_FinishUserErrorReport(); + } + + /* Calculate the size of debug marks */ + memory_LEFTTAG = sizeof(MEMORY_INFONODE) + sizeof(unsigned int); + + if ((sizeof(MEMORY_INFONODE) + sizeof(unsigned int)) % memory_ALIGN == 0) { + memory_OFFSET = memory_LEFTTAG; + } + else { + memory_OFFSET = memory_LEFTTAG + memory_ALIGN + - (memory_LEFTTAG % memory_ALIGN); + } + + if ((sizeof(unsigned int) % memory_ALIGN) == 0) { + memory_MARKSIZE = memory_OFFSET + sizeof(unsigned int); + } + else { + memory_MARKSIZE = memory_OFFSET + sizeof(unsigned int) + memory_ALIGN + - (sizeof(unsigned int) % memory_ALIGN); + } +#endif + + /* Calculate the size of internally used space on each page */ + /* extra: One pointer for chaining pages, one for EOF (+ marksize) */ + extra = 2*sizeof(POINTER) + memory_MARKSIZE; + + + /* Test whether page size is reasonable with respect + to dynamic allocation threshold + */ + while (memory_PAGESIZE < (2*(memory__DYNMAXSIZE + memory_MARKSIZE) + extra)) { + /* Minimum two objects per allocated page */ + memory_PAGESIZE += memory__DEFAULTPAGESIZE/2; + } + + /* Set amount of memory available to the module for allocation */ + if (Maxmem <= 0) { + /* unlimited (limited only by the operating system) */ + memory_MAXMEM = memory__UNLIMITED; + } + else { + /* Maxmem bytes */ + memory_MAXMEM = Maxmem; + } + + /* Initialize memory_ARRAY and memory_RESOURCEs */ + for (i=1; i<memory__DYNMAXSIZE; i++) { + MEMORY_RESOURCE *CurrentResource; + int TotalSize; + + /* Map memory_ARRAY[i] to appropriate Resource */ + memory_ARRAY[i] = &memory_PAGES[(i-1)/memory__SHAREDPAGES]; + + CurrentResource = memory_ARRAY[i]; + + CurrentResource->free = &memory__EOF; /* no blocks freed */ + CurrentResource->next = &memory__EOF; /* no blocks allocated */ + CurrentResource->end_of_page = &memory__EOF; /* no (end of) page */ + CurrentResource->page = &memory__EOF; /* no page allocated */ + + /* Size of a properly aligned block of requested size i */ + CurrentResource->aligned_size = memory_CalculateRealBlockSize(i); + + /* Total block size including debug marks */ + CurrentResource->total_size = memory_MARKSIZE + + CurrentResource->aligned_size; + + TotalSize = CurrentResource->total_size; + + /* last block´s offset */ + CurrentResource->offset = + ((memory_PAGESIZE-extra)/TotalSize)*TotalSize + + sizeof(POINTER) + memory_OFFSET; + } +} + + +void memory_Restrict(long Maxmem) +/************************************************************* + INPUT : The maximal amount of memory available for further + allocation (in bytes); if Maxmem < 0 future + allocations are unrestricted. + RETURNS: None. + SUMMARY: Sets the maximal amount of memory available for + future allocations. If the user tries to allocate + more memory, the module displays an error message + and terminates the program by calling the exit() + function. +*************************************************************/ +{ + /* Reset the maximum amount of memory available */ + if (Maxmem <= 0) { + /* unlimited */ + memory_MAXMEM = memory__UNLIMITED; + } + else { + /* Maxmem bytes */ + memory_MAXMEM = Maxmem; + } +} + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CHECK CODE * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +#ifdef CHECK +static void memory_CheckIfModuleIsInitialized(const char * Function, + const char * File, + unsigned short int Line) +/******************************************************** + INPUT : The name of the function that requests the + check, the name of the file and the line, + where the requesting function was called, and + the line. + RETURNS: None. + SUMMARY: Checks if the memory management module has + been properly initialized. You need to + initialize the module by calling memory_Init + before you use any functions from the module. + If the check fails, this function prints an + error message and exits the application. +*********************************************************/ +{ + if (!memory_ManagementInitialized()) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In %s:", Function); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Memory management is not initialized."); + misc_UserErrorReport("\n You have to call memory_Init()"); + misc_UserErrorReport(" before you can use memory management functions.\n"); + misc_UserErrorReport("\n Error occurred in %s", Function); + misc_UserErrorReport(" called from file %s at line %d.\n", + File, Line); + misc_FinishUserErrorReport(); + } +} + +static void memory_CheckIfPointerIsAlreadyFreed(POINTER Pointer, + const char * Function, + const char * File, + unsigned short int Line) +/******************************************************** + INPUT : The pointer to be checked, the name of the + function that requests the check, the name of + the file and the line, where the requesting + function was called, and the line. + RETURNS: None. + SUMMARY: Checks if the pointer has already been freed. + If the check fails, this function prints an + error message and exits the application. +*********************************************************/ +{ + if ( memory_GetBlockStatus(Pointer) == memory_MAGICFREE) { + MEMORY_INFO Info; /* block´s debug information */ + + Info = (MEMORY_INFO) ((char *) Pointer - memory_OFFSET); + + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In %s:", Function); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Pointer %p was allocated in file %s at line %d.", + Pointer, Info->mallocInFile, Info->mallocAtLine); + misc_UserErrorReport("\n It has already been freed in file %s at line %d.", + Info->freeInFile, Info->freeAtLine); + misc_UserErrorReport("\n Size of memory block is %d bytes.", + memory_GetBlockSize(Pointer)); + misc_UserErrorReport("\n Error occurred in %s", Function); + misc_UserErrorReport(" called from file %s at line %d.\n", + File, Line); + misc_FinishUserErrorReport(); + } +} + +static void memory_CheckPointer(POINTER Pointer, unsigned int Size) +/********************************************************* + INPUT : A pointer to a block of memory, and its size. + RETURNS: Nothing. + SUMMARY: Checks whether a pointer points to a valid + block of memory. + + This function performs the following tests: + + Is Pointer a NULL pointer? + + Is Size equal to zero? + + Is the Pointer alignment correct? + + Did someone write over the memory block + boundaries? + + Is Size still correct? + + If Size is greater than memory__DYNMAXSIZE: + Is it properly administrated by the module? + + If the memory block was freed: Did someone + write to it after deallocation? +*********************************************************/ +{ + + MEMORY_INFO Info; + unsigned int BlockSize, RealBlockSize, BlockStatus; + + Info = (MEMORY_INFO) ((char *) Pointer - memory_OFFSET); + + RealBlockSize = memory_LookupRealBlockSize(Size); + + if (Pointer == NULL) { + /* NULL pointers must not be dereferenced */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_CheckPointer:"); + misc_UserErrorReport("\n Memory Error. Pointer is a NULL pointer.\n"); + misc_FinishUserErrorReport(); + } + + + if (Size == 0) { + /* We don´t allocate 0 byte sized blocks */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_CheckPointer:"); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Pointer %p points to a block of memory", Pointer); + misc_UserErrorReport(" with size 0.\n"); + misc_FinishUserErrorReport(); + } + + if ((unsigned long)Pointer % (unsigned long)memory_ALIGN){ + /* we expect all pointers to be correctly aligned */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_CheckPointer:"); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Pointer %p is not a legal pointer.\n", Pointer); + misc_FinishUserErrorReport(); + } + + /* BlockStatus and BlockSize are initialized after + we can be sure Pointer is properly aligned. + */ + + BlockStatus = memory_GetBlockStatus(Pointer); + BlockSize = memory_GetBlockSize(Pointer); + + if (BlockStatus != memory_MAGICMALLOC + && BlockStatus != memory_MAGICFREE) { + + /* we expect block status to be either + memory_MAGICMALLOC or memory_MAGICFREE. + Other values might result from overwriting, + trying to return an unallocated block, + or trying to return a block allocated with + another allocator. + */ + + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_CheckPointer:"); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Pointer %p was not (de)allocated by the module,", + Pointer); + misc_UserErrorReport("\n or the memory block was corrupted.\n"); + misc_FinishUserErrorReport(); + } + + if (BlockStatus == memory_MAGICMALLOC) { + if (BlockSize != Size) { + + /* we expect block size in a block´s debug + information and given block size to match. + */ + + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_CheckPointer:"); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Pointer %p was apparently allocated for", + Pointer); + misc_UserErrorReport(" a block of size %d,", + BlockSize); + misc_UserErrorReport("\n but it is expected to be a block of size %d.", + Size); + misc_UserErrorReport("\n Probably the memory block was corrupted.\n"); + misc_FinishUserErrorReport(); + + /* since the left dog tag seems to be corrupted we can not safely assume + that our memory info structure is still valid so we can't print it*/ + } + + if ((Size % memory_ALIGN) || (Size % memory__SHAREDPAGES)) { + /* check the fillbytes between used storage + and dog tag for overwriting */ + char * ptr, * limit; + + limit = (char *)Pointer + RealBlockSize; + + for (ptr = (char *)Pointer + Size; ptr < limit; ptr++) { + if (*ptr != memory__FREESHREDDER) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_CheckPointer:"); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Pointer %p was allocated in file %s at line %d,", + Pointer, Info->mallocInFile, Info->mallocAtLine); + misc_UserErrorReport("\n for a block of size %d.", + BlockSize); + misc_UserErrorReport("\n The memory block was corrupted.\n"); + misc_FinishUserErrorReport(); + } + } + } + } + + if (Size >= memory__DYNMAXSIZE) { + /* we expect big blocks to be correctly linked */ + MEMORY_BIGBLOCKHEADER BigBlockHeader; + + BigBlockHeader = (MEMORY_BIGBLOCKHEADER) ((char *) Pointer - memory_OFFSET + - sizeof(MEMORY_BIGBLOCKHEADERNODE)); + + /* this test might crash the program + if something is wrong with the pointers, + so you may not get a message every time. + */ + if (((BigBlockHeader->previous != NULL) + && (BigBlockHeader->previous->next != BigBlockHeader)) + || ((BigBlockHeader->previous == NULL) + && (memory_BIGBLOCKS != BigBlockHeader)) + || ((BigBlockHeader->next != NULL) + && (BigBlockHeader->next->previous != BigBlockHeader))) { + + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_CheckPointer:"); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Pointer %p was not allocated by the module,", + Pointer); + misc_UserErrorReport("\n or the memory block was corrupted.\n"); + misc_FinishUserErrorReport(); + } + } + + if (BlockStatus == memory_MAGICFREE) { + /* test if someone wrote over freed memory */ + char * ptr, * limit; + + limit = (char *)Pointer + RealBlockSize; + + for (ptr = (char *)Pointer + sizeof(POINTER); ptr < limit ; ptr++){ + /* first sizeof(POINTER) bytes are reserved for the + pointer to the next freed block in the list. All + other bytes in the block should still have the value + of memory__FREESHREDDER + */ + if (*ptr != memory__FREESHREDDER) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_CheckPointer:"); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Pointer %p was allocated in file %s at line %d", + Pointer, Info->mallocInFile, Info->mallocAtLine); + misc_UserErrorReport("\n for a block of size %d",BlockSize); + misc_UserErrorReport("\n and freed in file %s at line %d.", + Info->freeInFile, Info->freeAtLine); + misc_UserErrorReport("\n The memory block was used after deallocation.\n"); + misc_FinishUserErrorReport(); + } + } + } +} + +void memory_CheckFree(POINTER Freepointer, unsigned int Size, + unsigned int RealBlockSize, const char * File, + unsigned short int Line) +/********************************************************** + INPUT : The pointer to be freed, the size of the block + it is supposed to point to, the real size of + that block, the file and line where memory_Free + was called. + RETURNS: None. + SUMMARY: Checks if memory management was initialized, + the given pointer is legal, and not freed + already. It also zeroes the freed memory, and + sets the block's debug and administration + information. +**********************************************************/ +{ + MEMORY_INFO Info; /* block´s debug information */ + + /* Check if memory management was initialized */ + memory_CheckIfModuleIsInitialized("memory_Free", File, Line); + + /* Check if given pointer is legal */ + memory_CheckPointer(Freepointer, Size); + + /* Check if current pointer is being freed for a second time */ + memory_CheckIfPointerIsAlreadyFreed(Freepointer, "memory_Free", File, Line); + + /* Set all bytes to zero, so we can detect overwriting of freed memory */ + memset (Freepointer, memory__FREESHREDDER, RealBlockSize); + + /* Get current block´s debug information */ + Info = (MEMORY_INFO) ((char *) Freepointer - memory_OFFSET); + + /* Set block´s debug and administration information */ + memory_SetInfo(Info,Info->mallocInFile, Info->mallocAtLine, File, Line); + memory_SetBlockStatusAndSize(Freepointer, memory_MAGICFREE, Size); +} +#endif /* CHECK */ + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * MALLOC * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +#ifdef NO_MEMORY_MANAGEMENT + +POINTER memory_Malloc(unsigned int Bytes) +{ + char *mem; /* pointer to memory block obtained from malloc */ + + /* Pass the call through to compiler´s malloc */ + mem = (char *)malloc(Bytes); + + /* If malloc fails print an error message and exit */ + if (mem == NULL) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_Malloc:"); + misc_UserErrorReport("\n Memory Error. Out of memory.\n"); + misc_FinishUserErrorReport(); + } + + return mem; +} + +#else + +#ifdef CHECK +POINTER memory_MallocIntern(unsigned int Bytes, + const char * File, + unsigned short int Line) +#else +POINTER memory_Malloc(unsigned int Bytes) +#endif +/******************************************************** + INPUT : The size of the requested memory block. + RETURNS: A pointer to a block of <Bytes> bytes. + SUMMARY: Allocates a memory block of requested length. + EXCEPT : Trying to allocate 0 bytes, violating a memory + restriction, or running out of system memory + cause the function to print an error message and + call exit(). +*********************************************************/ +{ + char *NewMemory; /* pointer to allocated memory */ + + MEMORY_RESOURCE *Resource; /* current page resource, + required if we do not allocate + a big block */ + +#ifdef CHECK + MEMORY_INFO NewInfo; /* Storage for file and line + of allocation */ +#endif + + +#ifdef CHECK + /* Is the module initialized? */ + memory_CheckIfModuleIsInitialized("memory_Malloc", File, Line); + + /* Is it a request for a block of zero bytes? */ + if (Bytes == 0) { + /* The latest draft for the ANSI C 9X standard says in section 7.20.3: + + "If the size of the space requested is zero, the behavior is + implementation-defined: either a null pointer is returned, or + the behavior is as if the size were some nonzero value, + except that the pointer shall not be used to access an object." + + We have decided to print an error and exit upon such requests + since they are often originated by a bug. + + Nonstandard but hopefully helpful. + */ + + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_Malloc:"); + misc_UserErrorReport("\n Memory Error. Tried to allocate 0 Bytes!"); + misc_UserErrorReport("\n Error occurred in memory_Malloc"); + misc_UserErrorReport(" called from file %s at line %d.\n", + File, Line); + misc_FinishUserErrorReport(); + } +#endif + + /* If it is a big block, then it has to be + administrated in a special way + */ + if (Bytes >= memory__DYNMAXSIZE) { + unsigned int RealBigBlockSize; /* real block size including + padding,header + and debug marks */ + + /* This is what a big block looks like: + + -------------------------------------------------------------------- + | MEMORY_BIGBLOCKHEADERNODE | debug marks | char * | debug marks | + | previous and next big block |in debug mode| block |in debug mode| + -------------------------------------------------------------------- + */ + + + /* Calculate the real size of the big block, + from the size of administration information, + the size of debug marks and the requested block size + */ + + RealBigBlockSize = sizeof(MEMORY_BIGBLOCKHEADERNODE) + + memory_MARKSIZE + memory_CalculateRealBlockSize(Bytes); + + /* Check for violation of maximum allocation limit */ + if (memory_MAXMEM >= 0) { + /* there is a maximum allocation limit, + let´s see if there is enough left + */ + if ((unsigned int)memory_MAXMEM < RealBigBlockSize) { + /* if it is not print an error message and exit */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_Malloc:"); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Terminated by user given memory restriction,\n"); + misc_UserErrorReport("\n while trying to allocate %lu bytes.\n", + RealBigBlockSize); + misc_UserErrorReport("\n Maximum amount of memory"); + misc_UserErrorReport(" left for allocation is %l bytes.\n", + memory_MAXMEM); +#ifdef CHECK + misc_UserErrorReport("\n Error occurred in memory_Malloc"); + misc_UserErrorReport(" called from file %s at line %d.\n", + File, Line); +#endif + misc_FinishUserErrorReport(); + } + else + /* otherwise subtract the real block size + from the amount of memory available for + allocation + */ + memory_MAXMEM -= RealBigBlockSize; + } + + /* allocate a fresh block of memory via a call to malloc */ + NewMemory = (char *)malloc(RealBigBlockSize); + + /* Check if allocation was successful */ + if (NewMemory != NULL) { + + /* if it was, then administrate the fresh block: + insert it into the big block list. The list + is double linked for fast deletion + */ + + MEMORY_BIGBLOCKHEADER NewBigBlock; /* new block´s administration + information */ + + /* insert the fresh block as the first list element */ + NewBigBlock = (MEMORY_BIGBLOCKHEADER) NewMemory; + NewBigBlock->next = memory_BIGBLOCKS; + NewBigBlock->previous = NULL; + + /* if there are already elements in the big block list, + change the first element´s pointer to the previous block + to point to the fresh block´s administration information + */ + if (memory_BIGBLOCKS != NULL) { + memory_BIGBLOCKS->previous = NewBigBlock; + } + + /* reset the big block list pointer to point to the fresh block */ + memory_BIGBLOCKS = NewBigBlock; + + /* skip the administration information */ + NewMemory += sizeof(MEMORY_BIGBLOCKHEADERNODE); + +#ifdef CHECK + /* set the debug information address */ + NewInfo = (MEMORY_INFO) NewMemory; + + /* skip left debug mark */ + NewMemory += memory_OFFSET; +#endif + + /* add block´s real size to the total sum of allocated bytes */ + memory_NEWBYTES += RealBigBlockSize; + } + else { + /* NewMemory == NULL. + malloc could not allocate a memory block of required size, + so we print an error message and exit + */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_MallocIntern:"); + misc_UserErrorReport("\n Memory Error. Out of memory."); + misc_UserErrorReport("\n Failed to allocate %d bytes.\n", + RealBigBlockSize); +#ifdef CHECK + misc_UserErrorReport("\n Error occurred in memory_Malloc"); + misc_UserErrorReport(" called from file %s at line %d.\n", + File, Line); +#endif + misc_FinishUserErrorReport(); + } + } + else { + /* Bytes < memory__DYNMAXSIZE. + A memory request for a manageable size + */ + + /* Initialize the memory resource for the given size */ + Resource = memory_ARRAY[Bytes]; + + + /* Check if there are freed blocks of that size */ + if (*((int *)Resource->free) != EOF) { + + /* if that is the case, then use an already freed block */ + + NewMemory = (char *) Resource->free; + + /* update the free blocks list for that size */ + Resource->free = *((POINTER *)(NewMemory)); + + /* subtract block´s total size from the sum of freed bytes */ + memory_FREEDBYTES -= Resource->total_size; + +#ifdef CHECK + /* calculate the address of the block´s debug information */ + NewInfo = (MEMORY_INFO) ((char*) NewMemory - memory_OFFSET); + + /* Check if the block has been used after deallocation */ + memory_CheckPointer(NewMemory, Bytes); +#endif + } + else { + /* there are no already freed blocks of that size */ + + /* Check if there is enough space left on current page */ + if (Resource->next != Resource->end_of_page) { + + /* if that is the case, then use a fresh block from current page */ + NewMemory = (char *)Resource->next; + + /* update the pointer to the next usable block */ + Resource->next = NewMemory + Resource->total_size; + + /* add block´s total size to the sum of allocated bytes */ + memory_NEWBYTES += Resource->total_size; + +#ifdef CHECK + /* Check if the fresh block´s address is sane */ + if ((char *)NewMemory > (char *) Resource->end_of_page) { + /* if it is not, then we have detected an internal error + in the module itself. Oops! So we print an error message + and abort, hoping that the core dump will enable us to + trace the error back to its origin + */ + misc_StartErrorReport(); + misc_ErrorReport("\n In memory_Malloc:"); + misc_ErrorReport("\n Memory Error. Address overflow %d.",Bytes); + misc_ErrorReport("\n Error occurred in memory_Malloc"); + misc_ErrorReport(" called from file %s at line %d.\n", File, Line); + misc_FinishErrorReport(); + } + + /* if all is well, we initialize the pointer to fresh block´s + debug information + */ + NewInfo = (MEMORY_INFO)((char*) NewMemory - memory_OFFSET); +#endif + + } + else { + /* Check for violation of maximum allocation limit */ + if (memory_MAXMEM >=0) { + /* there is a maximum allocation limit, + let´s see if there is enough left + */ + if ((unsigned int)memory_MAXMEM < memory_PAGESIZE) { + /* if it is not, then print an error message and exit */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_Malloc:"); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Terminated by user given memory restriction.\n"); +#ifdef CHECK + misc_UserErrorReport("\n Error occurred in memory_Malloc"); + misc_UserErrorReport(" called from file %s at line %d.\n", + File, Line); +#endif + misc_FinishUserErrorReport(); + } + else { + /* otherwise subtract the page size from the limit */ + memory_MAXMEM -= memory_PAGESIZE; + } + } + + /* try to allocate a new page via malloc */ + NewMemory=(char *)malloc(memory_PAGESIZE); + + /* check if allocation was successful */ + if (NewMemory == NULL) { + /* if it wasn´t print an error message and exit */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_Malloc:"); + misc_UserErrorReport("\n Memory Error."); + misc_UserErrorReport(" Terminated, ran out of system memory.\n"); +#ifdef CHECK + misc_UserErrorReport("\n Error occurred in memory_Malloc"); + misc_UserErrorReport(" called from file %s at line %d.\n", + File, Line); +#endif + misc_FinishUserErrorReport(); + } + + /* otherwise administrate the fresh page, + i.e insert it as the first element of the + page list for the given size + */ + *((POINTER *)NewMemory) = Resource->page; + Resource->page = NewMemory; + + /* add block´s total size to the sum of allocated bytes */ + memory_NEWBYTES += Resource->total_size; + + /* set the end of page pointer for the fresh page */ + Resource->end_of_page = (char *) NewMemory + Resource->offset; + + /* skip the page list */ + NewMemory += sizeof(POINTER); + +#ifdef CHECK + /* set the debug information address */ + NewInfo = (MEMORY_INFO) NewMemory; + + /* skip the left debug mark */ + NewMemory += memory_OFFSET; +#endif + + /* update the pointer to the next usable block */ + Resource->next = NewMemory + Resource->total_size; + } + } + } + +#ifdef CHECK + /* Set block´s debug information */ + memory_SetInfo(NewInfo, File, Line, NULL, 0); + memory_SetBlockStatusAndSize(NewMemory, + memory_MAGICMALLOC, Bytes); + + /* delete all block´s usable bytes with a shredder value */ + memset(NewMemory, memory__FREESHREDDER, + memory_LookupRealBlockSize(Bytes)); +#endif + + return NewMemory; +} + +#endif + + + +#ifdef NO_MEMORY_MANAGEMENT + +POINTER memory_Calloc(unsigned int Elements, unsigned int Bytes) +{ + char *mem; /* pointer to memory block obtained from calloc */ + + /* Pass call through to compiler´s calloc */ + mem = (char *)calloc(Elements, Bytes); + + /* If calloc fails print an error message and exit */ + if (mem == NULL) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_Calloc:"); + misc_UserErrorReport("\n Memory Error. Out of memory.\n"); + misc_FinishUserErrorReport(); + } + + return mem; +} + +#else + +#ifdef CHECK +POINTER memory_CallocIntern(unsigned int Elements, unsigned int Bytes, + const char * File, unsigned short int Line) +#else +POINTER memory_Calloc(unsigned int Elements, unsigned int Bytes) +#endif +/******************************************************** + INPUT : The number of requested equally huge blocks, + and each block's size. + RETURNS: A pointer to a block of (Bytes * Elements) bytes. + SUMMARY: Allocates a memory block of requested length + filled with char value '\0'. +*********************************************************/ +{ + char * mem; /* pointer to memory block obtained from the module */ + + /* Allocate memory via our memory management */ +#ifdef CHECK + mem = (char *)memory_MallocIntern(Elements * Bytes, File, Line); +#else + mem = (char *)memory_Malloc(Elements * Bytes); +#endif + + /* If allocation was successful set all bytes to zero */ + if (mem != NULL) { + memset(mem,0, Elements * Bytes); + } + /* otherwise print an error message and exit */ + else { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_Calloc:"); + misc_UserErrorReport("\n Memory Error. Out of memory.\n"); +#ifdef CHECK + misc_UserErrorReport("\n Error occurred in memory_Calloc"); + misc_UserErrorReport(" called from file %s at line %d.\n", + File, Line); +#endif + misc_FinishUserErrorReport(); + } + + return mem; +} +#endif + +void memory_FreeAllMem(void) +/************************************************************** + INPUT : None. + RETURNS: None. + SUMMARY: Frees all memory allocated by calls to the module. +***************************************************************/ +{ + int i; + + /* delete all pages first by going through the memory_ARRAY. + This is slower than traversing the array memory_PAGES + directly, but is easier to implement correctly. Since + the only reasonable way to call memory_FreeAllMem is + before the program exits, a minimal performance penalty + should be acceptable + */ + + for (i = 1; i < memory__DYNMAXSIZE; i++) { + POINTER thispage, nextpage; + MEMORY_RESOURCE * Resource; + + Resource = memory_ARRAY[i]; + + thispage = Resource->page; + + if (*((int *)thispage) != EOF) { + do { + nextpage = *((POINTER *)thispage); + free(thispage); + thispage = nextpage; + } while (*((int *)thispage) != EOF); + + /* and reset the resource structure */ + Resource->page = &memory__EOF; + Resource->free = &memory__EOF; + Resource->next = &memory__EOF; + Resource->end_of_page = &memory__EOF; + } + } + + /* now delete all big blocks left */ + + if (memory_BIGBLOCKS != NULL) { + MEMORY_BIGBLOCKHEADER thisblock, nextblock; + + for (thisblock = memory_BIGBLOCKS; + thisblock != NULL; + thisblock = nextblock) { + nextblock = thisblock->next; + free(thisblock); + } + + /* and reset the list pointer */ + memory_BIGBLOCKS = NULL; + } +} + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * DEBUGGING INFORMATION * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +void memory_Print(void) +/************************************************************** + INPUT : None. + RETURNS: None. + SUMMARY: Prints module status information to stdout: + the fixed size of an internal memory page, the size + of debug marks for a block of memory, the size of + demanded and freed memory in kilobytes, remaining + memory in bytes and the number of allocated pages of + memory. +***************************************************************/ +{ +#ifndef NO_MEMORY_MANAGEMENT + /* Call memory_FPrint to print status information to stdout */ + memory_FPrint(stdout); +#endif +} + +void memory_FPrint(FILE* File) +/************************************************************** + INPUT : A file pointer. + RETURNS: None. + SUMMARY: Prints module status information to given File: + the fixed size of an internal memory page, the size + of debug marks for a block of memory, the size of + demanded and freed memory in kilobytes, remaining + memory in bytes and the number of allocated pages of + memory. +***************************************************************/ +{ +#ifndef NO_MEMORY_MANAGEMENT + int Pages; /* number of allocated pages */ + int i; + POINTER ActPage; /* current page in page list for a block size */ + + /* Calculate the total number of pages */ + Pages = 0; + for (i = 1; i < memory__DYNMAXSIZE; i+=memory__SHAREDPAGES) { + /* increase i by memory_SHAREDPAGES due to page sharing */ + ActPage = memory_ARRAY[i]->page; + + /* Traverse the page list */ + while (*((int *)ActPage) != EOF) { + Pages++; + ActPage = *((POINTER *)ActPage); + } + } + + /* Print status information */ + fputs("\n###\n", File); + fprintf(File,"### Pagesize: %d\n", + memory_PAGESIZE); + fprintf(File,"### Marksize: %d\n", + (int)memory_MARKSIZE); + fprintf(File,"### Memory demanded: %lu KBytes\n", + memory_NEWBYTES/memory__KILOBYTE); + fprintf(File,"### Memory freed: %lu KBytes\n", + memory_FREEDBYTES/memory__KILOBYTE); + fprintf(File,"### Memory remaining: %lu Bytes\n", + memory_NEWBYTES-memory_FREEDBYTES); + fprintf(File,"### Pages allocated: %d Pages\n", + Pages); + fputs("###\n", File); +#endif +} + +void memory_PrintAllocatedBlocks(unsigned int Size) +/************************************************************** + INPUT : Block size. + RETURNS: None. + SUMMARY: Prints addresses of allocated memory blocks with + given Size to stdout, if Size is less than + memory_DYNMAXSIZE. +***************************************************************/ +{ +#ifndef NO_MEMORY_MANAGEMENT + MEMORY_RESOURCE *Resource; /* current resource */ + + POINTER ActPage; /* current page */ + POINTER ActNext; /* next usable block on current page */ + POINTER ActEndOfPage; /* end of current page */ + + unsigned int BlockSize; /* current block size */ + +#ifdef CHECK + MEMORY_INFO Info; /* current block´s debug information */ +#endif + + /* Allocated blocks are administered + in two ways depending on their + size. If the size is less than + memory__DYNMAXSIZE the block is + allocated from the appropriate + page. Otherwise the block is + allocated directly via a call + to malloc or calloc. + + Thus we have two functions to + print the allocated blocks: + memory_PrintAllocatedBlocks and + memory_PrintAlocatedBigBlocks. + */ + + + /* Check if memory_PrintAllocatedBlocks has been called for + a legal block size + */ + + if (Size >= memory__DYNMAXSIZE) { + /* if that´s not the case print an error message and exit */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_PrintAllocatedBlocks:"); + misc_UserErrorReport("\n Parameter size is too big: %d.", + Size); + misc_UserErrorReport("\n Maximal allowed value is: %d.\n", + memory__DYNMAXSIZE); + misc_FinishUserErrorReport(); + } + else { + /* otherwise size is legal */ + + /* initialize the variables */ + Resource = memory_ARRAY[Size]; + ActPage = Resource->page; + ActNext = Resource->next; + ActEndOfPage = Resource->end_of_page; + BlockSize = Resource->total_size; + + /* Test if there were any requests made for blocks of that size */ + if (*((int *)ActPage) == EOF) { + /* Check if pointers are consistent */ + if (*((int *)ActNext) == EOF) { + /* If that is true, print that information to stdout */ + puts(" No request so far"); + } + else { + /* Otherwise print an error message and abort */ + misc_StartErrorReport(); + misc_ErrorReport("\n In memory_PrintAllocatedBlocks:"); + misc_ErrorReport("\n Memory Error. No Page entry but Next entry.\n"); + misc_FinishErrorReport(); + } + } + else { + /* We have received some requests for blocks of that size */ +#ifdef CHECK + + POINTER ActData; /* current block */ + + + /* Traverse through the page list for given block size */ + while (*((int *)ActPage) != EOF) { + + /* Initialize the variables */ + ActData = (char *)ActPage + sizeof(POINTER) + memory_OFFSET; + ActEndOfPage = (char *)ActPage + Resource->offset; + + /* Visit blocks on current page until the end of + page is reached, or an allocated block is found + */ + while (ActData != ActNext + && ActData != ActEndOfPage + && memory_GetBlockStatus(ActData) != memory_MAGICMALLOC) { + ActData = (char *)ActData + BlockSize; + } + + /* Check if there were any allocated blocks from current page */ + if (ActData == ActNext || ActData == ActEndOfPage) { + /* if that´s not the case print the information to stdout */ + printf("\n\n No memory allocated from page at address %p\n", ActPage); + } + else { + /* otherwise print address and origin of (de)allocation of + all allocated blocks on current page, starting + with the block just found + */ + fputs("\n\n Allocated but not freed: ", stdout); + do { + Info = (MEMORY_INFO) ((char *) ActData - memory_OFFSET); + if (memory_GetBlockStatus(ActData) == memory_MAGICMALLOC + && memory_GetBlockSize(ActData) == Size) { + printf("\n\t%p allocated in file %s at line %d ", + ActData, Info->mallocInFile, Info->mallocAtLine); + } + ActData = (char *)ActData + BlockSize; + } while (ActData != ActNext && ActData != ActEndOfPage); + } + + /* go to the next page in the page list for given block size */ + ActPage = *((POINTER *)ActPage); + } +#endif + } + } +#endif +} + +void memory_PrintFreedBlocks(unsigned int Size) +/************************************************************** + INPUT : Block size. + RETURNS: None. + SUMMARY: Prints addresses of freed memory blocks with given + Size to stdout, if Size is less than + memory_DYNMAXSIZE. +***************************************************************/ +{ +#ifndef NO_MEMORY_MANAGEMENT + POINTER ActFree; /* current block */ + +#ifdef CHECK + MEMORY_INFO Info; /* current block´s debug information */ +#endif + + /* since we don´t recycle blocks whose size is + greater or equal to memory__DYNMAXSIZE, + memory_PrintFreedBlocks is meaningless + for such block sizes. + */ + + /* test if given block size is legal */ + if (Size >= memory__DYNMAXSIZE) { + /* if that´s not the case print an error message and exit */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_PrintFreedBlocks."); + misc_UserErrorReport("\n Parameter Size is too big: %d.", + Size); + misc_UserErrorReport("\n Maximal allowed value is: %d.\n", + memory__DYNMAXSIZE); + misc_FinishUserErrorReport(); + } + else { + /* otherwise size is legal */ + + /* start at the first element of the free block list + for the given block size + */ + ActFree = memory_ARRAY[Size]->free; + + /* test if the free block list is empty */ + if (*((int *)ActFree) == EOF) { + /* if that´s true, print that information to stdout */ + puts("\n\n No freed memory"); + } + else { + /* otherwise traverse the list of freed blocks */ + + fputs("\n\n Free: ", stdout); + while (*((int *)ActFree) != EOF) { +#ifdef CHECK + /* in debug mode print current block´s address + and origin of (de)allocation + */ + + /* check if block´s size is correct */ + if ( memory_GetBlockSize(ActFree) == Size) { + /* if that´s true than print block´s information */ + Info = (MEMORY_INFO) ((char *) ActFree - memory_OFFSET); + printf("\n\t%p\tallocated in file %s at line %d", + ActFree, Info->mallocInFile, Info->mallocAtLine); + printf("\n\t\tfreed in file %s at line %d", + Info->freeInFile, Info->freeAtLine); + } + else { + /* otherwise if we are sharing pages among different + block sizes, the block is uncorrupted, despite not + matching assumed and real size. But if we are + not sharing pages then the block is probably corrupted, + so print an error message and exit + */ + + /* test if we are not in page sharing mode */ + if (memory__SHAREDPAGES == 1) { + /* if that´s true print an error message and exit */ + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In memory_PrintFreedBlocks:"); + misc_UserErrorReport("\n Memory Error. Memory block size mismatch."); + misc_UserErrorReport("\n Expected %d found %d for memory block at %p.\n", + Size, memory_GetBlockSize(ActFree), ActFree); + misc_UserErrorReport("\n Probably the memory block was corrupted.\n"); + misc_FinishUserErrorReport(); + } + } + +#endif + + /* go to the next free block in list */ + ActFree = *((POINTER *)ActFree); + } + } + } +#endif +} + + +void memory_PrintAllocatedBigBlocks(void) +/************************************************************** + INPUT : None. + RETURNS: None. + SUMMARY: Prints addresses of all allocated memory blocks, + that are greater than memory_DYNMAXSIZE to stdout. +***************************************************************/ +{ +#ifndef NO_MEMORY_MANAGEMENT +#ifdef CHECK + MEMORY_BIGBLOCKHEADER Ptr; /* current big block in list */ + MEMORY_INFO Info; /* block´s debug information */ + char * BlockStart; /* block´s start address */ + + /* start with the first block in the big block list */ + Ptr = memory_BIGBLOCKS; + + /* check whether big block list isn´t empty */ + if (Ptr != NULL) { + /* if that´s the case traverse through the list + and print each block´s address, size and + origin of (de)allocation information + */ + do { + BlockStart = (char *)Ptr + memory_OFFSET + + sizeof(MEMORY_BIGBLOCKHEADERNODE); + + Info = (MEMORY_INFO) (BlockStart - memory_OFFSET); + printf("\n\t%p %d bytes allocated in file %s at line %d ", + (void*)BlockStart, memory_GetBlockSize(BlockStart), + Info->mallocInFile, Info->mallocAtLine); + Ptr = Ptr->next; + } while (Ptr != NULL); + puts(""); + } + else { + /* otherwise there are no big blocks allocated */ + puts(" No request so far"); + } +#endif +#endif +} + +void memory_PrintDetailed(void) +/************************************************************** + INPUT : None. + RETURNS: None. + SUMMARY: Prints addresses of all pages, and allocated and freed + blocks on them. +***************************************************************/ +{ +#ifndef NO_MEMORY_MANAGEMENT + MEMORY_RESOURCE *Resource; /* current resource */ + + POINTER ActPage; /* current page */ + POINTER ActData; /* current block */ + POINTER ActEndOfPage; /* end of current page */ + unsigned int BlockSize; /* total size of a block of current size */ + unsigned int PageOffset; /* current page´s offset */ + + unsigned int i; + + + /* print end-of-memory pointer´s address */ + printf("\n\nEOF Pointer: %p\n", (void*)&memory__EOF); + + /* for all administrated block sizes print detailed information */ + for (i=1; i<memory__DYNMAXSIZE; i++) { + /* initialize variables for requested block size i */ + Resource = memory_ARRAY[i]; + ActPage = Resource->page; + ActData = Resource->next; + ActEndOfPage = Resource->end_of_page; + PageOffset = Resource->offset; + BlockSize = Resource->total_size; + + /* print requested block size, aligned block size + and block size including debug marks + */ + printf("\n\n Entry: %d aligned size: %d total size: %d\n", + i , Resource->aligned_size, BlockSize); + + /* Check if there were any requests for blocks of size i */ + if (*((int *)ActPage) == EOF) { + /* if that´s not the case check if memory management is consistent */ + if (*((int *)ActData) == EOF) { + /* if that´s true, print that no requests occurred to stdout */ + puts(" No request so far"); + } + else { + /* our memory management is no longer consistent, + so print an error message and abort. We hope that + the core dump will help us to find the bug + */ + misc_StartErrorReport(); + misc_ErrorReport("\n In memory_PrintDetailed:"); + misc_ErrorReport("\n Memory Error. No Page entry but Next entry.\n"); + misc_FinishErrorReport(); + } + } + else { + /* we have received requests for blocks of size i */ + + /* traverse the list of pages for size i */ + while (*((int *)ActPage) != EOF) { + /* print information about current page */ + printf("\n\n Page: %p Next Page: %p\n", + ActPage, *((POINTER *)ActPage)); + + /* initialize variables for current page */ + ActData = ((char *)ActPage + sizeof(POINTER) + memory_OFFSET); + ActEndOfPage = (char *)ActPage + PageOffset; + + /* print addresses of all blocks on current page */ + fputs(" Data: ", stdout); + while (ActData != ActEndOfPage) { + int column; + + fputs("\n\t\t", stdout); + for (column = 0; column < 6; column++) { + printf("%p ", ActData); + ActData = (char *)ActData + BlockSize; + if (ActData == ActEndOfPage) { + break; + } + } + } + + /* go to next page in list */ + ActPage = *((POINTER *)ActPage); + } + + /* print allocated and freed blocks of size i */ + memory_PrintAllocatedBlocks(i); + memory_PrintFreedBlocks(i); + } + } + +#ifdef CHECK + /* print allocated blocks of size >= memory_DYNMAXSIZE */ + printf("\n\n Allocated blocks of size >= %d\n", + memory__DYNMAXSIZE); + memory_PrintAllocatedBigBlocks(); +#endif +#endif +} + + +void memory_PrintLeaks(void) +/************************************************************** + INPUT : None. + RETURNS: None. + SUMMARY: Prints addresses of all allocated blocks. Should be + used at the end of a program before the call to + memory_FreeAllMem. +***************************************************************/ +{ +#ifndef NO_MEMORY_MANAGEMENT + POINTER ActPage; /* current page */ + POINTER ActNext; /* next fresh block on current page */ + POINTER ActEndOfPage; /* end of current page */ + MEMORY_RESOURCE *Resource; /* current resource */ + unsigned int Size; /* current size */ + unsigned int BlockSize; /* total block size */ + + /* Check if some memory is still allocated */ + if (memory_UsedBytes() != 0L) { + + /* If that´s true, print all allocated blocks */ + + /* Start with blocks administered by our memory management */ + for (Size = 1; Size < memory__DYNMAXSIZE; Size++) { + /* Initialize variables for current block size */ + Resource = memory_ARRAY[Size]; + ActPage = Resource->page; + ActNext = Resource->next; + ActEndOfPage = Resource->end_of_page; + BlockSize = Resource->total_size; + + /* Check if there were any requests for + memory blocks of that size */ + if (*((int *)ActPage) != EOF) { + + /* if that´s true, browse through all blocks on all pages + to find a block that is still allocated + */ +#ifdef CHECK + + POINTER ActData; + BOOL LeakFound; + + LeakFound = FALSE; + + while (*((int *)ActPage) != EOF) { + + /* search through all pages for a block that is still allocated */ + + ActData = (char *)ActPage + sizeof(POINTER) + memory_OFFSET; + ActEndOfPage = (char *)ActPage + Resource->offset; + + while (ActData != ActNext && ActData != ActEndOfPage) { + if (memory_GetBlockStatus(ActData) == memory_MAGICMALLOC) { + LeakFound = TRUE; + break; + } + ActData = (char *)ActData + BlockSize; + } + + if (LeakFound) { + + /* if we have found one, than call memory_PrintAllocatedBlocks + to print its address */ + + printf("\n\n Leaked blocks of size %d:", Size); + + memory_PrintAllocatedBlocks(Size); + putchar('\n'); + /* since memory_PrintAllocatedblocks prints + *all* allocated blocks of specific size, we can + break out of the while loop + */ + break; + } + else { + /* go to next page */ + ActPage = *((POINTER *)ActPage); + } + } + +#endif + + } + } + +#ifdef CHECK + /* Print allocated blocks of size >= memory__DYNMAXSIZE */ + if (memory_BIGBLOCKS != NULL) { + printf("\n\n Leaked blocks of size >= %d\n", + memory__DYNMAXSIZE); + memory_PrintAllocatedBigBlocks(); + putchar('\n'); + } +#endif + + } +#endif +} diff --git a/test/spass/memory.h b/test/spass/memory.h new file mode 100644 index 0000000000000000000000000000000000000000..d0edac187bcc8601aaf2a3ff393a0f5e2986ee71 --- /dev/null +++ b/test/spass/memory.h @@ -0,0 +1,478 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * DYNAMIC MEMORY MANAGEMENT MODULE * */ +/* * * */ +/* * $Module: MEMORY * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + + +#ifndef _MEMORY_ +#define _MEMORY_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "misc.h" + +/**************************************************************/ +/* Data structures and constants */ +/**************************************************************/ + +#ifndef memory__DYNMAXSIZE +#define memory__DYNMAXSIZE 1024 /* At most blocks of size memory__DYNMAXSIZE + bytes are administrated by the + module, larger requests are + directly mapped to system calls */ +#endif + +#ifndef memory__SHAREDPAGES +#define memory__SHAREDPAGES 1 /* Number of block sizes sharing an allocated + page. By setting memory__SHAREDPAGES to 4, + the module would administrate requests + for 1, 2, 3 and 4 bytes on the same set of + pages, requests for 5, 6, 7 and 8 on another + one, etc. By default every block size has + its own set of pages */ +#endif + +#ifndef memory__FREESHREDDER +#define memory__FREESHREDDER 'S' /* The decimal number 83, which can also be + read as 53 hexadecimal, or the character + 'S' in ASCII code */ +#endif + +#define memory__KILOBYTE 1024 + +#ifndef memory__DEFAULTPAGESIZE +#define memory__DEFAULTPAGESIZE (8 * memory__KILOBYTE) + /* Used to set the default size of a page. + If the default page size is too small to + contain two objects of size memory__DYNMAXSIZE + the default page size is automatically + increased by the function memory_Init */ +#endif + +#ifndef memory__UNLIMITED +#define memory__UNLIMITED (-1) + /* Used to set the maximal amount of memory + available for the memory module to + "unlimited" when calling memory_Init. */ +#endif + +typedef struct MEMORY_RESOURCEHELP { + POINTER free; /* pointer to the next free block in list */ + POINTER next; /* pointer to the next fresh block */ + POINTER page; /* pointer to head of page list */ + POINTER end_of_page; /* pointer to the end of current page */ + int total_size; /* total block size inc. debug marks */ + int aligned_size; /* block size without debug marks */ + int offset; /* offset of last usable block on page */ +} MEMORY_RESOURCE; + +extern MEMORY_RESOURCE * memory_ARRAY[]; + +#if defined(CHECK) +typedef struct MEMORY_INFOHELP { + const char * mallocInFile; /* origin of allocation request: file */ + const char * freeInFile; /* origin of deallocation request: file */ + unsigned short int mallocAtLine; /* origin of allocation request: line */ + unsigned short int freeAtLine; /* origin of deallocation request: line */ +} MEMORY_INFONODE, * MEMORY_INFO; + +#endif + +typedef struct MEMORY_BIGBLOCKHEADERHELP { + struct MEMORY_BIGBLOCKHEADERHELP * previous, * next; +} MEMORY_BIGBLOCKHEADERNODE, * MEMORY_BIGBLOCKHEADER; + +extern long memory_MAXMEM; + +extern unsigned long memory_NEWBYTES; +extern unsigned long memory_FREEDBYTES; + +extern const unsigned int memory_MAGICMALLOC; +extern const unsigned int memory_MAGICFREE; + +extern const unsigned int memory_ALIGN; + +extern MEMORY_BIGBLOCKHEADER memory_BIGBLOCKS; + +/**************************************************************/ +/* Debug Information */ +/**************************************************************/ + +extern unsigned int memory_MARKSIZE; +extern unsigned int memory_OFFSET; + +/**************************************************************/ +/* Check Functions */ +/**************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef CHECK +void memory_CheckFree(POINTER Freepointer, unsigned int Size, unsigned int RealBlockSize, const char * File, unsigned short int Line); +#endif /* CHECK */ + +#ifdef __cplusplus +} +#endif + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + + +static __inline__ unsigned int memory_CalculateRealBlockSize(unsigned int + BlockSize) +/********************************************************** + INPUT : Size of a block of memory. + RETURNS: its real size. + SUMMARY: Calculates the size of a memory block, + including padding due to memory alignment and + page sharing +**********************************************************/ +{ + unsigned int RealSize; + + RealSize = BlockSize; + + if (RealSize % memory__SHAREDPAGES) { + RealSize += memory__SHAREDPAGES - (RealSize % memory__SHAREDPAGES); + } + + if (RealSize % memory_ALIGN) { + RealSize += memory_ALIGN - (RealSize % memory_ALIGN); + } + + return RealSize; + +} + +static __inline__ unsigned int memory_LookupRealBlockSize(unsigned int + BlockSize) +/********************************************************** + INPUT : Size of a block of memory. + RETURNS: its real size. + SUMMARY: Returns the size of a memory block, + including padding due to memory alignment and + page sharing. +**********************************************************/ +{ + + unsigned int RealSize; + + if (BlockSize < memory__DYNMAXSIZE) { + RealSize = memory_ARRAY[BlockSize]->aligned_size; + } + else { + RealSize = memory_CalculateRealBlockSize(BlockSize); + } + + return RealSize; + +} + +#ifdef CHECK +static __inline__ void memory_SetBlockStatusAndSize(POINTER Mem, + unsigned int Status, + unsigned int Size) +/********************************************************** + INPUT : a pointer to a block of memory, its status + (memory_MAGICMALLOC or memory_MAGICFREE), and + size. + RETURNS: None. + SUMMARY: Sets a status flag (memory_MAGICMALLOC or + memory_MAGICFREE) and block size. +**********************************************************/ +{ + *((int *)Mem - 1) = Size; + *((int *)((char *)Mem + memory_LookupRealBlockSize(Size))) = Status; +} + +static __inline__ unsigned int memory_GetBlockSize(POINTER Mem) +/********************************************************** + INPUT : A pointer to a block of memory. + RETURNS: its size. + SUMMARY: Returns the size of a memory block. +**********************************************************/ +{ + return *((int *)Mem - 1); +} + +static __inline__ unsigned int memory_GetRealBlockSize(POINTER Mem) +/********************************************************** + INPUT : A pointer to a block of memory. + RETURNS: its real size. + SUMMARY: Returns the real size of a memory block, + including padding bytes. +**********************************************************/ +{ + return memory_LookupRealBlockSize(memory_GetBlockSize(Mem)); +} + +static __inline__ unsigned int memory_GetBlockStatus(POINTER Mem) +/********************************************************** + INPUT : A pointer to a block of memory. + RETURNS: its status. + SUMMARY: Returns the status of a memory block. +**********************************************************/ +{ + unsigned int Size; + + Size = memory_GetBlockSize(Mem); + + return *((int *)((char *)Mem + memory_LookupRealBlockSize(Size))); +} + +static __inline__ void memory_SetInfo(MEMORY_INFO Info, + const char * MallocInFile, + unsigned short int MallocAtLine, + const char * FreeInFile, + unsigned short int FreeAtLine) +/********************************************************** + INPUT : a memory info structure, strings for files where + the block was allocated and freed, and short + integers for the corresponding lines. + RETURNS: None. + SUMMARY: Sets the debugging information for a memory block +**********************************************************/ +{ + if (!Info) { + misc_StartErrorReport(); + misc_ErrorReport("\n In memory_SetInfo:"); + misc_ErrorReport("\n Memory Error. Info is a NULL pointer.\n"); + misc_FinishErrorReport(); + } + + Info->mallocAtLine = MallocAtLine; + Info->mallocInFile = MallocInFile; + Info->freeAtLine = FreeAtLine; + Info->freeInFile = FreeInFile; +} +#endif + +static __inline__ unsigned long memory_DemandedBytes(void) +/********************************************************** + INPUT : Nothing. + RETURNS: Maximum number of bytes allocated at the same + time by the module. + SUMMARY: Returns maximum number of allocated bytes at the + same time. +**********************************************************/ +{ + return memory_NEWBYTES; +} + + +static __inline__ unsigned long memory_UsedBytes(void) +/********************************************************** + INPUT : Nothing. + RETURNS: Number of bytes currently in use by your program. + SUMMARY: Returns number of bytes currently allocated. +**********************************************************/ +{ + return memory_NEWBYTES-memory_FREEDBYTES; +} + +#ifdef NO_MEMORY_MANAGEMENT + +static __inline__ void memory_Free(POINTER Freepointer, unsigned int Size) +{ + free((char*)Freepointer); +} + +#else + +#ifdef CHECK +static __inline__ void memory_FreeIntern(POINTER Freepointer, + unsigned int Size, + const char * File, + unsigned short int Line) +#else +static __inline__ void memory_Free(POINTER Freepointer, unsigned int Size) +#endif +/********************************************************** + INPUT : Pointer to the block of memory to be freed, + and the block's size + RETURNS: Nothing. + SUMMARY: Frees a block of memory for reallocation. + This function performs correctness checks + in debugging mode. +**********************************************************/ +{ + unsigned int RealBlockSize; /* block´s alignment correct size */ + + RealBlockSize = memory_LookupRealBlockSize(Size); + +#ifdef CHECK + memory_CheckFree(Freepointer, Size, RealBlockSize, File, Line); +#endif + + + /* Check if current block is a big block */ + if (Size >= memory__DYNMAXSIZE) { + /* if that´s true, remove it from the double linked big block list */ + MEMORY_BIGBLOCKHEADER BigBlockHeader; + + BigBlockHeader = + (MEMORY_BIGBLOCKHEADER) ((char *) Freepointer - memory_OFFSET + - sizeof(MEMORY_BIGBLOCKHEADERNODE)); + + /* Check if current big block is the first block in the list */ + if (BigBlockHeader->previous != NULL) { + /* if that´s not true, set previous block´s successor + to current block´s successor + */ + BigBlockHeader->previous->next = BigBlockHeader->next; + } + else { + /* otherwise set the first block in the big blocks list + to current block´s successor + */ + memory_BIGBLOCKS = BigBlockHeader->next; + } + + /* Check if current block is the last block in the list */ + if (BigBlockHeader->next != NULL) { + /* if that´s not true, set next block´ predecessor to + current block´s predecessor + */ + BigBlockHeader->next->previous = BigBlockHeader->previous; + } + + /* Adapt total number of freed bytes + and number of bytes available for allocation + accordingly + */ + memory_FREEDBYTES += RealBlockSize + memory_MARKSIZE + + sizeof(MEMORY_BIGBLOCKHEADERNODE); + + if (memory_MAXMEM >= 0) { + memory_MAXMEM += RealBlockSize + memory_MARKSIZE + + sizeof(MEMORY_BIGBLOCKHEADERNODE); + } + + /* pass the call though to free() with correct pointer value */ +#ifdef CHECK + free((char *)Freepointer - memory_OFFSET + - sizeof(MEMORY_BIGBLOCKHEADERNODE)); +#else + free((char*) Freepointer - sizeof(MEMORY_BIGBLOCKHEADERNODE)); +#endif + } + else { + /* current block is not a big block */ + /* Adapt number of allocated bytes + and the freed blocks list accordingly + */ + memory_FREEDBYTES += memory_ARRAY[Size]->total_size; + *(POINTER *)Freepointer = memory_ARRAY[Size]->free; + memory_ARRAY[Size]->free = Freepointer; + } + +} + +#endif + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + + +void memory_Init(long); +void memory_Restrict(long); + +void memory_Print(void); +void memory_FPrint(FILE*); + +void memory_PrintLeaks(void); +void memory_PrintDetailed(void); +void memory_PrintAllocatedBlocks(unsigned int Size); +void memory_PrintFreedBlocks(unsigned int Size); +void memory_PrintAllocatedBigBlocks(void); + +void memory_FreeAllMem(void); + +#ifdef __cplusplus +} +#endif + +#if defined(CHECK) && !defined(NO_MEMORY_MANAGEMENT) +/* declare drop-in debug versions memory functions */ +#ifdef __cplusplus +extern "C" { +#endif +POINTER memory_MallocIntern(unsigned int, const char *, unsigned short int); +POINTER memory_CallocIntern(unsigned int, + unsigned int, + const char *, + unsigned short int); +#ifdef __cplusplus +} +#endif +#define memory_Malloc(Size) memory_MallocIntern((Size), __FILE__, __LINE__) +#define memory_Calloc(Elements, Size) \ +memory_CallocIntern((Elements), (Size), __FILE__, __LINE__) +#define memory_Free(Pointer, Size) \ +memory_FreeIntern((Pointer), (Size), __FILE__, __LINE__) +#else +#ifdef __cplusplus +extern "C" { +#endif +POINTER memory_Malloc(unsigned int); +POINTER memory_Calloc(unsigned int, unsigned int); +#ifdef __cplusplus +} +#endif +#endif + +#endif diff --git a/test/spass/misc.c b/test/spass/misc.c new file mode 100644 index 0000000000000000000000000000000000000000..3a63396d77accb05f4ac8cbda2f81ea4ff3094ea --- /dev/null +++ b/test/spass/misc.c @@ -0,0 +1,147 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * MISCELLANEOUS * */ +/* * * */ +/* * $Module: MISC * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "misc.h" + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +#if 0 +void misc_ErrorReport(const char * Format, ...) +{ + va_list args; + va_start(args,Format); + vfprintf(misc_ERROROUT,Format,args); + va_end(args); +} + +void misc_UserErrorReport(const char * Format, ...) +{ + va_list args; + va_start(args,Format); + vfprintf(misc_USERERROROUT,Format,args); + va_end(args); +} +#endif + +void misc_DumpCoreOut(const char* String) +/************************************************************** + INPUT: A string. + RETURNS: Nothing. + EFFECT: Prints <String> and then dumps a core. +***************************************************************/ +{ + fprintf(stderr, "\n %s \n", String); + misc_DumpCore(); +} + + + +int misc_ReturnValue(void) +{ + return 0; +} + + +int misc_Max(int a, int b) +{ + if (a > b) + return a; + else + return b; +} + +FILE* misc_OpenFile(const char* Name, const char* Mode) +/************************************************************** + INPUT: The name of a file and a string containing the mode + for opening the file (see fopen(3)). + Examples for Mode are "r" for reading and "w" for writing. + RETURNS: The FILE pointer, if the file was successfully opened. + EFFECT: If it wasn't possible to open the file with the + requested mode, an error message is printed and the + program exits. +***************************************************************/ +{ + FILE* File; + + File = fopen(Name,Mode); + + if (File == (FILE*)NULL) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n\tError in opening file %s for %s !\n\n", Name, + (Mode[0] == 'r' ? "reading" : + (Mode[0] == 'w' ? "writing" : "i/o operations"))); + misc_FinishUserErrorReport(); + } + + return File; +} + +void misc_CloseFile(FILE* File, const char* Name) +/************************************************************** + INPUT: A FILE and its name. + RETURNS: Nothing. + EFFECT: Closes the file. If an error occurs, a message is + printed and the program exits. +***************************************************************/ +{ + int Result; + + Result = fclose(File); + + if (Result != 0) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n\tError in closing file %s !\n\n", Name); + misc_FinishUserErrorReport(); + } +} + diff --git a/test/spass/misc.h b/test/spass/misc.h new file mode 100644 index 0000000000000000000000000000000000000000..69d929d1be7ff937898447a6250652f5f3077165 --- /dev/null +++ b/test/spass/misc.h @@ -0,0 +1,161 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * MISCELLANEOUS * */ +/* * * */ +/* * $Module: MISC * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _MISC_ +#define _MISC_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#define __USE_FIXED_PROTOTYPES__ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <limits.h> +#include <stdarg.h> + +/**************************************************************/ +/* More basic types and macros */ +/**************************************************************/ + +#if defined(TRUE) +#undef TRUE +#endif + +#if defined(FALSE) +#undef FALSE +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + + +#define misc_ERROROUT stderr +#define misc_USERERROROUT stderr + +typedef enum { FALSE=0, TRUE=1 } BOOL; + +#define misc_VERSION "V 2.1" + + +typedef void* POINTER; +typedef unsigned int NAT; + +/* Limits for EARL data types */ +#define NAT_MAX UINT_MAX + + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +#define misc_ReportStandardErrorMessage(Stream) fputs("\n Please report this error via email to spass@mpi-sb.mpg.de including\n the SPASS version, input problem, options, operating system.\n",Stream) + +static __inline__ void misc_Error(void) +{ + fflush(misc_USERERROROUT); + fflush(stdout); + fflush(stderr); + exit(EXIT_FAILURE); +} + + +static __inline__ void misc_DumpCore(void) +{ + fputs("\n\n", misc_ERROROUT); + fflush(misc_ERROROUT); + fflush(stdout); + fflush(stderr); + abort(); +} + + +static __inline__ void misc_PrintChar(NAT Number, char Character) +{ + NAT Counter; + for (Counter = 1; Counter <= Number; Counter++) + putchar(Character); +} + +static __inline__ BOOL misc_SmallerThan(int i, int j) +{ + return (BOOL)(i < j); +} + +#define misc_StartErrorReport() { fflush(stdout); fprintf(misc_ERROROUT,"\n\tError in file %s at line %d\n",__FILE__,__LINE__); } +#define misc_FinishErrorReport() { misc_ReportStandardErrorMessage(misc_ERROROUT); misc_DumpCore(); } + +#define misc_StartUserErrorReport() fflush(stdout) +#define misc_FinishUserErrorReport() misc_Error() + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif +#define misc_ErrorReport(...) fprintf(misc_ERROROUT, __VA_ARGS__) +#define misc_UserErrorReport(...) fprintf(misc_USERERROROUT, __VA_ARGS__) + +void misc_DumpCoreOut(const char*); +int misc_ReturnValue(void); +int misc_Max(int, int); + +FILE* misc_OpenFile(const char*, const char*); +void misc_CloseFile(FILE*, const char*); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/spass/options.c b/test/spass/options.c new file mode 100644 index 0000000000000000000000000000000000000000..c9e84b5cc22a935c4ab66a9afd3e3329da3b47e9 --- /dev/null +++ b/test/spass/options.c @@ -0,0 +1,1889 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SPASS OPTIONS HANDLING * */ +/* * * */ +/* * $Module: OPTIONS * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* $Revision: 35442 $ * */ +/* $State$ * */ +/* $Date: 2007-03-28 17:24:40 -0700 (Wed, 28 Mar 2007) $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/* $RCSfile$ */ + + +/*************************************************************** + + COPYRIGHT NOTICE: + + This file contains code that + has been copied with minor modifications + from the 'getopt' module in the + GNU gcc library 2.0. The copyright for + this code is claimed by + + Copyright 1991 Regents of the + University of California. + All rights reserved. + + The copying and modification of the + original code is in accordance + with the copyright conditions for the + GNU gcc library, which are listed below. + + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + All advertising materials mentioning features or use of this software + must display the following acknowledgement: + + This product includes software developed by the University of + California, Berkeley and its contributors. + + Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + This software is provided by the regents and contributors ``as is'' and + any express or implied warranties, including, but not limited to, the + implied warranties of merchantability and fitness for a particular purpose + are disclaimed. in no event shall the regents or contributors be liable + for any direct, indirect, incidental, special, exemplary, or consequential + damages (including, but not limited to, procurement of substitute goods + or services; loss of use, data, or profits; or business interruption) + however caused and on any theory of liability, whether in contract, strict + liability, or tort (including negligence or otherwise) arising in any way + out of the use of this software, even if advised of the possibility of + such damage. + +************************************************************************ +************************************************************************/ + +#include "options.h" +#include "stringsx.h" + +/**************************************************************/ +/* Local variables and types */ +/**************************************************************/ + +/* all option declarations. List with *DECL entries */ +static LIST opts_DECLARATIONS; + +/* list of <option id/value string> tupels that holds all parameters and their values */ +static LIST opts_PARAMETERS; + +static OPTID opts_IdNextAvailable; + + +/**************************************************************/ +/* Forwarding functions */ +/**************************************************************/ + +static void opts_AddParam(OPTID, const char*); +static BOOL opts_AddParamCheck(OPTID, const char*); + +static int opts_GetOptLongOnly(int, const char* [], const char*, + const struct OPTION *, int *); + +static OPTDECL* opts_DeclGetById(OPTID); +static void opts_PrintDeclarationList(LIST); +static OPTID opts_IdNext(OPTID); +static OPTID opts_IdEqual(OPTID, OPTID); + + +/************************************************************* + Local variables and types from the former getopt module code. +**************************************************************/ + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `opts_Ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `opts_Ind' != ARGC. */ + +static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } opts_Ordering; + +/* Value of POSIXLY_CORRECT environment variable. */ +static char *opts_PosixlyCorrect; + +static int opts_FirstNonOpt; +static int opts_LastNonOpt; + +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +static int opts_NonOptionFlagslen; + + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `opts_Ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +static const char *opts_Arg = NULL; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +static int opts_Ind = 1; + +/* Formerly, initialization of getopt depended on opts_Ind==0, which + causes problems with re-calling getopt as programs generally don't + know that. */ + +static int opts_GetOptInitialized = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static const char *opts_NextChar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +static int opts_Err = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +static int opts_Opt = '?'; + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +OPTID opts_IdFirst(void) +/************************************************************** + INPUT: None. + RETURNS: First option id that is used in option declarations. +***************************************************************/ +{ + return opts_IDFIRST; +} + +static __inline__ OPTID opts_IdNull(void) +/************************************************************** + INPUT: None. + RETURNS: An NULL id that is never used for option declarations + (used as indicator for errors etc.). +***************************************************************/ +{ + return -1; +} + +BOOL opts_IdIsNull(OPTID Id) +/************************************************************** + INPUT: An option id. + RETURNS: TRUE iff it is the NULL id. +***************************************************************/ +{ + return opts_IdEqual(opts_IdNull(), Id); +} + +static __inline__ void opts_IdIncAvailable(void) +/************************************************************** + INPUT: None. + RETURNS: Nothing. + EFFECTS: Increases the counter for next available id. +***************************************************************/ +{ + opts_IdNextAvailable = opts_IdNext(opts_IdNextAvailable); +} + +static __inline__ OPTID opts_IdGetNextAvailable(void) +/************************************************************** + INPUT: None. + RETURNS: Nothing. + EFFECTS: Returns the counter for the next available id. +***************************************************************/ +{ + return opts_IdNextAvailable; +} + +static __inline__ void opts_DeclSetClName(OPTDECL* D, char* s) +/************************************************************** + INPUT: An option declaration, a string. + RETURNS: Nothing. + EFFECTS: Sets the command line name of <D> to <s>. +***************************************************************/ +{ + D->clname = s; +} + +static __inline__ char* opts_DeclGetClName(OPTDECL* D) +/************************************************************** + INPUT: An option declaration. + RETURNS: The command line name in <D>. +***************************************************************/ +{ + return D->clname; +} + + +static __inline__ void opts_DeclSetType(OPTDECL* D, OPTTYPE type) +/************************************************************** + INPUT: An option declaration and an option type. + RETURNS: Nothing. + EFFECTS: Set the option type of <D> to <type>. +***************************************************************/ +{ + D->type = type; +} + +static __inline__ OPTTYPE opts_DeclGetType(OPTDECL* D) +/************************************************************** + INPUT: An option declaration. + RETURNS: The option type of <D>. +***************************************************************/ +{ + return D->type; +} + +static __inline__ BOOL opts_DeclIsShortOpt(OPTDECL* D) +/************************************************************** + INPUT: An option declaration. + RETURNS: TRUE iff <D> is a declaration of a short option + (with a single character command line name). +***************************************************************/ +{ + return (strlen(opts_DeclGetClName(D)) == 1); +} + +static __inline__ BOOL opts_DeclHasOptArg(OPTDECL* D) +/************************************************************** + INPUT: An option declaration. + RETURNS: TRUE iff <D> is a declaration of an option + with an optional argument. +***************************************************************/ +{ + return (opts_DeclGetType(D) == opts_OPTARGTYPE); +} + +static __inline__ BOOL opts_DeclHasReqArg(OPTDECL* D) +/************************************************************** + INPUT: An option declaration. + RETURNS: TRUE iff <D> is a declaration of an option + with a required argument. +***************************************************************/ +{ + return (opts_DeclGetType(D) == opts_REQARGTYPE); +} + +static __inline__ BOOL opts_DeclHasNoArg(OPTDECL* D) +/************************************************************** + INPUT: An option declaration. + RETURNS: TRUE iff <D> is a declaration of an option + with a required argument. +***************************************************************/ +{ + return (opts_DeclGetType(D) == opts_NOARGTYPE ); + +} + +OPTID opts_Declare(const char* ClName, OPTTYPE OptType) +/* declare option by name/shorthand/argtype (command line name) */ +/************************************************************** + INPUT: An option name (its command line name) and an option type. + RETURNS: An option id. + EFFECTS: Appends the declaration to opts_DECLARATIONS. +***************************************************************/ +{ + OPTDECL* D; + OPTID Id; + + if (!opts_IdIsNull(opts_Id(ClName))) { + misc_StartErrorReport(); + misc_ErrorReport("internal error: option with command line name '%s' redeclared.\n", ClName); + misc_FinishErrorReport(); } + + D = memory_Malloc(sizeof(OPTDECL)); + + opts_DeclSetClName(D, string_StringCopy(ClName)); + opts_DeclSetType(D,OptType); + + opts_DECLARATIONS = list_Nconc(opts_DECLARATIONS, list_List(D)); + + Id = opts_IdGetNextAvailable(); + opts_IdIncAvailable(); + + return Id; +} + +OPTID opts_DeclareVector(OPTDECL Decls[]) +/************************************************************** + INPUT: An option declaration vector, which must have + a NULL pointer in the clname field of the last + declaration. + RETURNS: The id of the last declared option. + EFFECTS: All option declarations are added to opts_DECLARATIONS. +***************************************************************/ +{ + int i; + + i = 0; + while (strlen(opts_DeclGetClName(&Decls[i])) != 0) { + opts_Declare(opts_DeclGetClName(&Decls[i]), opts_DeclGetType(&Decls[i])); + i++; + } + return opts_IdGetNextAvailable(); +} + +static char* opts_TranslateShortOptDeclarations(void) +/************************************************************** + INPUT: None. + RETURNS: A string that codes the option declarations in + opts_DECLARATIONS in a string as required by the + GNU getopt module. +***************************************************************/ +{ + LIST Scan; + char* ShortDecl; + OPTDECL* Decl; + + ShortDecl = string_StringCopy("\0"); + + Scan = opts_DECLARATIONS; + + while (Scan) { + /* option is short iff: + - it was declared with a one letter command line name or + - it has an abbreviation + */ + Decl = (OPTDECL*)list_Car(Scan); + + if (opts_DeclIsShortOpt(Decl)) { + ShortDecl = string_Nconc(ShortDecl, string_StringCopy(opts_DeclGetClName(Decl))); + + /* + add colon if optional or required argument + */ + if (opts_DeclHasReqArg(Decl)||opts_DeclHasOptArg(Decl)) + ShortDecl = string_Nconc(ShortDecl, string_StringCopy(":")); + } + Scan = list_Cdr(Scan); + } + + /* add leading colon if any short options exist */ + if (strlen(ShortDecl) != 0) { + ShortDecl = string_Nconc(string_StringCopy(":"),ShortDecl); } + + return ShortDecl; +} + +static LIST opts_GetLongOptDeclarations(void) +/************************************************************** + INPUT: None. + RETURNS: A list of all 'long option' (with command line name + length > 1) declarations in opts_DECLARATIONS. + EFFECTS: Allocates list. +***************************************************************/ +{ + LIST Scan, Long; + OPTDECL* Decl; + + Scan = opts_DECLARATIONS; + Long = list_Nil(); + + while (!list_Empty(Scan)) { + Decl = list_Car(Scan); + + if (!opts_DeclIsShortOpt(Decl)) { + Long = list_Cons(Decl, Long); + } + Scan = list_Cdr(Scan); + } + return Long; +} + +static __inline__ struct OPTION *opts_GetLongOptsArray(int OptNum) +/************************************************************** + INPUT: An option number . + RETURNS: An array with <OptNum> entries for OPTION structs + as needed by GetOptLongOnly. + EFFECTS: Allocates array. +***************************************************************/ +{ + return (struct OPTION*)memory_Malloc(sizeof(struct OPTION)*(OptNum+1)); +} + +static void opts_FreeLongOptsArray(struct OPTION *LongOpts) +/************************************************************** + INPUT: An array with entries for OPTION structs + RETURNS: Nothing + EFFECTS: Frees array. End of array is marked by a struct OPTION + entry with a NULL pointer in the 'name' field. +***************************************************************/ +{ + int i; + + for (i=0; LongOpts[i].name != 0; i++) /* empty */; + + memory_Free(LongOpts, (i+1)*sizeof(struct OPTION)); +} + + +static struct OPTION* opts_TranslateLongOptDeclarations(void) +/************************************************************** + INPUT : None + RETURNS: Translates opts_DECLARATIONS into an array as needed + by GetLongOptOnly + EFFECTS: Allocates the array +***************************************************************/ +{ + LIST Scan; + LIST LongDeclarations; + int OptNum; + int OptCnt; + struct OPTION* LongOpts; + + OPTDECL* Decl; + + LongDeclarations = opts_GetLongOptDeclarations(); + OptNum = list_Length(LongDeclarations); + LongOpts = opts_GetLongOptsArray(OptNum); + OptCnt = 0; + Scan = LongDeclarations; + + while (!list_Empty(Scan)) { + Decl = list_Car(Scan); + + LongOpts[OptCnt].name = opts_DeclGetClName(Decl); + + if (opts_DeclHasOptArg(Decl)) + LongOpts[OptCnt].has_arg = 2; + else if (opts_DeclHasReqArg(Decl)) + LongOpts[OptCnt].has_arg = 1; + else + LongOpts[OptCnt].has_arg = 0; + LongOpts[OptCnt].flag = 0; + LongOpts[OptCnt].val = 0; + + Scan = list_Cdr(Scan); + OptCnt++; + } + /* set last field to 0 as required by getopt */ + LongOpts[OptCnt].name = NULL; + LongOpts[OptCnt].has_arg = 0; + LongOpts[OptCnt].flag = 0; + LongOpts[OptCnt].val = 0; + + list_Delete(LongDeclarations); + + return LongOpts; +} + + +static void opts_PrintLongOpts(struct OPTION *LongOpts) +/************************************************************** + INPUT: An array with OPTIONS structs + RETURNS: Nothing + EFFECTS: Prints contents of array +***************************************************************/ +{ + int i; + + if (LongOpts == NULL) { + puts("\nPrintLongOpts gets NULL pointer."); + return; + } + puts("\nLong options array:"); + + i = 0; + while (LongOpts[i].name != NULL) { + printf("\nentry %d:\n",i); + + printf("Name: %s\n", LongOpts[i].name); + printf("has_arg: %d\n", LongOpts[i].has_arg); + printf("flag; : %d\n", (int)LongOpts[i].flag); + printf("val : %d\n", LongOpts[i].val); + i++; + } +} + +static __inline__ OPTID opts_IdCmp(OPTID Id1, OPTID Id2) +/************************************************************** + INPUT: Two option ids + RETURNS: Analogously to strcmp: + '0' if Id1 == Id2 + '<0' if Id1 < Id2 + '>0' if Id1 > Id2 +***************************************************************/ +{ + return (Id1-Id2); +} + +static OPTID opts_IdEqual(OPTID Id1, OPTID Id2) +/************************************************************** + INPUT: Two options ids + RETURNS: TRUE if they are equal +***************************************************************/ +{ + return (opts_IdCmp(Id1,Id2) == 0); +} + +static OPTID opts_IdNext(OPTID Id) +/************************************************************** + INPUT: An option id + RETURNS: The next option id in the ordering +***************************************************************/ +{ + return (Id+1); +} + + +const char* opts_ClName(OPTID Id) +/************************************************************** + INPUT: An option id + RETURNS: Its command line name +***************************************************************/ +{ + OPTDECL* Decl; + + Decl = opts_DeclGetById(Id); + return opts_DeclGetClName(Decl); +} + +OPTID opts_Id(const char* ClName) +/************************************************************** + INPUT: The command line name of an option + RETURNS: The corresponding id of the option, + the NULL id if no option with <ClName> exist. +***************************************************************/ +{ + LIST Scan; + BOOL found; + OPTID Id; + + Scan = opts_DECLARATIONS; + Id = opts_IdFirst(); + found = FALSE; + + while (!found && !list_Empty(Scan)) { + if (string_Equal(opts_DeclGetClName(list_Car(Scan)), ClName)) { + found = TRUE; + } else { + Scan = list_Cdr(Scan); + Id = opts_IdNext(Id); + } + } + if (!found) + Id = opts_IdNull(); + return Id; +} + +static OPTID opts_ShortOptId(char c) +/************************************************************** + INPUT: A character + RETURNS: The id of a short option <c>, NULL id + if it does not exist. +***************************************************************/ +{ + char Str[2]; + + Str[0] = c; + Str[1] = '\0'; + + return opts_Id(Str); +} + +void opts_Init(void) +/************************************************************** + INPUT: None + RETURNS: Nothing + EFFECT: Initialize option module +***************************************************************/ +{ + opts_DECLARATIONS = list_Nil(); + opts_PARAMETERS = list_Nil(); + opts_Err = 1; /* let getopt generate its own error messages */ + opts_IdNextAvailable = opts_IdFirst(); +} + +void opts_DeclareSPASSFlagsAsOptions(void) +/************************************************************** + INPUT: None + RETURNS: Nothing + EFFECT: Initialize option for use with SPASS: + declares all SPASS flags as command line opts. + MEMORY: Allocates space for declarations +***************************************************************/ +{ + int i; + + for (i=0; i < flag_MAXFLAG; i++) { + opts_Declare(flag_Name(i), opts_OPTARGTYPE); + } +} + +static void opts_FreeParameterPair(LIST Pair) +/************************************************************** + INPUT : An (id/string) pair + RETURNS: Nothing + EFFECTS: Frees memory of list element and string +***************************************************************/ +{ + string_StringFree(list_PairSecond(Pair)); + + list_PairFree(Pair); +} + +static void opts_FreeDecl(OPTDECL* D) +/************************************************************** + INPUT: An options declaration + RETURNS: Nothing + EFFECTS: Frees memory of struct. +***************************************************************/ +{ + string_StringFree((char*)opts_DeclGetClName(D)); + memory_Free(D, sizeof(OPTDECL)); +} + +void opts_Free(void) +/************************************************************** + INPUT: None + RETURNS: Nothing + EFFECT: Free memory of module +***************************************************************/ +{ + list_DeleteWithElement(opts_PARAMETERS, (void (*)(POINTER))opts_FreeParameterPair); + list_DeleteWithElement(opts_DECLARATIONS,(void (*)(POINTER))opts_FreeDecl); +} + +static void opts_PrintDeclarationList(LIST Scan) +/************************************************************** + INPUT: A list with option declarations + RETURNS: Nothing + EFFECTS: Prints the list +***************************************************************/ +{ + OPTDECL* Decl; + OPTID Id; + + Id = opts_IdFirst(); + + while (Scan) { + Decl = (OPTDECL*)list_Car(Scan); + printf("Id:%-6d Name:%-18s Type:%d\n", Id, opts_DeclGetClName(Decl), + opts_DeclGetType(Decl)); + Scan = list_Cdr(Scan); + Id = opts_IdNext(Id); + } +} + +static __inline__ void opts_PrintDeclarations(void) +/************************************************************** + INPUT: None + RETURNS: Nothing + EFFECTS: Prints all currently declared options +***************************************************************/ +{ + opts_PrintDeclarationList(opts_DECLARATIONS); +} + +static void opts_PrintParameters(void) +/************************************************************** + INPUT: None + RETURNS: Nothing + EFFECTS: Prints all values of options read so far +***************************************************************/ +{ + LIST Scan; + LIST Pair; + + Scan = opts_PARAMETERS; + + while (!list_Empty(Scan)) { + + Pair = list_Car(Scan); + printf("\nId: %d ", (OPTID)list_PairFirst(Pair)); + printf("Par: %s", (char*) list_PairSecond(Pair)); + + Scan = list_Cdr(Scan); + } +} + + +void opts_PrintSPASSNames(void) +/************************************************************** + INPUT: None + RETURNS: Nothing + EFFECT: Prints all options in three rows +***************************************************************/ +{ + int i,j; + + for (i=0; i < flag_MAXFLAG; i=i+4) { + for (j =0; j <=3; j++) { + if (i+j < flag_MAXFLAG) + printf("%-18s ", flag_Name(i+j)); } + putchar('\n'); + } +} + +static OPTDECL* opts_DeclGetById(OPTID Id) +/************************************************************** + INPUT : An option id + RETURNS: The declaration corresponding to option <id> +***************************************************************/ +{ + OPTID ScanId; + LIST Scan; + + ScanId = opts_IdFirst(); + Scan = opts_DECLARATIONS; + + while (!list_Empty(Scan)) { + if (opts_IdEqual(Id, ScanId)) + return list_Car(Scan); + Scan = list_Cdr(Scan); + ScanId = opts_IdNext(ScanId); + } + + return (OPTDECL*)NULL; +} + + +/* Currently unused */ +/*static*/ OPTDECL* opts_DeclGetByClName(const char* ClName) +/************************************************************** + INPUT : A command line name + RETURNS: The declaration of the option with <ClName> as command + line name, NULL if there's no such option +***************************************************************/ +{ + OPTID Id; + + Id = opts_Id(ClName); + if (opts_IdIsNull(Id)) + return NULL; + return opts_DeclGetById(Id); +} + + +BOOL opts_Read(int argc, const char* argv[]) +/************************************************************** + INPUT: Program parameter data + RETURNS: TRUE iff options are correctly specified + EFFECT: Errors are commented + MEMORY: Builds up opts_PARAMETERS while reading + options and their values. +***************************************************************/ +{ + int OptIndex, c; + char *ShortOpts; + BOOL Ok; + OPTID OptId; + OPTDECL *OptDecl; + const char *OptName; + struct OPTION *LongOpts; + + Ok = TRUE; + + ShortOpts = opts_TranslateShortOptDeclarations(); + LongOpts = opts_TranslateLongOptDeclarations(); + + while (Ok && (c = opts_GetOptLongOnly(argc, argv, ShortOpts, + LongOpts, &OptIndex)) != -1) { + /* + for following eval of opts_GetOptLongOnly result see + GNU getopt documentation. In short, opts_GetOptLongOnly + returns a char if it has found that char as an option in + the command line, and this option is declared in opts_DECLARATIONS. + It returns 0 if it has found a declared long option. + + */ + if (c == '?') { + /**** unknown option ****/ + + /* This has already been commented by opts_GetOptLongOnly */ + return FALSE; + } else if (c == 0) { + /**** its a long option ****/ + + OptName = LongOpts[OptIndex].name; + OptId = opts_Id(OptName); + OptDecl = opts_DeclGetById(OptId); + + if (opts_Arg == NULL) { + /* if argument required and no arg specified, error */ + if (opts_DeclHasReqArg(OptDecl)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\nerror, option %s requires argument.\n", OptName); + misc_FinishUserErrorReport(); + return FALSE; + } + + /* otherwise, set default value */ + Ok = opts_AddParamCheck(OptId,opts_DEFAULTOPTARG); + } else + Ok = opts_AddParamCheck(OptId,opts_Arg); + } else { + /**** its a short option ****/ + + /* handle missing but required arguments. So far, this is left + to opts_GetOptLongOnly */ + if (c == ':') + return FALSE; + + /* + + One further special case: if a short option has an optional + argument, but this argument is a '--', then take the + default argument value. '--' normally signifies: no further + options and is not interpreted nor returned by getopt as + an argument value of an option with argument. As we + permit default values for options with args, we have to declare + all options with args. Therefore, getopt takes + + -o -- + + '-o with arg --' if "o:" is the declaration. We interpret + this as '-o with default value'. + + */ + + else { + OptId = opts_ShortOptId(c); + if (opts_IdIsNull(OptId)) { + misc_StartErrorReport(); + misc_ErrorReport("\ninternal error: option %c not found.\n", c); + misc_FinishErrorReport(); + } + OptDecl = opts_DeclGetById(OptId); + + if (opts_DeclHasReqArg(OptDecl)) { + if (!opts_Arg) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\nerror: option %c requires argument.\n",c); + misc_FinishUserErrorReport(); + Ok = FALSE; + } else if (string_Equal(opts_Arg, opts_ENDMARKER)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\nerror: option %c has delimiter -- as argument.\n",c); + misc_FinishUserErrorReport(); + Ok = FALSE; + } else + Ok = opts_AddParamCheck(OptId,opts_Arg); + } + /* options with args */ + else if (opts_DeclHasOptArg(OptDecl)) { + /* if arg is present, check for endmarker */ + if (opts_Arg) { + if (string_Equal(opts_Arg, opts_ENDMARKER)) + Ok = opts_AddParamCheck(OptId,opts_DEFAULTOPTARG); + else + Ok = opts_AddParamCheck(OptId,opts_Arg); } + else + Ok = opts_AddParamCheck(OptId,opts_DEFAULTOPTARG); + } + /* default for options without args */ + else + Ok = opts_AddParamCheck(OptId,opts_DEFAULTOPTARG); + } + } + } + + string_StringFree(ShortOpts); + opts_FreeLongOptsArray(LongOpts); + + return Ok; +} + + +BOOL opts_ReadOptionsFromString(const char* Options) +/************************************************************** + INPUT: A string containing program parameter data + RETURNS: TRUE iff the string contains only valid options. + The function returns FALSE if the string contains + any substring that isn't a option or invalid option + settings. + EFFECT: Errors are commented (via stderr). + MEMORY: Builds up opts_PARAMETERS while reading options and + their values. + CAUTION: The function cannot !! be used in context with the + other option evaluation functions like opts_Read. +***************************************************************/ +{ + char **argv; + char *Copy; + int argc, i; + BOOL Result; + + /* Copy the options string since "string_Tokens" modifies it temporarily */ + Copy = string_StringCopy(Options); + /* Split the string into substrings without whitespace. */ + /* Collect the substrings in an array similar to "argv" for main(). */ + argv = string_Tokens(Copy, &argc); + + /* Check whether all options are valid. */ + Result = opts_Read(argc, (const char**)argv); + /* Check whether the string contains only option settings. */ + if (opts_Indicator() < argc) + Result = FALSE; + + /* Cleanup */ + for (i = argc-1; i >= 0; i--) + string_StringFree(argv[i]); + memory_Free(argv, sizeof(char)*(argc+1)); + string_StringFree(Copy); + + return Result; +} + + +BOOL opts_GetValueByName(const char* Name, const char** Value) +/************************************************************** + INPUT: An option command line name, a string by ref. + RETURNS: TRUE if an option with this name exists + in opts_PARAMETERS (as set by opts_Read()), + and the assigned value of this option in <Value>. + FALSE otherwise + EFFECTS: <*Value> is changed +***************************************************************/ +{ + LIST Scan; + LIST Pair; + BOOL found; + + found = FALSE; + Pair = list_Nil(); /* to quiet gcc */ + + for (Scan = opts_PARAMETERS; + (!found && !list_Empty(Scan)); Scan = list_Cdr(Scan)) { + Pair = list_Car(Scan); + if (string_Equal(Name, opts_ClName((OPTID)list_PairFirst(Pair)))) + found = TRUE; + } + + if (found) + (*Value) = list_PairSecond(Pair); + + return found; +} + +BOOL opts_GetValue(OPTID Id, const char** s) +/************************************************************** + INPUT: An option id, a string by reference + RETURNS: TRUE if an option with this id exists + in opts_PARAMETERS (as set by opts_Read()), + and the assigned value of this option in <Value>. + FALSE otherwise + EFFECTS: <s*> is changed +***************************************************************/ +{ + LIST Scan; + LIST Pair; + BOOL found; + + Pair = list_Nil(); + found = FALSE; + + for (Scan = opts_PARAMETERS; + (!found && !list_Empty(Scan)); Scan = list_Cdr(Scan)) { + Pair = list_Car(Scan); + if (opts_IdEqual(Id, (OPTID)list_PairFirst(Pair))) + found = TRUE; + } + + if (found) + (*s) = list_PairSecond(Pair); + + return found; +} + + +BOOL opts_GetIntValueByName(const char* Name, int* Val) +/************************************************************** + INPUT: An options name, an integer by reference + RETURNS: TRUE + if an option with <Name> exists + in opts_PARAMETERS (as set by opts_Read()) and + if its assigned value is an integer. + The assigned value of this option is returned in <Val>. + FALSE + otherwise + EFFECTS: <Val*> is changed +***************************************************************/ +{ + const char* ValStr ; + + if (!opts_GetValueByName(Name, &ValStr)) + return FALSE; + + return string_StringToInt(ValStr, FALSE, Val); +} + +BOOL opts_GetIntValue(OPTID Id, int* i) +/************************************************************** + INPUT: An options name, an integer by reference + RETURNS: TRUE + if an option with <Id> exists + in opts_PARAMETERS (as set by opts_Read()) and + if its assigned value is an integer. + T he assigned value of this option is returned in <*i>. + FALSE + otherwise + EFFECTS: <*i> is changed +***************************************************************/ +{ + return opts_GetIntValueByName(opts_ClName(Id), i); +} + + + +BOOL opts_IsSet(OPTID Id) +/************************************************************** + INPUT: An option id + RETURNS: TRUE iff the option has been set in the command line + (that is, is listed in opts_PARAMETERS) +***************************************************************/ +{ + LIST Scan; + LIST Pair; + BOOL found; + + found = FALSE; + + for (Scan = opts_PARAMETERS; + (!found && !list_Empty(Scan)); Scan = list_Cdr(Scan)) { + Pair = list_Car(Scan); + if (opts_IdEqual(Id, (OPTID)list_Car(Pair))) + found = TRUE; + } + return found; +} + + +/* Currently unused */ +/*static*/ BOOL opts_IsSetByName(const char* Name) +/************************************************************** + INPUT: An option name + RETURNS: TRUE iff option with this name has been set in command line +***************************************************************/ +{ + LIST Scan; + LIST Pair; + BOOL found; + + found = FALSE; + + for (Scan = opts_PARAMETERS; + (!found && !list_Empty(Scan)); Scan = list_Cdr(Scan)) { + Pair = list_Car(Scan); + if (string_Equal(Name, opts_ClName((OPTID)list_PairFirst(Pair)))) + found = TRUE; + } + return found; +} + +void opts_SetFlags(FLAGSTORE Store) +/************************************************************** + INPUT: A flag store. + RETURNS: Nothing + EFFECT : Transfer options into SPASS flags in <Store> + CAUTION: To connect SPASS flags and options, we assume that + all flag names and command line names of all options + are the same! +***************************************************************/ +{ + int IntValue; + OPTID Id; + FLAG_ID i; + + for (i = 0; i < flag_MAXFLAG; i++) { + Id = opts_Id(flag_Name(i)); + if (opts_IsSet(Id)) { + if (opts_GetIntValue(Id, &IntValue)) { + flag_SetFlagValue(Store, Id, IntValue); + } else { + misc_StartUserErrorReport(); + misc_UserErrorReport("\nerror: argument of option %s must be integer.\n",flag_Name(i)); + misc_FinishUserErrorReport(); + } + } + } +} + +void opts_Transfer(FLAGSTORE Store) +/************************************************************** + INPUT: A flag store. + RETURNS: Nothing + EFFECT: Transfer options from 'opts_PARAMETERS' list into SPASS + flags in <Store> + CAUTION: To connect SPASS flags and options, we assume that + all flag names and command line names of all options + are the same! +***************************************************************/ +{ + LIST Scan; + LIST Pair; + int IntValue; + const char *Name, *ValStr; + OPTID Id; + BOOL ok; + + Scan = opts_PARAMETERS; + + while (!list_Empty(Scan)) { + Pair = list_Car(Scan); + Id = (int)list_PairFirst(Pair); + ValStr = (const char*)list_PairSecond(Pair); + Name = opts_ClName(Id); + + ok = string_StringToInt(ValStr, FALSE, &IntValue); + if (!ok) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\nerror: argument '%s' of option '%s' must be integer.\n", + ValStr, Name); + misc_FinishUserErrorReport(); + } else { + flag_SetFlagValue(Store, flag_Id(Name), IntValue); + } + Scan = list_Cdr(Scan); + } +} + + +static void opts_AddParam(OPTID Id, const char* ValueString) +/************************************************************** + INPUT: An option id and a string with its assigned value + RETURNS: Nothing. + EFFECT: Add (Id, ValueString) tupel to 'opts_PARAMETERS' list +***************************************************************/ +{ + LIST Pair; + Pair = list_PairCreate((POINTER)Id, string_StringCopy(ValueString)); + opts_PARAMETERS = list_Cons(Pair, opts_PARAMETERS); +} + + +static BOOL opts_AddParamCheck(OPTID Id, const char* ValueString) +/************************************************************** + INPUT: An option id and a string + RETURNS: TRUE iff option with <Id> has not been defined + EFFECTS: Adds (<Id>,<ValueString>) tupel to opts_PARAMETERS +***************************************************************/ +{ + const char* Dummy; + if (opts_GetValue(Id, &Dummy)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("error: option %s is multiply defined.\n", opts_ClName(Id)); + misc_FinishUserErrorReport(); + return FALSE; + } + opts_AddParam(Id, ValueString); + return TRUE; +} + + +int opts_Indicator(void) +/************************************************************** + INPUT: None + RETURNS: Integer variable indicating position of next argument +***************************************************************/ +{ + return opts_Ind; +} + + +static void opts_Exchange (const char *argv[]) +/************************************************************** + INPUT: Reference to string + RETURNS: Nothing + EFFECT: See below +***************************************************************/ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [opts_FirstNonOpt,opts_LastNonOpt) + which contains all the non-options that have been skipped so far. + The other is elements [opts_LastNonOpt,opts_Ind), which contains all + the options processed since those non-options were skipped. + + `opts_FirstNonOpt' and `opts_LastNonOpt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ +{ + int bottom = opts_FirstNonOpt; + int middle = opts_LastNonOpt; + int top = opts_Ind; + const char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + + while (top > middle && middle > bottom) { + if (top - middle > middle - bottom) { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + opts_FirstNonOpt += (opts_Ind - opts_LastNonOpt); + opts_LastNonOpt = opts_Ind; +} + + +static const char *opts_GetOptInitialize (int argc, const char *const argv[], + const char *optstring) +/************************************************************** + INPUT: The command line arguments ('argc', 'argv') and + a string describing options ('optstring') + RETURNS: a possibly modified 'optstring' + EFFECT: Several static variables related to options + processing are influenced (see below). + MEMORY: None +***************************************************************/ +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + opts_FirstNonOpt = opts_LastNonOpt = opts_Ind = 1; + + opts_NextChar = NULL; + + opts_PosixlyCorrect = getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') { + opts_Ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') { + opts_Ordering = REQUIRE_ORDER; + ++optstring; + } + else if (opts_PosixlyCorrect != NULL) + opts_Ordering = REQUIRE_ORDER; + else + opts_Ordering = PERMUTE; + + opts_NonOptionFlagslen = 0; + + return optstring; +} + +static int opts_GetOptInternal (int argc, const char* argv[], + const char *optstring, + const struct OPTION *longopts, int *longind, + int long_only) +/************************************************************** + INPUT: An array of pointers to arguments (strings), + and format information. See below for extensive + description + RETURNS: -1 only if there are no more options, otherwise + a value identifying a read option. See below. + EFFECT: Affects statics opts_Ind, opts_Arg, opts_Opt, + opts_NextChar and argument array. See below. + MEMORY: See below. +***************************************************************/ +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `opts_Ind' and `opts_NextChar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `opts_Ind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opts_Err' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `opts_Arg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `opts_Arg', otherwise `opts_Arg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct OPTION' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ +{ + opts_Arg = NULL; + + if (!opts_GetOptInitialized || opts_Ind == 0) { + optstring = opts_GetOptInitialize(argc, argv, optstring); + opts_Ind = 1; /* Don't scan ARGV[0], the program name. */ + opts_GetOptInitialized = 1; + } + + /* Test whether ARGV[opts_Ind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ + + + if (opts_NextChar == NULL || *opts_NextChar == '\0') { + /* Advance to the next ARGV-element. */ + + /* Give OPTS_FIRSTNONOPT & LAST_NONOPT rational values if OPTS_IND has been + moved back by the user (who may also have changed the arguments). */ + if (opts_LastNonOpt > opts_Ind) + opts_LastNonOpt = opts_Ind; + if (opts_FirstNonOpt > opts_Ind) + opts_FirstNonOpt = opts_Ind; + + if (opts_Ordering == PERMUTE) { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (opts_FirstNonOpt != opts_LastNonOpt && opts_LastNonOpt != opts_Ind) + opts_Exchange(argv); + else if (opts_LastNonOpt != opts_Ind) + opts_FirstNonOpt = opts_Ind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (opts_Ind < argc && (argv[opts_Ind][0] != '-' || argv[opts_Ind][1] == '\0')) + opts_Ind++; + opts_LastNonOpt = opts_Ind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (opts_Ind != argc && !strcmp(argv[opts_Ind], "--")) { + opts_Ind++; + + if (opts_FirstNonOpt != opts_LastNonOpt && opts_LastNonOpt != opts_Ind) + opts_Exchange(argv); + else if (opts_FirstNonOpt == opts_LastNonOpt) + opts_FirstNonOpt = opts_Ind; + opts_LastNonOpt = argc; + + opts_Ind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (opts_Ind == argc) { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (opts_FirstNonOpt != opts_LastNonOpt) + opts_Ind = opts_FirstNonOpt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ( (argv[opts_Ind][0] != '-' || argv[opts_Ind][1] == '\0')) { + if (opts_Ordering == REQUIRE_ORDER) + return -1; + opts_Arg = argv[opts_Ind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + opts_NextChar = (argv[opts_Ind] + 1 + + (longopts != NULL && argv[opts_Ind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[opts_Ind][1] == '-' + || (long_only && (argv[opts_Ind][2] || !strchr(optstring, argv[opts_Ind][1]))))) { + const char *nameend; + const struct OPTION *p; + const struct OPTION *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = opts_NextChar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, opts_NextChar, nameend - opts_NextChar)) { + if ((unsigned int) (nameend - opts_NextChar) + == (unsigned int) strlen(p->name)) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) { + if (opts_Err) { + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: option `%s' is ambiguous\n", argv[0], argv[opts_Ind]); + misc_FinishUserErrorReport(); + } + opts_NextChar += strlen(opts_NextChar); + opts_Ind++; + opts_Opt = 0; + return '?'; + } + + if (pfound != NULL) { + option_index = indfound; + opts_Ind++; + if (*nameend) { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + opts_Arg = nameend + 1; + else { + if (opts_Err) { + if (argv[opts_Ind - 1][1] == '-') { + /* --option */ + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: option `--%s' doesn't allow an argument\n",argv[0], pfound->name); + misc_FinishUserErrorReport(); + } + else { + /* +option or -option */ + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[opts_Ind - 1][0], pfound->name); + misc_FinishUserErrorReport(); + } + } + opts_NextChar += strlen(opts_NextChar); + + opts_Opt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) { + if (opts_Ind < argc) + opts_Arg = argv[opts_Ind++]; + else { + if (opts_Err) { + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: option `%s' requires an argument\n", + argv[0], argv[opts_Ind - 1]); + misc_FinishUserErrorReport(); + } + opts_NextChar += strlen(opts_NextChar); + opts_Opt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + opts_NextChar += strlen(opts_NextChar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not opts_GetOptLong_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[opts_Ind][1] == '-' + || strchr(optstring, *opts_NextChar) == NULL) { + if (opts_Err) { + if (argv[opts_Ind][1] == '-') { + /* --option */ + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: unrecognized option `--%s'\n",argv[0], opts_NextChar); + misc_FinishUserErrorReport(); + } + else { + /* +option or -option */ + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: unrecognized option `%c%s'\n", + argv[0], argv[opts_Ind][0], opts_NextChar); + misc_FinishUserErrorReport(); + } + } + opts_NextChar = ""; + opts_Ind++; + opts_Opt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *opts_NextChar++; + char *temp = strchr(optstring, c); + + /* Increment `opts_Ind' when we start to process its last character. */ + if (*opts_NextChar == '\0') + ++opts_Ind; + + if (temp == NULL || c == ':') { + if (opts_Err) { + if (opts_PosixlyCorrect) { + /* 1003.2 specifies the format of this message. */ + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: illegal option -- %c\n", argv[0], c); + misc_FinishUserErrorReport(); + } + else { + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: invalid option -- %c\n", argv[0], c); + misc_FinishUserErrorReport(); + } + } + opts_Opt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') { + const char *nameend; + const struct OPTION *p; + const struct OPTION *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*opts_NextChar != '\0') { + opts_Arg = opts_NextChar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + opts_Ind++; + } + else if (opts_Ind == argc) { + if (opts_Err) { + /* 1003.2 specifies the format of this message. */ + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: option requires an argument -- %c\n", argv[0], c); + misc_FinishUserErrorReport(); + } + opts_Opt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `opts_Ind' once; + increment it again when taking next ARGV-elt as argument. */ + opts_Arg = argv[opts_Ind++]; + + /* opts_Arg is now the argument, see if it's in the + table of longopts. */ + + for (opts_NextChar = nameend = opts_Arg; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, opts_NextChar, nameend - opts_NextChar)) { + if ((unsigned int) (nameend - opts_NextChar) == strlen(p->name)) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) { + if (opts_Err) { + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: option `-W %s' is ambiguous\n", argv[0], argv[opts_Ind]); + misc_FinishUserErrorReport(); + } + opts_NextChar += strlen(opts_NextChar); + opts_Ind++; + return '?'; + } + if (pfound != NULL) { + option_index = indfound; + if (*nameend) { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + opts_Arg = nameend + 1; + else { + if (opts_Err) { + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: option `-W %s' doesn't allow an argument\n", argv[0], pfound->name); + misc_FinishUserErrorReport(); + } + + opts_NextChar += strlen(opts_NextChar); + return '?'; + } + } + else if (pfound->has_arg == 1) { + if (opts_Ind < argc) + opts_Arg = argv[opts_Ind++]; + else { + if (opts_Err) { + misc_StartUserErrorReport(); + misc_UserErrorReport("%s: option `%s' requires an argument\n", argv[0], argv[opts_Ind - 1]); + misc_FinishUserErrorReport(); + } + opts_NextChar += strlen(opts_NextChar); + return optstring[0] == ':' ? ':' : '?'; + } + } + opts_NextChar += strlen(opts_NextChar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + opts_NextChar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') { + if (temp[2] == ':') { + /* This is an option that accepts an argument optionally. */ + if (*opts_NextChar != '\0') { + opts_Arg = opts_NextChar; + opts_Ind++; + } + else + opts_Arg = NULL; + opts_NextChar = NULL; + } + else { + /* This is an option that requires an argument. */ + if (*opts_NextChar != '\0') { + opts_Arg = opts_NextChar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + opts_Ind++; + } + else if (opts_Ind == argc) { + if (opts_Err) { + /* 1003.2 specifies the format of this message. */ + misc_StartUserErrorReport(); + misc_UserErrorReport(("%s: option requires an argument -- %c\n"), argv[0], c); + misc_FinishUserErrorReport(); + } + opts_Opt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `opts_Ind' once; + increment it again when taking next ARGV-elt as argument. */ + opts_Arg = argv[opts_Ind++]; + opts_NextChar = NULL; + } + } + return c; + } +} + + +/* Like opts_GetOptLong, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +static int opts_GetOptLongOnly(int argc, const char* argv[], const char *options, + const struct OPTION *long_options, int *opt_index) +/************************************************************** + FUNCTIONALITY: See opts_GetOptInternal +***************************************************************/ +{ + return opts_GetOptInternal (argc, argv, options, long_options, opt_index, 1); +} + + +static void opts_Dummy(void) +/************************************************************** + Assemble all unused functions to quiet gcc +***************************************************************/ +{ + if (FALSE) { + opts_PrintParameters(); + opts_PrintDeclarations(); + opts_DeclHasNoArg(NULL); + opts_PrintLongOpts((struct OPTION*)NULL); + opts_Dummy(); + } +} diff --git a/test/spass/options.h b/test/spass/options.h new file mode 100644 index 0000000000000000000000000000000000000000..f41da831f68885bbc2344e386b62328d8f5b656c --- /dev/null +++ b/test/spass/options.h @@ -0,0 +1,127 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SPASS OPTIONS HANDLING * */ +/* * * */ +/* * $Module: OPTIONS * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/* $RCSfile$ */ + + +#ifndef _OPTIONS_ +#define _OPTIONS_ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include "flags.h" +#include "list.h" + + +/**************************************************************/ +/* Data Structures and Constants */ +/**************************************************************/ + +/* option type */ +typedef int OPTTYPE; + +#define opts_NOARGTYPE 0 /* no argument */ +#define opts_REQARGTYPE 1 /* required argument */ +#define opts_OPTARGTYPE 2 /* optional argument */ + +/* option id */ +typedef int OPTID; +#define opts_IDFIRST 0 /* option id to start with */ + +/* struct for declaration of options */ +typedef struct { + char* clname; /* option name in the command line */ + OPTTYPE type; /* argument type: required, optional, non */ +} OPTDECL; + +#define opts_ENDMARKER "--" /* double hyphen: marks end of all options */ +#define opts_DEFAULTOPTARG "1" /* default value of options with optional arguments */ + +/************************************************************** + from the getopt.h file + **************************************************************/ +struct OPTION +{ + char *name; + + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +void opts_Init(void); +void opts_Free(void); +OPTID opts_DeclareVector(OPTDECL []); +OPTID opts_Declare(const char*, OPTTYPE); +BOOL opts_Read(int, const char* []); +BOOL opts_ReadOptionsFromString(const char*); +int opts_Indicator(void); + +BOOL opts_IsSet(OPTID); +BOOL opts_GetIntValueByName(const char*, int*); +BOOL opts_GetValueByName(const char*, const char**); +BOOL opts_GetValue(OPTID, const char**); +BOOL opts_GetIntValue(OPTID, int*) ; + +const char* opts_ClName(OPTID); +OPTID opts_IdFirst(void); +OPTID opts_Id(const char*); +BOOL opts_IdIsNull(OPTID); + +/* specials for SPASS */ +void opts_Transfer(FLAGSTORE); +void opts_SetFlags(FLAGSTORE); +void opts_DeclareSPASSFlagsAsOptions(void); +void opts_PrintSPASSNames(void); + +#endif diff --git a/test/spass/order.c b/test/spass/order.c new file mode 100644 index 0000000000000000000000000000000000000000..48a1dd32f31f16330891b314b141ab74a614c12c --- /dev/null +++ b/test/spass/order.c @@ -0,0 +1,516 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INTERFACE FOR ALL ORDERING IMPLEMENTATIONS * */ +/* * * */ +/* * $Module: ORDER * */ +/* * * */ +/* * Copyright (C) 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "flags.h" +#include "order.h" +#include "kbo.h" +#include "rpos.h" +#include "symbol.h" + +NAT ord_VARCOUNT[symbol__MAXSTANDARDVAR][2]; +PRECEDENCE ord_PRECEDENCE; + + +static ord_RESULT ord_CheckDomPred(TERM T1, TERM T2, PRECEDENCE P) +/************************************************************** + INPUT: Two terms and a precedence. + RETURNS: An ordering result with respect to a possible domination + of leading predicates in <T1> or <T2>. +***************************************************************/ +{ + if ((term_IsAtom(T1) && symbol_HasProperty(term_TopSymbol(T1), DOMPRED)) || + (term_IsAtom(T2) && symbol_HasProperty(term_TopSymbol(T2), DOMPRED))) { + if (term_IsAtom(T1)) { + if (term_IsAtom(T2)) { + if (symbol_HasProperty(term_TopSymbol(T1), DOMPRED) && + (!symbol_HasProperty(term_TopSymbol(T2), DOMPRED) || + symbol_PrecedenceGreater(P,term_TopSymbol(T1),term_TopSymbol(T2)))) + return ord_GREATER_THAN; + if (!symbol_HasProperty(term_TopSymbol(T1), DOMPRED) || + term_TopSymbol(T1) != term_TopSymbol(T2)) + return ord_SMALLER_THAN; + /* If the top symbols are equal, do the normal comparison */ + } else { + /* T1 is an atom, T2 is not, so T1 is greater */ + return ord_GREATER_THAN; + } + } else { + /* T1 is not an atom, so T2 must be an atom */ + return ord_SMALLER_THAN; + } + } + return ord_UNCOMPARABLE; +} + + +ord_RESULT ord_Compare(TERM T1, TERM T2, FLAGSTORE FlagStore, PRECEDENCE P) +/************************************************************** + INPUT: + RETURNS: +***************************************************************/ +{ + ord_RESULT Aux; + +#ifdef CHECK + if (fol_IsEquality(T1) || fol_IsEquality(T2)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In ord_Compare:"); + misc_ErrorReport("\n Illegal input. One input term is an equality."); + misc_FinishErrorReport(); + } +#endif + + Aux = ord_CheckDomPred(T1, T2, P); + if (Aux != ord_UNCOMPARABLE) + return Aux; + else { + ord_PRECEDENCE = P; + switch(flag_GetFlagValue(FlagStore, flag_ORD)) { + case flag_ORDKBO: return kbo_Compare(T1, T2); break; + case flag_ORDRPOS: return rpos_Compare(T1, T2); break; + default: + misc_StartErrorReport(); + misc_ErrorReport("\n In ord_Compare:"); + misc_ErrorReport("\n Illegal ordering type."); + misc_FinishErrorReport(); + } + } + return ord_UNCOMPARABLE; +} + + +BOOL ord_CompareEqual(TERM T1, TERM T2, FLAGSTORE Flags) +/************************************************************** + INPUT: Two terms and a flag store. + RETURNS: TRUE, iff the two terms are equal with respect to the + reduction ordering selected by the 'flag_ORD' flag. +***************************************************************/ +{ + switch(flag_GetFlagValue(Flags, flag_ORD)) { + case flag_ORDKBO: return term_Equal(T1, T2); break; + case flag_ORDRPOS: return rpos_Equal(T1, T2); break; + default: + misc_StartErrorReport(); + misc_ErrorReport("\n In ord_Compare: Illegal ordering type."); + misc_FinishErrorReport(); + return FALSE; /* unreachable code ... */ + } +} + +ord_RESULT ord_ContCompare(CONTEXT C1, TERM T1, CONTEXT C2, TERM T2, + FLAGSTORE FlagStore, PRECEDENCE P) +{ + ord_RESULT Aux; + +#ifdef CHECK + if (fol_IsEquality(T1) || fol_IsEquality(T2)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In ord_ContCompare:"); + misc_ErrorReport("\n Illegal input. One input term is an equality."); + misc_FinishErrorReport(); + } +#endif + + Aux = ord_CheckDomPred(T1, T2, P); + if (Aux != ord_UNCOMPARABLE) + return Aux; + else { + ord_PRECEDENCE = P; + switch(flag_GetFlagValue(FlagStore, flag_ORD)) { + case flag_ORDKBO: return kbo_ContCompare(C1, T1, C2, T2); break; + case flag_ORDRPOS: return rpos_ContCompare(C1, T1, C2, T2); break; + default: + misc_StartErrorReport(); + misc_ErrorReport("\n In ord_ContCompare:"); + misc_ErrorReport("\n Illegal ordering type."); + misc_FinishErrorReport(); + } + } + return ord_UNCOMPARABLE; +} + + +BOOL ord_ContGreater(CONTEXT C1, TERM T1, CONTEXT C2, TERM T2, + FLAGSTORE FlagStore, PRECEDENCE P) +{ + ord_RESULT Aux; + +#ifdef CHECK + if (fol_IsEquality(T1) || fol_IsEquality(T2)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In ord_ContGreater:"); + misc_ErrorReport("\n Illegal input. One input term is an equality."); + misc_FinishErrorReport(); + } +#endif + + Aux = ord_CheckDomPred(T1, T2, P); + if (Aux != ord_UNCOMPARABLE) + return (Aux == ord_GREATER_THAN); + else { + ord_PRECEDENCE = P; + switch(flag_GetFlagValue(FlagStore, flag_ORD)) { + case flag_ORDKBO: return kbo_ContGreater(C1, T1, C2, T2); break; + case flag_ORDRPOS: return rpos_ContGreater(C1, T1, C2, T2); break; + default: + misc_StartErrorReport(); + misc_ErrorReport("\n In ord_ContGreater:"); + misc_ErrorReport("\n Illegal ordering type."); + misc_FinishErrorReport(); + } + } + return FALSE; /* This line is never reached ... */ +} + + +ord_RESULT ord_Not(ord_RESULT Result) +/************************************************************** + INPUT: An ord_RESULT + RETURNS: The negation with respect to argument switching. +***************************************************************/ +{ + if (Result == ord_UNCOMPARABLE || Result == ord_EQUAL) + return Result; + + if (Result == ord_GREATER_THAN) + return ord_SMALLER_THAN; + + return ord_GREATER_THAN; +} + + +void ord_Print(ord_RESULT Result) +/************************************************************** + INPUT: An ord_Result. + RETURNS: None, prints the Result as a string to stdout. +***************************************************************/ +{ + switch(Result) { + case ord_UNCOMPARABLE: fputs(" uncomparable ",stdout); break; + case ord_EQUAL: fputs(" equal ",stdout); break; + case ord_GREATER_THAN: fputs(" greater than ",stdout); break; + case ord_SMALLER_THAN: fputs(" smaller than ",stdout); break; + default: fputs(" Nonsense! ",stdout); + } +} + + +ord_RESULT ord_LiteralCompare(TERM Lit1, BOOL Orient1, TERM Lit2, BOOL Orient2, + BOOL Check, FLAGSTORE FlagStore, + PRECEDENCE Precedence) +/********************************************************* + INPUT: Two term literals and two flags indicating whether these + two literals are oriented equalities. + Additionally a check flag that indicates whether + the orientation flags are sufficient or necessary and sufficient: + If Check=TRUE then if flag is FALSE it is interpreted that it is not + known whether the (possible) equation can be oriented oriented. + However, if flag is TRUE we assume that it is oriented. + A flag store. + A precedence. + RETURNS: The result if these literals are compared with + respect to the ordering. Dependent on their sign, the literals + are compared as multiset of their topsymbol terms, + where any literal is considered to be an equation + and non equational literals are considered to be + equations with the artificial, non-existent, minimal + constant tt. + EFFECT: The arguments of the literals are possibly, destructively flipped. +**********************************************************/ +{ + ord_RESULT result,auxResult,AuxRl1r2,AuxRr1r2,AuxRr1l2,Comp1,Comp2; + BOOL pos1,pos2; + + pos1 = pos2 = TRUE; + Comp1 = Comp2 = result = ord_UNCOMPARABLE; + if (symbol_Equal(term_TopSymbol(Lit1),fol_Not())) { + Lit1 = term_FirstArgument(Lit1); + pos1 = FALSE; + } + if (symbol_Equal(term_TopSymbol(Lit2),fol_Not())) { + Lit2 = term_FirstArgument(Lit2); + pos2 = FALSE; + } + + if (fol_IsEquality(Lit1)) { /* Real equation */ + if (fol_IsEquality(Lit2)) { + TERM l1,r1,l2,r2,aux; + l1 = term_FirstArgument(Lit1); + r1 = term_SecondArgument(Lit1); + l2 = term_FirstArgument(Lit2); + r2 = term_SecondArgument(Lit2); + if (Orient1 || + (Check && + ((Comp1 = ord_Compare(l1,r1,FlagStore,Precedence)) == ord_GREATER_THAN || + Comp1 == ord_SMALLER_THAN))) { + if (Comp1 == ord_SMALLER_THAN) { + aux = l1; l1 = r1; r1 = aux; + } + if (Orient2 || + (Check && + ((Comp2 = ord_Compare(l2,r2,FlagStore,Precedence))==ord_GREATER_THAN || + Comp2 == ord_SMALLER_THAN))) { + /* Both equations are oriented */ + if (Comp2 == ord_SMALLER_THAN) { + aux = l2; l2 = r2; r2 = aux; + } + result = ord_Compare(l1,l2, FlagStore, Precedence); + if (result == ord_EQUAL) { + if (pos1) { + if (pos2) + return ord_Compare(r1,r2, FlagStore, Precedence); + else + return ord_SMALLER_THAN; + } + else + if (pos2) + return ord_GREATER_THAN; + else + return ord_Compare(r1,r2, FlagStore, Precedence); + } + return result; + } + else { /* Lit2 is not oriented equation */ + if (term_Equal(l1,l2)) { + result = ord_Compare(r1,r2, FlagStore, Precedence); + if (result == ord_EQUAL) { + if (pos1 && !pos2) + return ord_SMALLER_THAN; + else + if (!pos1 && pos2) + return ord_GREATER_THAN; + } + return result; + } + if (term_Equal(l1,r2)) { + result = ord_Compare(r1,l2, FlagStore, Precedence); + if (result == ord_EQUAL) { + if (pos1 && !pos2) + return ord_SMALLER_THAN; + else + if (!pos1 && pos2) + return ord_GREATER_THAN; + } + return result; + } + result = ord_Compare(l1,l2, FlagStore, Precedence); + AuxRl1r2 = ord_Compare(l1,r2, FlagStore, Precedence); + if (result == AuxRl1r2) + return result; + AuxRr1r2 = ord_Compare(r1,r2, FlagStore, Precedence); + if (result == AuxRr1r2) + return result; + if (AuxRl1r2 == AuxRr1r2 && AuxRl1r2 == ord_SMALLER_THAN) + return ord_SMALLER_THAN; + AuxRr1l2 = ord_Compare(r1,l2, FlagStore, Precedence); + if (result == AuxRr1l2 && result == ord_SMALLER_THAN) + return ord_SMALLER_THAN; + return ord_UNCOMPARABLE; + } + } + else /* Lit1 is unorientable equation */ + if (Orient2 || + (Check && + ((Comp2 = ord_Compare(term_FirstArgument(Lit2), + term_SecondArgument(Lit2), + FlagStore, Precedence) == ord_GREATER_THAN) || + Comp2 == ord_SMALLER_THAN))) { /* Lit2 is orientable equation */ + if (Comp2 == ord_SMALLER_THAN) { + aux = l2; l2 = r2; r2 = aux; + } + if (term_Equal(l1,l2)) { + result = ord_Compare(r1,r2, FlagStore, Precedence); + if (result == ord_EQUAL) { + if (pos1 && !pos2) + return ord_SMALLER_THAN; + else + if (!pos1 && pos2) + return ord_GREATER_THAN; + } + return result; + } + if (term_Equal(r1,l2)) { + result = ord_Compare(l1,r2, FlagStore, Precedence); + if (result == ord_EQUAL) { + if (pos1 && !pos2) + return ord_SMALLER_THAN; + else + if (!pos1 && pos2) + return ord_GREATER_THAN; + } + return result; + } + + result = ord_Compare(l1,l2, FlagStore, Precedence); + AuxRr1l2 = ord_Compare(r1,l2, FlagStore, Precedence); + if (result == AuxRr1l2) + return result; + AuxRr1r2 = ord_Compare(r1,r2, FlagStore, Precedence); + if (result == AuxRr1r2) + return result; + if (AuxRr1l2 == AuxRr1r2 && AuxRr1l2 == ord_GREATER_THAN) + return ord_GREATER_THAN; + AuxRl1r2 = ord_Compare(l1,r2, FlagStore, Precedence); + if (result == AuxRl1r2 && result == ord_GREATER_THAN) + return ord_GREATER_THAN; + return ord_UNCOMPARABLE; + } + else { /* Both literals are unorientable equations */ + if (term_Equal(l1,l2)) { + result = ord_Compare(r1,r2, FlagStore, Precedence); + if (result == ord_EQUAL) { + if (pos1 && !pos2) + return ord_SMALLER_THAN; + else if (!pos1 && pos2) + return ord_GREATER_THAN; + } + return result; + } + if (term_Equal(r1,l2)) { + result = ord_Compare(l1,r2, FlagStore, Precedence); + if (result == ord_EQUAL) { + if (pos1 && !pos2) + return ord_SMALLER_THAN; + else if (!pos1 && pos2) + return ord_GREATER_THAN; + } + return result; + } + if (term_Equal(l1,r2)) { + result = ord_Compare(r1,l2, FlagStore, Precedence); + if (result == ord_EQUAL) { + if (pos1 && !pos2) + return ord_SMALLER_THAN; + else if (!pos1 && pos2) + return ord_GREATER_THAN; + } + return result; + } + if (term_Equal(r1,r2)) { + result = ord_Compare(l1,l2, FlagStore, Precedence); + if (result == ord_EQUAL) { + if (pos1 && !pos2) + return ord_SMALLER_THAN; + else if (!pos1 && pos2) + return ord_GREATER_THAN; + } + return result; + } + result = ord_Compare(l1,l2, FlagStore, Precedence); + if (result == ord_UNCOMPARABLE) { + result = ord_Compare(l1,r2, FlagStore, Precedence); + if (result == ord_UNCOMPARABLE) { + if (ord_Compare(r1,l2, FlagStore, Precedence) == ord_GREATER_THAN && + ord_Compare(r1,r2, FlagStore, Precedence) == ord_GREATER_THAN) + return ord_GREATER_THAN; + return ord_UNCOMPARABLE; + } + if (result == ord_GREATER_THAN) { + if (ord_Compare(r1,l2, FlagStore, Precedence) == ord_GREATER_THAN) + return ord_GREATER_THAN; + return ord_UNCOMPARABLE; + } + if (result == ord_SMALLER_THAN) { + if (ord_Compare(r1,l2, FlagStore, Precedence) == ord_SMALLER_THAN || + ord_Compare(r1,r2, FlagStore, Precedence) == ord_SMALLER_THAN) + return ord_SMALLER_THAN; + return ord_UNCOMPARABLE; + } + } + if (result == ord_GREATER_THAN) { + if ((result = ord_Compare(l1,r2,FlagStore,Precedence)) == ord_GREATER_THAN || + (auxResult = ord_Compare(r1,r2,FlagStore,Precedence)) == ord_GREATER_THAN) + return ord_GREATER_THAN; + if (result == ord_UNCOMPARABLE || auxResult == ord_UNCOMPARABLE) + return ord_UNCOMPARABLE; + return ord_SMALLER_THAN; + } + if (result == ord_SMALLER_THAN) { + if ((result = ord_Compare(r1,l2,FlagStore,Precedence)) == ord_SMALLER_THAN || + (auxResult = ord_Compare(r1,r2,FlagStore,Precedence)) == ord_SMALLER_THAN) + return ord_SMALLER_THAN; + if (result == ord_UNCOMPARABLE || auxResult == ord_UNCOMPARABLE) + return ord_UNCOMPARABLE; + return ord_GREATER_THAN; + } + } + } + else {/* Second Atom is not an equation */ + /* They can't be equal ! */ + result = ord_Compare(term_FirstArgument(Lit1),Lit2,FlagStore,Precedence); + if (!Orient1 && result != ord_GREATER_THAN) { + auxResult = ord_Compare(term_SecondArgument(Lit1),Lit2,FlagStore,Precedence); + if (auxResult == ord_GREATER_THAN) + result = ord_GREATER_THAN; + else if (result != auxResult) + result = ord_UNCOMPARABLE; + } + } + } + else /* First Atom is not an equation */ + /* They can't be equal ! */ + if (fol_IsEquality(Lit2)) { + result = ord_Compare(Lit1,term_FirstArgument(Lit2), FlagStore, Precedence); + if (!Orient2 && result != ord_SMALLER_THAN) { + auxResult = ord_Compare(Lit1,term_SecondArgument(Lit2),FlagStore,Precedence); + if (auxResult == ord_SMALLER_THAN) + result = ord_SMALLER_THAN; + else if (result != auxResult) + result = ord_UNCOMPARABLE; + } + } else { /* None of the atoms is an equation */ + result = ord_Compare(Lit1,Lit2, FlagStore, Precedence); + if (result == ord_EQUAL) { + if (pos1 && !pos2) + result = ord_SMALLER_THAN; + else if (!pos1 && pos2) + result = ord_GREATER_THAN; + } + } + + return result; +} diff --git a/test/spass/order.h b/test/spass/order.h new file mode 100644 index 0000000000000000000000000000000000000000..3817576fa721fbb07f58e3dd0dd0e0ecebf07d9d --- /dev/null +++ b/test/spass/order.h @@ -0,0 +1,147 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INTERFACE FOR ALL ORDERING IMPLEMENTATIONS * */ +/* * * */ +/* * $Module: ORDER * */ +/* * * */ +/* * Copyright (C) 1997, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _ORDER_ +#define _ORDER_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "term.h" +#include "context.h" +#include "flags.h" +#include "symbol.h" + +/**************************************************************/ +/* TYPES and GLOBAL VARIABLES */ +/**************************************************************/ + +typedef enum { ord_UNCOMPARABLE, + ord_SMALLER_THAN, + ord_EQUAL, + ord_GREATER_THAN } ord_RESULT; + +/* This array is used to count variable occurrences in two terms. */ +/* It may be used by any available ordering. */ +extern NAT ord_VARCOUNT[symbol__MAXSTANDARDVAR][2]; + +/* A precedence is needed in almost every ordering function. */ +/* For performance reasons it is stored in a global variable, */ +/* instead of passing it to all those functions, which are */ +/* often recursive. Nevertheless this variable must not be */ +/* set externally! */ +extern PRECEDENCE ord_PRECEDENCE; + +/**************************************************************/ +/* INLINE FUNCTIONS */ +/**************************************************************/ + +static __inline__ ord_RESULT ord_Uncomparable(void) +{ + return ord_UNCOMPARABLE; +} + +static __inline__ ord_RESULT ord_Equal(void) +{ + return ord_EQUAL; +} + +static __inline__ ord_RESULT ord_GreaterThan(void) +{ + return ord_GREATER_THAN; +} + +static __inline__ ord_RESULT ord_SmallerThan(void) +{ + return ord_SMALLER_THAN; +} + +static __inline__ BOOL ord_IsGreaterThan(ord_RESULT Res) +{ + return ord_GREATER_THAN == Res; +} + +static __inline__ BOOL ord_IsNotGreaterThan(ord_RESULT Res) +{ + return ord_GREATER_THAN != Res; +} + +static __inline__ BOOL ord_IsSmallerThan(ord_RESULT Res) +{ + return ord_SMALLER_THAN == Res; +} + +static __inline__ BOOL ord_IsNotSmallerThan(ord_RESULT Res) +{ + return ord_SMALLER_THAN != Res; +} + +static __inline__ BOOL ord_IsEqual(ord_RESULT Res) +{ + return ord_EQUAL == Res; +} + +static __inline__ BOOL ord_IsUncomparable(ord_RESULT Res) +{ + return ord_UNCOMPARABLE == Res; +} + + + +/**************************************************************/ +/* FUNCTIONS */ +/**************************************************************/ + +ord_RESULT ord_Not(ord_RESULT); +ord_RESULT ord_Compare(TERM, TERM, FLAGSTORE, PRECEDENCE); +ord_RESULT ord_ContCompare(CONTEXT, TERM, CONTEXT, TERM, FLAGSTORE, PRECEDENCE); +BOOL ord_CompareEqual(TERM, TERM, FLAGSTORE); +BOOL ord_ContGreater(CONTEXT, TERM, CONTEXT, TERM, FLAGSTORE, PRECEDENCE); +ord_RESULT ord_LiteralCompare(TERM,BOOL,TERM,BOOL,BOOL, FLAGSTORE, PRECEDENCE); +void ord_Print(ord_RESULT); + +#endif diff --git a/test/spass/partition.c b/test/spass/partition.c new file mode 100644 index 0000000000000000000000000000000000000000..ac060da35be050401c23ffb9b5d91eb201b799b5 --- /dev/null +++ b/test/spass/partition.c @@ -0,0 +1,287 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * PARTITION * */ +/* * * */ +/* * $Module: PARTITION * */ +/* * * */ +/* * Copyright (C) 1999, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/**************************************************************/ +/* Include */ +/**************************************************************/ + +#include "partition.h" + + +/**************************************************************/ +/* Inline functions */ +/**************************************************************/ + +static __inline__ ECLASS part_GetClass(PARTITION p, ELEMENT e) +{ + return p[e]; +} + + +static __inline__ PARTITION part_SetClass(PARTITION p, ELEMENT e, ECLASS c) +{ + p[e] = c; + return p; +} + + +static __inline__ int part_GetClassSize(PARTITION p, ELEMENT e) +{ + return p[p[part_CARD] + e]; +} + + +static __inline__ PARTITION part_SetClassSize(PARTITION p, ELEMENT e, int + classsize) +{ + p[p[part_CARD] + e] = classsize; + return p; +} + + +static __inline__ int part_GetStamp(PARTITION p, ELEMENT e) +{ + return p[-part_HEAD - 1 - e]; +} + + +static __inline__ PARTITION part_SetStamp(PARTITION p, ELEMENT e, int stamp) +{ + p[-part_HEAD - 1 - e] = stamp; + return p; +} + + +static __inline__ BOOL part_Stamped(PARTITION p, ELEMENT e) +{ + return part_GetStamp(p, e) == p[part_STAMPCOUNTER]; +} + + +static __inline__ ELEMENT part_DelayedInit(PARTITION p, ELEMENT e) +/*************************************************************** + RETURNS: the (now stamped) element + EFFECT: establishes the equivalence class {e} in p, thus + partially initializing p +***************************************************************/ +{ + if (!part_Stamped(p, e)) { + part_SetClass(p, e, -e - 1); /* representative e (>= 0) of {e} is coded */ + /* as -e - 1 (< 0) */ + part_SetClassSize(p, e, 1); + part_SetStamp(p, e, p[part_STAMPCOUNTER]); + } + return e; +} + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +PARTITION part_Create(int size) +/**************************************************************** + RETURNS: the initial partition {{0}, {1}, {2}, ..., {size - 1}} + of the set {0, 1, 2, ..., size - 1} +****************************************************************/ +{ + PARTITION result; + +#ifdef CHECK + if (size < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In part_Create: negative size %d.", size); + misc_FinishErrorReport(); + } +#endif + + result = (PARTITION) memory_Calloc(size * 3 + part_HEAD, sizeof(int)) + + size + part_HEAD; /* move pointer to the middle of the array */ + /* to allow negative indices */ + result[part_CARD] = size; + result[part_ALLOC] = size * 3 + part_HEAD; + result[part_STAMPCOUNTER] = 1; + return result; +} + + +PARTITION part_Init(PARTITION p, int size) +/**************************************************************** + RETURNS: the initial partition {{0}, {1}, {2}, ..., {size - 1}} + of the set {0, 1, 2, ..., size - 1} + EFFECT: stores the initial partition to p if it's big enough, + otherwise creates a new partition, therefore + CAUTION: must be called inside an assignment like: + p = part_Init(p, ...) +****************************************************************/ +{ + int alloc, i; + +#ifdef CHECK + if (size < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In part_Init: negative size %d.", size); + misc_FinishErrorReport(); + } +#endif + + alloc = (p[part_ALLOC] - part_HEAD) / 3; + if (size > alloc) { + part_Free(p); + p = part_Create(size); + } + else { + p[part_CARD] = size; + p[part_STAMPCOUNTER]++; + + /* if a stamp overflow occurs, reinit stamps: */ + if (p[part_STAMPCOUNTER] <= 0) { + for (i = 0; i < alloc; i++) + part_SetStamp(p, i, 0); + p[part_STAMPCOUNTER] = 1; + } + + } + return p; +} + + +static ELEMENT part_NF(PARTITION p, ELEMENT e) +/*************************************************************** + RETURNS: the normal form element of the class [e]; this is an + element of [e] that sometimes differ from the + representative + EFFECT: makes the normal form to the direct parent of all + elements visited on the search path from e to this + normal form ("path compression") +***************************************************************/ +{ + ELEMENT nf, aux; + +#ifdef CHECK + if (!part_Element(p, e)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In part_NF: %d not in partitioned set.", e); + misc_FinishErrorReport(); + } +#endif + + nf = e; + while (part_GetClass(p, part_DelayedInit(p, nf)) >= 0) + nf = part_GetClass(p, nf); + + /* path compression: */ + while (e != nf) { + aux = part_GetClass(p, e); + part_SetClass(p, e, nf); + e = aux; + } + + return nf; +} + + +ECLASS part_Find(PARTITION p, ELEMENT e) +/*************************************************************** + RETURNS: (the representative of) class [e] +***************************************************************/ +{ + +#ifdef CHECK + if (!part_Element(p, e)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In part_Find: %d not in partitioned set.", e); + misc_FinishErrorReport(); + } +#endif + + return -part_GetClass(p, part_NF(p, e)) - 1; + /* representative e is coded as -e - 1 (cf. part_DelayedInit) */ +} + + +PARTITION part_Union(PARTITION p, ECLASS c1, ECLASS c2) +/*************************************************************** + RETURNS: the union of the classes + EFFECT: the representative of c1 is the representative of the + union +***************************************************************/ +{ + ELEMENT nf1, nf2, aux; + +#ifdef CHECK + if (!part_Element(p, c1)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In part_Union: first class %d not in partitioned set.", + c1); + misc_FinishErrorReport(); + } + if (!part_Element(p, c2)) { + misc_StartErrorReport(); + misc_ErrorReport + ("\n In part_Union: second class %d not in partitioned set.", c2); + misc_FinishErrorReport(); + } +#endif + + nf1 = part_NF(p, c1); + nf2 = part_NF(p, c2); + if (nf1 != nf2) { + + /* make [nf1] the bigger (or at least not smaller) class: */ + if (part_GetClassSize(p, nf1) < part_GetClassSize(p, nf2)) { + aux = nf1; + nf1 = nf2; + nf2 = aux; + part_SetClass(p, nf1, part_GetClass(p, nf2)); + part_SetClass(p, -part_GetClass(p, nf2) - 1, nf1); + } + + part_SetClass(p, nf2, nf1); + part_SetClassSize(p, nf1, + part_GetClassSize(p, nf1) + part_GetClassSize(p, nf2)); + } + return p; +} + diff --git a/test/spass/partition.h b/test/spass/partition.h new file mode 100644 index 0000000000000000000000000000000000000000..2de3aad7b3777932227e3d99b148d282b85fbe77 --- /dev/null +++ b/test/spass/partition.h @@ -0,0 +1,127 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * PARTITION * */ +/* * * */ +/* * $Module: PARTITION * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/* module manages partitions (i. e. sets of equivalence classes) of the set */ +/* {0, 1, 2, ..., size - 1} */ + +#ifndef _PARTITION_ +#define _PARTITION_ + + +/**************************************************************/ +/* Include */ +/**************************************************************/ + +#include "memory.h" + + +/**************************************************************/ +/* Constants and types */ +/**************************************************************/ + +#define part_CARD -1 /* index of cardinality of partitioned set */ +#define part_ALLOC -2 /* index of size of allocated space */ +#define part_STAMPCOUNTER -3 /* index of stampcounter */ +#define part_HEAD 3 /* length of head for management purposes */ + + +typedef int ELEMENT; +typedef ELEMENT ECLASS, *PARTITION; + +/* an equivalence class is represented by one of its elements, the */ +/* _representative_; a partition is an array to hold the size of the */ +/* partitioned set and of the allocated space, the equivalence classes, */ +/* their sizes and stamps and the stampcounter: */ +/* STAMPCOUNTER ALLOC CARD */ +/* | | | */ +/* -size - 3, ..., -4, -3, -2, -1, 0, ..., size - 1, size, ..., 2 * size - 1 */ +/* <--- stamp[] ----| |--- class[] --> |---- classsize[] ----> */ + + +/**************************************************************/ +/* Prototypes */ +/**************************************************************/ + +PARTITION part_Create(int); +PARTITION part_Init(PARTITION, int); +ECLASS part_Find(PARTITION, ELEMENT); + /* gets (the representative of) the class of the second argument */ +PARTITION part_Union(PARTITION, ECLASS, ECLASS); + /* unions the classes, the representative of the first class is the */ + /* representative of the union */ + + +/**************************************************************/ +/* Inline functions */ +/**************************************************************/ + +static __inline__ void part_Free(PARTITION p) +{ + if (p != NULL) + memory_Free( + p - (p[part_ALLOC] - part_HEAD) / 3 - part_HEAD, + p[part_ALLOC] * sizeof(int) + ); +} + + +static __inline__ int part_Size(PARTITION p) +{ + return p[part_CARD]; +} + + +static __inline__ BOOL part_Element(PARTITION p, ELEMENT e) +{ + return 0 <= e && e < part_Size(p); +} + + +static __inline__ BOOL part_Equivalent(PARTITION p, ELEMENT e1, ELEMENT e2) +{ + return part_Find(p, e1) == part_Find(p, e2); +} + + +#endif + diff --git a/test/spass/problem.dfg b/test/spass/problem.dfg new file mode 100644 index 0000000000000000000000000000000000000000..4527e6aaa0f95e6f009dc52c51e4a1a8f1190889 --- /dev/null +++ b/test/spass/problem.dfg @@ -0,0 +1,718 @@ +%-------------------------------------------------------------------------- +% File : SET505-6 : TPTP v2.2.1. Bugfixed v2.1.0. +% Domain : Set Theory +% Problem : Corollary 2 to universal class not set +% Version : [Qua92] axioms. +% English : + +% Refs : [BL+86] Boyer et al. (1986), Set Theory in First-Order Logic: +% : [Qua92] Quaife (1992), Automated Deduction in von Neumann-Bern +% Source : [Quaife] +% Names : SP6 cor.2 [Qua92] + +% Status : unsatisfiable +% Rating : 0.83 v2.2.0, 0.67 v2.1.0 +% Syntax : Number of clauses : 113 ( 8 non-Horn; 38 unit; 80 RR) +% Number of literals : 219 ( 49 equality) +% Maximal clause size : 5 ( 1 average) +% Number of predicates : 11 ( 0 propositional; 1-3 arity) +% Number of functors : 47 ( 13 constant; 0-3 arity) +% Number of variables : 214 ( 32 singleton) +% Maximal term depth : 6 ( 1 average) + +% Comments : Quaife proves all these problems by augmenting the axioms with +% all previously proved theorems. With a few exceptions (the +% problems that correspond to [BL+86] problems), the TPTP has +% retained the order in which Quaife presents the problems. The +% user may create an augmented version of this problem by adding +% all previously proved theorems (the ones that correspond to +% [BL+86] are easily identified and positioned using Quaife's +% naming scheme). +% : tptp2X -f dfg -t rm_equality:rstfp SET505-6.p +% Bugfixes : v1.0.1 - Bugfix in SET004-1.ax. +% : v2.1.0 - Bugfix in SET004-0.ax. +%-------------------------------------------------------------------------- + +begin_problem(TPTP_Problem). + +list_of_descriptions. +name({*[ File : SET505-6 : TPTP v2.2.1. Bugfixed v2.1.0.],[ Names : SP6 cor.2 [Qua92]]*}). +author({*[ Source : [Quaife]]*}). +status(unsatisfiable). +description({*[ Refs : [BL+86] Boyer et al. (1986), Set Theory in First-Order Logic: , : [Qua92] Quaife (1992), Automated Deduction in von Neumann-Bern]*}). +end_of_list. + +list_of_symbols. +functions[(application_function,0), (apply,2), (cantor,1), (choice,0), (complement,1), (compose,2), (compose_class,1), (composition_function,0), (cross_product,2), (diagonalise,1), (domain,3), (domain_of,1), (domain_relation,0), (element_relation,0), (first,1), (flip,1), (identity_relation,0), (image,2), (intersection,2), (inverse,1), (not_homomorphism1,3), (not_homomorphism2,3), (not_subclass_element,2), (null_class,0), (omega,0), (ordered_pair,2), (power_class,1), (range,3), (range_of,1), (regular,1), (restrict,3), (rotate,1), (second,1), (single_valued1,1), (single_valued2,1), (single_valued3,1), (singleton,1), (singleton_relation,0), (subset_relation,0), (successor,1), (successor_relation,0), (sum_class,1), (symmetric_difference,2), (union,2), (universal_class,0), (unordered_pair,2), (y,0)]. +predicates[(compatible,3), (function,1), (homomorphism,3), (inductive,1), (maps,3), (member,2), (one_to_one,1), (operation,1), (single_valued_class,1), (subclass,2)]. +end_of_list. + +list_of_clauses(axioms,cnf). + +clause( +forall([U,X,Y], +or( not(subclass(X,Y)), + not(member(U,X)), + member(U,Y))), +subclass_members ). + +clause( +forall([X,Y], +or( member(not_subclass_element(X,Y),X), + subclass(X,Y))), +not_subclass_members1 ). + +clause( +forall([X,Y], +or( not(member(not_subclass_element(X,Y),Y)), + subclass(X,Y))), +not_subclass_members2 ). + +clause( +forall([X], +or( subclass(X,universal_class))), +class_elements_are_sets ). + +clause( +forall([X,Y], +or( not(equal(X,Y)), + subclass(X,Y))), +equal_implies_subclass1 ). + +clause( +forall([X,Y], +or( not(equal(X,Y)), + subclass(Y,X))), +equal_implies_subclass2 ). + +clause( +forall([X,Y], +or( not(subclass(X,Y)), + not(subclass(Y,X)), + equal(X,Y))), +subclass_implies_equal ). + +clause( +forall([U,X,Y], +or( not(member(U,unordered_pair(X,Y))), + equal(U,X), + equal(U,Y))), +unordered_pair_member ). + +clause( +forall([X,Y], +or( not(member(X,universal_class)), + member(X,unordered_pair(X,Y)))), +unordered_pair2 ). + +clause( +forall([X,Y], +or( not(member(Y,universal_class)), + member(Y,unordered_pair(X,Y)))), +unordered_pair3 ). + +clause( +forall([X,Y], +or( member(unordered_pair(X,Y),universal_class))), +unordered_pairs_in_universal ). + +clause( +forall([X], +or( equal(unordered_pair(X,X),singleton(X)))), +singleton_set ). + +clause( +forall([X,Y], +or( equal(unordered_pair(singleton(X),unordered_pair(X,singleton(Y))),ordered_pair(X,Y)))), +ordered_pair ). + +clause( +forall([U,V,X,Y], +or( not(member(ordered_pair(U,V),cross_product(X,Y))), + member(U,X))), +cartesian_product1 ). + +clause( +forall([U,V,X,Y], +or( not(member(ordered_pair(U,V),cross_product(X,Y))), + member(V,Y))), +cartesian_product2 ). + +clause( +forall([U,V,X,Y], +or( not(member(U,X)), + not(member(V,Y)), + member(ordered_pair(U,V),cross_product(X,Y)))), +cartesian_product3 ). + +clause( +forall([X,Y,Z], +or( not(member(Z,cross_product(X,Y))), + equal(ordered_pair(first(Z),second(Z)),Z))), +cartesian_product4 ). + +clause( +or( subclass(element_relation,cross_product(universal_class,universal_class))), +element_relation1 ). + +clause( +forall([X,Y], +or( not(member(ordered_pair(X,Y),element_relation)), + member(X,Y))), +element_relation2 ). + +clause( +forall([X,Y], +or( not(member(ordered_pair(X,Y),cross_product(universal_class,universal_class))), + not(member(X,Y)), + member(ordered_pair(X,Y),element_relation))), +element_relation3 ). + +clause( +forall([X,Y,Z], +or( not(member(Z,intersection(X,Y))), + member(Z,X))), +intersection1 ). + +clause( +forall([X,Y,Z], +or( not(member(Z,intersection(X,Y))), + member(Z,Y))), +intersection2 ). + +clause( +forall([X,Y,Z], +or( not(member(Z,X)), + not(member(Z,Y)), + member(Z,intersection(X,Y)))), +intersection3 ). + +clause( +forall([X,Z], +or( not(member(Z,complement(X))), + not(member(Z,X)))), +complement1 ). + +clause( +forall([X,Z], +or( not(member(Z,universal_class)), + member(Z,complement(X)), + member(Z,X))), +complement2 ). + +clause( +forall([X,Y], +or( equal(complement(intersection(complement(X),complement(Y))),union(X,Y)))), +union ). + +clause( +forall([X,Y], +or( equal(intersection(complement(intersection(X,Y)),complement(intersection(complement(X),complement(Y)))),symmetric_difference(X,Y)))), +symmetric_difference ). + +clause( +forall([X,Xr,Y], +or( equal(intersection(Xr,cross_product(X,Y)),restrict(Xr,X,Y)))), +restriction1 ). + +clause( +forall([X,Xr,Y], +or( equal(intersection(cross_product(X,Y),Xr),restrict(Xr,X,Y)))), +restriction2 ). + +clause( +forall([X,Z], +or( not(equal(restrict(X,singleton(Z),universal_class),null_class)), + not(member(Z,domain_of(X))))), +domain1 ). + +clause( +forall([X,Z], +or( not(member(Z,universal_class)), + equal(restrict(X,singleton(Z),universal_class),null_class), + member(Z,domain_of(X)))), +domain2 ). + +clause( +forall([X], +or( subclass(rotate(X),cross_product(cross_product(universal_class,universal_class),universal_class)))), +rotate1 ). + +clause( +forall([U,V,W,X], +or( not(member(ordered_pair(ordered_pair(U,V),W),rotate(X))), + member(ordered_pair(ordered_pair(V,W),U),X))), +rotate2 ). + +clause( +forall([U,V,W,X], +or( not(member(ordered_pair(ordered_pair(V,W),U),X)), + not(member(ordered_pair(ordered_pair(U,V),W),cross_product(cross_product(universal_class,universal_class),universal_class))), + member(ordered_pair(ordered_pair(U,V),W),rotate(X)))), +rotate3 ). + +clause( +forall([X], +or( subclass(flip(X),cross_product(cross_product(universal_class,universal_class),universal_class)))), +flip1 ). + +clause( +forall([U,V,W,X], +or( not(member(ordered_pair(ordered_pair(U,V),W),flip(X))), + member(ordered_pair(ordered_pair(V,U),W),X))), +flip2 ). + +clause( +forall([U,V,W,X], +or( not(member(ordered_pair(ordered_pair(V,U),W),X)), + not(member(ordered_pair(ordered_pair(U,V),W),cross_product(cross_product(universal_class,universal_class),universal_class))), + member(ordered_pair(ordered_pair(U,V),W),flip(X)))), +flip3 ). + +clause( +forall([Y], +or( equal(domain_of(flip(cross_product(Y,universal_class))),inverse(Y)))), +inverse ). + +clause( +forall([Z], +or( equal(domain_of(inverse(Z)),range_of(Z)))), +range_of ). + +clause( +forall([X,Y,Z], +or( equal(first(not_subclass_element(restrict(Z,X,singleton(Y)),null_class)),domain(Z,X,Y)))), +domain ). + +clause( +forall([X,Y,Z], +or( equal(second(not_subclass_element(restrict(Z,singleton(X),Y),null_class)),range(Z,X,Y)))), +range ). + +clause( +forall([X,Xr], +or( equal(range_of(restrict(Xr,X,universal_class)),image(Xr,X)))), +image ). + +clause( +forall([X], +or( equal(union(X,singleton(X)),successor(X)))), +successor ). + +clause( +or( subclass(successor_relation,cross_product(universal_class,universal_class))), +successor_relation1 ). + +clause( +forall([X,Y], +or( not(member(ordered_pair(X,Y),successor_relation)), + equal(successor(X),Y))), +successor_relation2 ). + +clause( +forall([X,Y], +or( not(equal(successor(X),Y)), + not(member(ordered_pair(X,Y),cross_product(universal_class,universal_class))), + member(ordered_pair(X,Y),successor_relation))), +successor_relation3 ). + +clause( +forall([X], +or( not(inductive(X)), + member(null_class,X))), +inductive1 ). + +clause( +forall([X], +or( not(inductive(X)), + subclass(image(successor_relation,X),X))), +inductive2 ). + +clause( +forall([X], +or( not(member(null_class,X)), + not(subclass(image(successor_relation,X),X)), + inductive(X))), +inductive3 ). + +clause( +or( inductive(omega)), +omega_is_inductive1 ). + +clause( +forall([Y], +or( not(inductive(Y)), + subclass(omega,Y))), +omega_is_inductive2 ). + +clause( +or( member(omega,universal_class)), +omega_in_universal ). + +clause( +forall([X], +or( equal(domain_of(restrict(element_relation,universal_class,X)),sum_class(X)))), +sum_class_definition ). + +clause( +forall([X], +or( not(member(X,universal_class)), + member(sum_class(X),universal_class))), +sum_class2 ). + +clause( +forall([X], +or( equal(complement(image(element_relation,complement(X))),power_class(X)))), +power_class_definition ). + +clause( +forall([U], +or( not(member(U,universal_class)), + member(power_class(U),universal_class))), +power_class2 ). + +clause( +forall([Xr,Yr], +or( subclass(compose(Yr,Xr),cross_product(universal_class,universal_class)))), +compose1 ). + +clause( +forall([Xr,Y,Yr,Z], +or( not(member(ordered_pair(Y,Z),compose(Yr,Xr))), + member(Z,image(Yr,image(Xr,singleton(Y)))))), +compose2 ). + +clause( +forall([Xr,Y,Yr,Z], +or( not(member(Z,image(Yr,image(Xr,singleton(Y))))), + not(member(ordered_pair(Y,Z),cross_product(universal_class,universal_class))), + member(ordered_pair(Y,Z),compose(Yr,Xr)))), +compose3 ). + +clause( +forall([X], +or( not(single_valued_class(X)), + subclass(compose(X,inverse(X)),identity_relation))), +single_valued_class1 ). + +clause( +forall([X], +or( not(subclass(compose(X,inverse(X)),identity_relation)), + single_valued_class(X))), +single_valued_class2 ). + +clause( +forall([Xf], +or( not(function(Xf)), + subclass(Xf,cross_product(universal_class,universal_class)))), +function1 ). + +clause( +forall([Xf], +or( not(function(Xf)), + subclass(compose(Xf,inverse(Xf)),identity_relation))), +function2 ). + +clause( +forall([Xf], +or( not(subclass(Xf,cross_product(universal_class,universal_class))), + not(subclass(compose(Xf,inverse(Xf)),identity_relation)), + function(Xf))), +function3 ). + +clause( +forall([X,Xf], +or( not(function(Xf)), + not(member(X,universal_class)), + member(image(Xf,X),universal_class))), +replacement ). + +clause( +forall([X], +or( equal(X,null_class), + member(regular(X),X))), +regularity1 ). + +clause( +forall([X], +or( equal(X,null_class), + equal(intersection(X,regular(X)),null_class))), +regularity2 ). + +clause( +forall([Xf,Y], +or( equal(sum_class(image(Xf,singleton(Y))),apply(Xf,Y)))), +apply ). + +clause( +or( function(choice)), +choice1 ). + +clause( +forall([Y], +or( not(member(Y,universal_class)), + equal(Y,null_class), + member(apply(choice,Y),Y))), +choice2 ). + +clause( +forall([Xf], +or( not(one_to_one(Xf)), + function(Xf))), +one_to_one1 ). + +clause( +forall([Xf], +or( not(one_to_one(Xf)), + function(inverse(Xf)))), +one_to_one2 ). + +clause( +forall([Xf], +or( not(function(inverse(Xf))), + not(function(Xf)), + one_to_one(Xf))), +one_to_one3 ). + +clause( +or( equal(intersection(cross_product(universal_class,universal_class),intersection(cross_product(universal_class,universal_class),complement(compose(complement(element_relation),inverse(element_relation))))),subset_relation)), +subset_relation ). + +clause( +or( equal(intersection(inverse(subset_relation),subset_relation),identity_relation)), +identity_relation ). + +clause( +forall([Xr], +or( equal(complement(domain_of(intersection(Xr,identity_relation))),diagonalise(Xr)))), +diagonalisation ). + +clause( +forall([X], +or( equal(intersection(domain_of(X),diagonalise(compose(inverse(element_relation),X))),cantor(X)))), +cantor_class ). + +clause( +forall([Xf], +or( not(operation(Xf)), + function(Xf))), +operation1 ). + +clause( +forall([Xf], +or( not(operation(Xf)), + equal(cross_product(domain_of(domain_of(Xf)),domain_of(domain_of(Xf))),domain_of(Xf)))), +operation2 ). + +clause( +forall([Xf], +or( not(operation(Xf)), + subclass(range_of(Xf),domain_of(domain_of(Xf))))), +operation3 ). + +clause( +forall([Xf], +or( not(function(Xf)), + not(equal(cross_product(domain_of(domain_of(Xf)),domain_of(domain_of(Xf))),domain_of(Xf))), + not(subclass(range_of(Xf),domain_of(domain_of(Xf)))), + operation(Xf))), +operation4 ). + +clause( +forall([Xf1,Xf2,Xh], +or( not(compatible(Xh,Xf1,Xf2)), + function(Xh))), +compatible1 ). + +clause( +forall([Xf1,Xf2,Xh], +or( not(compatible(Xh,Xf1,Xf2)), + equal(domain_of(domain_of(Xf1)),domain_of(Xh)))), +compatible2 ). + +clause( +forall([Xf1,Xf2,Xh], +or( not(compatible(Xh,Xf1,Xf2)), + subclass(range_of(Xh),domain_of(domain_of(Xf2))))), +compatible3 ). + +clause( +forall([Xf1,Xf2,Xh], +or( not(function(Xh)), + not(equal(domain_of(domain_of(Xf1)),domain_of(Xh))), + not(subclass(range_of(Xh),domain_of(domain_of(Xf2)))), + compatible(Xh,Xf1,Xf2))), +compatible4 ). + +clause( +forall([Xf1,Xf2,Xh], +or( not(homomorphism(Xh,Xf1,Xf2)), + operation(Xf1))), +homomorphism1 ). + +clause( +forall([Xf1,Xf2,Xh], +or( not(homomorphism(Xh,Xf1,Xf2)), + operation(Xf2))), +homomorphism2 ). + +clause( +forall([Xf1,Xf2,Xh], +or( not(homomorphism(Xh,Xf1,Xf2)), + compatible(Xh,Xf1,Xf2))), +homomorphism3 ). + +clause( +forall([X,Xf1,Xf2,Xh,Y], +or( not(homomorphism(Xh,Xf1,Xf2)), + not(member(ordered_pair(X,Y),domain_of(Xf1))), + equal(apply(Xf2,ordered_pair(apply(Xh,X),apply(Xh,Y))),apply(Xh,apply(Xf1,ordered_pair(X,Y)))))), +homomorphism4 ). + +clause( +forall([Xf1,Xf2,Xh], +or( not(operation(Xf1)), + not(operation(Xf2)), + not(compatible(Xh,Xf1,Xf2)), + member(ordered_pair(not_homomorphism1(Xh,Xf1,Xf2),not_homomorphism2(Xh,Xf1,Xf2)),domain_of(Xf1)), + homomorphism(Xh,Xf1,Xf2))), +homomorphism5 ). + +clause( +forall([Xf1,Xf2,Xh], +or( not(operation(Xf1)), + not(operation(Xf2)), + not(compatible(Xh,Xf1,Xf2)), + not(equal(apply(Xf2,ordered_pair(apply(Xh,not_homomorphism1(Xh,Xf1,Xf2)),apply(Xh,not_homomorphism2(Xh,Xf1,Xf2)))),apply(Xh,apply(Xf1,ordered_pair(not_homomorphism1(Xh,Xf1,Xf2),not_homomorphism2(Xh,Xf1,Xf2)))))), + homomorphism(Xh,Xf1,Xf2))), +homomorphism6 ). + +clause( +forall([X], +or( subclass(compose_class(X),cross_product(universal_class,universal_class)))), +compose_class_definition1 ). + +clause( +forall([X,Y,Z], +or( not(member(ordered_pair(Y,Z),compose_class(X))), + equal(compose(X,Y),Z))), +compose_class_definition2 ). + +clause( +forall([X,Y,Z], +or( not(member(ordered_pair(Y,Z),cross_product(universal_class,universal_class))), + not(equal(compose(X,Y),Z)), + member(ordered_pair(Y,Z),compose_class(X)))), +compose_class_definition3 ). + +clause( +or( subclass(composition_function,cross_product(universal_class,cross_product(universal_class,universal_class)))), +definition_of_composition_function1 ). + +clause( +forall([X,Y,Z], +or( not(member(ordered_pair(X,ordered_pair(Y,Z)),composition_function)), + equal(compose(X,Y),Z))), +definition_of_composition_function2 ). + +clause( +forall([X,Y], +or( not(member(ordered_pair(X,Y),cross_product(universal_class,universal_class))), + member(ordered_pair(X,ordered_pair(Y,compose(X,Y))),composition_function))), +definition_of_composition_function3 ). + +clause( +or( subclass(domain_relation,cross_product(universal_class,universal_class))), +definition_of_domain_relation1 ). + +clause( +forall([X,Y], +or( not(member(ordered_pair(X,Y),domain_relation)), + equal(domain_of(X),Y))), +definition_of_domain_relation2 ). + +clause( +forall([X], +or( not(member(X,universal_class)), + member(ordered_pair(X,domain_of(X)),domain_relation))), +definition_of_domain_relation3 ). + +clause( +forall([X], +or( equal(first(not_subclass_element(compose(X,inverse(X)),identity_relation)),single_valued1(X)))), +single_valued_term_defn1 ). + +clause( +forall([X], +or( equal(second(not_subclass_element(compose(X,inverse(X)),identity_relation)),single_valued2(X)))), +single_valued_term_defn2 ). + +clause( +forall([X], +or( equal(domain(X,image(inverse(X),singleton(single_valued1(X))),single_valued2(X)),single_valued3(X)))), +single_valued_term_defn3 ). + +clause( +or( equal(intersection(complement(compose(element_relation,complement(identity_relation))),element_relation),singleton_relation)), +compose_can_define_singleton ). + +clause( +or( subclass(application_function,cross_product(universal_class,cross_product(universal_class,universal_class)))), +application_function_defn1 ). + +clause( +forall([X,Y,Z], +or( not(member(ordered_pair(X,ordered_pair(Y,Z)),application_function)), + member(Y,domain_of(X)))), +application_function_defn2 ). + +clause( +forall([X,Y,Z], +or( not(member(ordered_pair(X,ordered_pair(Y,Z)),application_function)), + equal(apply(X,Y),Z))), +application_function_defn3 ). + +clause( +forall([X,Y,Z], +or( not(member(ordered_pair(X,ordered_pair(Y,Z)),cross_product(universal_class,cross_product(universal_class,universal_class)))), + not(member(Y,domain_of(X))), + member(ordered_pair(X,ordered_pair(Y,apply(X,Y))),application_function))), +application_function_defn4 ). + +clause( +forall([X,Xf,Y], +or( not(maps(Xf,X,Y)), + function(Xf))), +maps1 ). + +clause( +forall([X,Xf,Y], +or( not(maps(Xf,X,Y)), + equal(domain_of(Xf),X))), +maps2 ). + +clause( +forall([X,Xf,Y], +or( not(maps(Xf,X,Y)), + subclass(range_of(Xf),Y))), +maps3 ). + +clause( +forall([Xf,Y], +or( not(function(Xf)), + not(subclass(range_of(Xf),Y)), + maps(Xf,domain_of(Xf),Y))), +maps4 ). + +end_of_list. + +list_of_clauses(conjectures,cnf). + +clause( %(conjecture) +or( member(ordered_pair(universal_class,y),cross_product(universal_class,universal_class))), +prove_corollary_2_to_universal_class_not_set_1 ). + +end_of_list. + +end_problem. +%-------------------------------------------------------------------------- diff --git a/test/spass/proofcheck.c b/test/spass/proofcheck.c new file mode 100644 index 0000000000000000000000000000000000000000..15010d931ed36cc7287c37f00859d7e1b4ae6540 --- /dev/null +++ b/test/spass/proofcheck.c @@ -0,0 +1,1391 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * PROOF CHECKING * */ +/* * * */ +/* * Copyright (C) 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ + +/* $RCSfile$ */ + +#include "proofcheck.h" + + +/* options */ +int pcheck_Timelimit; +const char *pcheck_ProofFileSuffix; +BOOL pcheck_Quiet; + +/* options for graph generation */ +BOOL pcheck_ClauseCg; +BOOL pcheck_GenNamedCg, pcheck_GenRedCg; +const char *pcheck_CgName, *pcheck_RedCgName; +GRAPHFORMAT pcheck_GraphFormat; + + +static int pcheck_MaxSplitLevel(LIST Clauses) +/************************************************************** + INPUT: A list of clauses. + RETURNS: The maximum split level of a clause. +***************************************************************/ +{ + int Max; + int Act; + + Max = 0; + while (!list_Empty(Clauses)) { + Act = clause_SplitLevel(list_Car(Clauses)); + if (Act > Max) + Max = Act; + Clauses = list_Cdr(Clauses); + } + return Max; +} + + +static __inline__ int pcheck_MaxParentSplitLevel(CLAUSE Clause) +/************************************************************** + INPUT: A clause + RETURNS: The max split level of the parent clauses +***************************************************************/ +{ + return pcheck_MaxSplitLevel(clause_ParentClauses(Clause)); +} + + +static BOOL pcheck_ClauseIsFromLeftSplit(CLAUSE Clause) +/************************************************************** + INPUT : A Clause + RETURNS: TRUE iff the clause is the left half of a split + CAUTION: This works also for clauses without parents, since + pcheck_MaxParentSplitLevel returns 0 in that case. +***************************************************************/ +{ + return (clause_SplitLevel(Clause) > pcheck_MaxParentSplitLevel(Clause)); +} + + +static BOOL pcheck_ClauseIsFromRightSplit(CLAUSE Clause) +/************************************************************** + INPUT: A clause + RETURNS: TRUE iff the clause is from the right half of a split +***************************************************************/ +{ + if (list_Empty(clause_ParentClauses(Clause))) + return FALSE; + + return clause_IsEmptyClause(list_Car(clause_ParentClauses(Clause))); +} + +static BOOL pcheck_ClauseIsFromSplit(CLAUSE Clause) +/************************************************************** + INPUT : A clause + RETURNS: TRUE iff the clause is from a split +***************************************************************/ +{ + return (pcheck_ClauseIsFromRightSplit(Clause) || + pcheck_ClauseIsFromLeftSplit(Clause)); +} + + +static int pcheck_LabelToNumber(const char* Label) +/************************************************************** + INPUT: A clause label + RETURNS: The label converted to a number. + EFFECT: If the conversion fails an error message is printed + and the program exits. +***************************************************************/ +{ + int Number; + + if (!string_StringToInt(Label, FALSE, &Number)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In pcheck_LabelToNumber:"); + misc_UserErrorReport(" Could not convert clause"); + misc_UserErrorReport(" label %s to a number.\n", Label); + misc_FinishUserErrorReport(); + } + + return Number; +} + + +static int pcheck_CompareNumberAndClause(const void* Number, const void* ClausePtr) +/************************************************************** + INPUT: A number and a pointer to a CLAUSE. + RETURNS: 1) a negative number if <number> is < number of <Clause> + 2) 0 if <Number> is equal to the number of <Clause> + 3) a positive number if <Number> is > number of <Clause> + EFFECT: This function is used as parameter to the bsearch function. +***************************************************************/ +{ + return (int)Number - clause_Number(*(const CLAUSE*)ClausePtr); +} + + +static void pcheck_ParentNumbersToPointersInVector(CLAUSE* ClauseVector, int Size) +/************************************************************** + INPUT: A clause vector without duplicate clauses and the maximal + number of elements in the vector + EFFECTS: All clause parent numbers are replaced by pointers + to the parents. + CAUTION: The clause vector has to be sorted by increasing + clause numbers, since this function performs a binary search + on the vector. +***************************************************************/ +{ + int Position; + LIST NewParents, OldParents; + LIST ScanParents; + int ParentNum; + CLAUSE* Parent; + + for (Position = 0; Position < Size; Position++) { + OldParents = clause_ParentClauses(ClauseVector[Position]); + NewParents = list_Copy(OldParents); + + for (ScanParents = NewParents; !list_Empty(ScanParents); ScanParents = list_Cdr(ScanParents)) { + ParentNum = (int)list_Car(ScanParents); + /* Binary search for parent clause with number <ParentNum>. */ + Parent = bsearch((const void*)ParentNum, ClauseVector, Size, + sizeof(CLAUSE), pcheck_CompareNumberAndClause); + if (Parent != NULL) + list_Rplaca(ScanParents, *Parent); + else { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Missing parent clause %d of clause %d.\n", + ParentNum, clause_Number(ClauseVector[Position])); + misc_FinishUserErrorReport(); + } + } + clause_SetParentClauses(ClauseVector[Position], NewParents); + list_Delete(OldParents); + } +} + + +static LIST pcheck_ForceParentNumbersToPointersInVector(CLAUSE* ClauseVector, + int Size) +/************************************************************** + INPUT: A clause vector, possibly with duplicates + RETURNS: All numbers of clauses <c> that are missing a parent clause + from the transitive hull of parent clauses of <c>. + EFFECTS: All MARKED and HIDDEN flags of the clauses are changed. + All parent numbers are converted to pointers, if the + parents exist, otherwise the parent number is deleted + from the list. + The parent literal list is changed accordingly. + A clause <c> is marked as HIDDEN, if any clause + from the transitive hull of parent clauses of <c> + was missing in <ClauseVector>. +***************************************************************/ +{ + int Position; + LIST NewParents, NewPLits, Parents, PLits, Missing; + int ParentNum, PLitNum; + CLAUSE *Parent, Clause; + + Missing = list_Nil(); + + for (Position = 0; Position < Size; Position++) { + clause_RemoveFlag(ClauseVector[Position], MARKED); + clause_RemoveFlag(ClauseVector[Position], HIDDEN); + } + + for (Position = 0; Position < Size; Position++) { + Clause = ClauseVector[Position]; + if (!clause_GetFlag(Clause, MARKED)) { + clause_SetFlag(Clause, MARKED); + Parents = clause_ParentClauses(Clause); + PLits = clause_ParentLiterals(Clause); + NewParents = list_Nil(); + NewPLits = list_Nil(); + + while (!list_Empty(Parents)) { + ParentNum = (int)list_Car(Parents); + PLitNum = (int)list_Car(PLits); + /* Binary search for parent clause with number <ParentNum>. */ + Parent = bsearch((const void*)ParentNum, ClauseVector, Size, + sizeof(CLAUSE), pcheck_CompareNumberAndClause); + if (Parent == NULL) { + Missing = list_Cons((POINTER)ParentNum, Missing); + clause_SetFlag(Clause, HIDDEN); + } else { + if (clause_GetFlag(*Parent, HIDDEN)) + clause_SetFlag(Clause, HIDDEN); + NewParents = list_Cons((POINTER)*Parent, NewParents); + NewPLits = list_Cons((POINTER)PLitNum, NewPLits); + } + Parents = list_Cdr(Parents); + PLits = list_Cdr(PLits); + } + list_Delete(clause_ParentClauses(Clause)); + list_Delete(clause_ParentLiterals(Clause)); + NewParents = list_NReverse(NewParents); + NewPLits = list_NReverse(NewPLits); + clause_SetParentClauses(Clause, NewParents); + clause_SetParentLiterals(Clause, NewPLits); + } /* if clause is not marked */ + } /* for all clauses */ + + return Missing; +} + + +static int pcheck_CompareClauseNumber(const void* C1, const void* C2) +/************************************************************** + INPUT : Two pointers to CLAUSEs. + RETURNS: 1) a negative number if the number of C1 is < number of C2. + 2) 0 if C1 and C2 have the same clause number + (that means a possible bug in SPASS) + 3) a positive number if number of C1 > number of C2 + EFFECT: This function is used as parameter to the qsort function. +************************************************************/ +{ + return clause_Number(*(const CLAUSE*)C1) - clause_Number(*(const CLAUSE*)C2); +} + + +static LIST pcheck_ConvertParentsInList(LIST List) +/************************************************************** + INPUT: A list of clauses. + RETURNS: The list of missing parent clause numbers from the list + EFFECTS: Parent numbers are converted to pointers +***************************************************************/ +{ + int Size, Index; + CLAUSE* ClauseVector; + LIST Missing; + + Size = list_Length(List); + if (Size == 0) + return list_Nil(); + + /* convert list into vector for binary search */ + ClauseVector = (CLAUSE*)memory_Malloc(sizeof(CLAUSE) * Size); + for (Index = 0; !list_Empty(List); List = list_Cdr(List), Index++) + ClauseVector[Index] = list_Car(List); + + /* sort the clauses in vector by increasing clause number */ + qsort(ClauseVector, Size, sizeof(CLAUSE), pcheck_CompareClauseNumber); + + /* convert parent lists */ + Missing = pcheck_ForceParentNumbersToPointersInVector(ClauseVector, Size); + + memory_Free(ClauseVector, sizeof(CLAUSE) * Size); + return Missing; +} + + +LIST pcheck_ConvertParentsInSPASSProof(PROOFSEARCH Search, LIST EmptyClauses) +/************************************************************** + INPUT : A proofsearch object with clauses sorted by weight + and an unsorted list <EmptyClauses> + RETURNS: The lists, where the clauses in <EmptyClauses> are + now sorted by weight, and parent numbers + in the clauses are replaced by parent pointers +***************************************************************/ +{ + LIST AllLists; + LIST Missing; + + AllLists = list_Nconc(list_Copy(prfs_DocProofClauses(Search)), + list_Copy(EmptyClauses)); + AllLists = list_Nconc(list_Copy(prfs_UsableClauses(Search)), AllLists); + AllLists = list_Nconc(list_Copy(prfs_WorkedOffClauses(Search)), AllLists); + + AllLists = pcheck_ClauseNumberMergeSort(AllLists); + Missing = pcheck_ConvertParentsInList(AllLists); + list_Delete(AllLists); + + return Missing; +} + + +static LIST pcheck_ParentNumbersToParents(LIST Proof) +/************************************************************** + INPUT: A list of clauses, representing a proof. + RETURNS: The list, where parent numbers in the + parent list of clauses are replaced + by the parents (pointers). + CAUTION: For finding the clause corresponding to a + a clause number, the <Proof> list is searched + with binary search. This is correct only if + the clause numbers in <Proof> are increasing. +************************************************************/ +{ + LIST ScanClauses; + int ProofLength, Position; + CLAUSE* ClauseVector; + + if (list_Empty(Proof)) + return list_Nil(); + + /* convert list into vector for binary search */ + ProofLength = list_Length(Proof); + ClauseVector = (CLAUSE*) memory_Malloc(ProofLength * sizeof(CLAUSE)); + + for (ScanClauses = Proof, Position = 0; !list_Empty(ScanClauses); + ScanClauses = list_Cdr(ScanClauses), Position++) { + ClauseVector[Position] = list_Car(ScanClauses); + } + + /* sort the clauses in vector by increasing clause number */ + qsort(ClauseVector, ProofLength, sizeof(CLAUSE), pcheck_CompareClauseNumber); + + /* convert parent lists */ + pcheck_ParentNumbersToPointersInVector(ClauseVector, ProofLength); + + memory_Free(ClauseVector, ProofLength * sizeof(CLAUSE)); + + return Proof; +} + + +LIST pcheck_ParentPointersToParentNumbers(LIST Clauses) +/************************************************************** + INPUT : A list of clauses + RETURNS: The list with parent pointers replaced by + parent numbers + EFFECTS: Sets marks on all clauses. +***************************************************************/ +{ + LIST ScanClauses; + LIST ScanParents; + + pcheck_ClauseListRemoveFlag(Clauses, MARKED); + + for (ScanClauses = Clauses; !list_Empty(ScanClauses); ScanClauses = list_Cdr(ScanClauses)) { + if (!clause_GetFlag(list_Car(ScanClauses), MARKED)) { + for (ScanParents = clause_ParentClauses(list_Car(ScanClauses)); !list_Empty(ScanParents); + ScanParents = list_Cdr(ScanParents)) + list_Rplaca(ScanParents, (POINTER)clause_Number(list_Car(ScanParents))); + clause_SetFlag(list_Car(ScanClauses), MARKED); + } + } + return Clauses; +} + + +LIST pcheck_ConvertTermListToClauseList(LIST ProofRest, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A list of quintupels (lists) representing a proof, + a flag store, and a precedence. + RETURNS: The conversion of this list into the internal clause + structure. For each clause, the numbers of parent + clauses are replaced by pointers to the parents. +***************************************************************/ +{ + LIST Clauses; + LIST ProofLine; + TERM ClauseTerm; + CLAUSE Clause; + int Level; + int ClauseNumber; + LIST ParentLabels; + LIST ParentIds; + LIST ParentLits; /* this is a dummy list; parent lits are not yet specified in a SPASS proof */ + RULE Origin; + char* ClauseLabel; + + Clauses = list_Nil(); /* result */ + + while (!list_Empty(ProofRest)) { + /* break proof line into components */ + ProofLine = list_Car(ProofRest); + + ClauseLabel = list_First(ProofLine); + ClauseTerm = list_Second(ProofLine); + /* replace by NULL clause, since dfg_CreateClauseFromTerm deletes clause ! */ + list_Rplaca(list_Cdr(ProofLine), clause_Null()); + ParentLabels = (LIST)list_Third(ProofLine); + Level = (int)list_Fourth(ProofLine); + Origin = (RULE)list_Fifth(ProofLine); + + /* Conversion */ + Clause = dfg_CreateClauseFromTerm(ClauseTerm, TRUE, Flags,Precedence); + /* It's necessary to update the weight since dfg_CreateClauseFromTerm */ + /* doesn't set it. */ + clause_UpdateWeight(Clause, Flags); + ClauseNumber = pcheck_LabelToNumber(ClauseLabel); + ParentIds = list_Nil(); + ParentLits = list_Nil(); + + while (!list_Empty(ParentLabels)) { + ParentIds = list_Cons((POINTER)pcheck_LabelToNumber(list_Car(ParentLabels)), ParentIds); + ParentLits = list_Cons(0, ParentLits); + ParentLabels = list_Cdr(ParentLabels); + } + + /* set all data */ + clause_SetNumber(Clause, ClauseNumber); + ParentIds = list_NReverse(ParentIds); + clause_SetParentClauses(Clause, ParentIds); + clause_SetParentLiterals(Clause, ParentLits); + Clause->origin = Origin; + + clause_SetSplitLevel(Clause, Level); + if (Level > 0) { + clause_ClearSplitField(Clause); + clause_SetSplitFieldBit(Clause, Level); + } else + clause_SetSplitField(Clause, (SPLITFIELD)NULL,0); + + clause_RemoveFlag(Clause, MARKED); + Clauses = list_Cons(Clause, Clauses); + ProofRest = list_Cdr(ProofRest); + } + Clauses = list_NReverse(Clauses); + + /* convert parent numbers to pointers */ + Clauses = pcheck_ParentNumbersToParents(Clauses); + + return Clauses; +} + + +static BOOL pcheck_ClauseIsUnmarked(CLAUSE C) +/************************************************************** + INPUT: A clause + RETURNS: The value of the clauses MARKED flag +***************************************************************/ +{ + return !clause_GetFlag(C, MARKED); +} + + +static void pcheck_RemoveUnmarkedFromTableau(TABLEAU T) +/************************************************************** + INPUT: A tableau + RETURNS: Nothing. + EFFECTS: Delete all clauses that have the MARKED flag + set from tableau. +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return; + + tab_SetClauses(T, list_DeleteElementIf(tab_Clauses(T), + (BOOL (*)(POINTER))pcheck_ClauseIsUnmarked)); + + pcheck_RemoveUnmarkedFromTableau(tab_LeftBranch(T)); + pcheck_RemoveUnmarkedFromTableau(tab_RightBranch(T)); +} + + +static void pcheck_CollectUnmarkedSplits(TABLEAU T, LIST* Splits) +/************************************************************** + INPUT: A tableau, a list of clauses by reference + RETURNS: Nothing. + EFFECTS: Add all split clauses in the tableau that are not + marked to the <Splits> list. +***************************************************************/ +{ + LIST Scan; + + if (tab_IsEmpty(T)) + return; + + for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (!clause_GetFlag(list_Car(Scan), MARKED) && clause_IsFromSplitting(list_Car(Scan))) + (*Splits) = list_Cons(list_Car(Scan), *Splits); + } + + pcheck_CollectUnmarkedSplits(tab_LeftBranch(T), Splits); + pcheck_CollectUnmarkedSplits(tab_RightBranch(T), Splits); +} + + +/* EK: unused, only recursive */ +static void pcheck_TableauSplitsComplete(TABLEAU T) +/************************************************************** + INPUT : A tableau + RETURNS: Checks that every split has exactly two or no + successors. This condition must be true after + tab_RemoveRedundantSplits has been called. +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return; + + if (tab_RightBranchIsEmpty(T) && !tab_LeftBranchIsEmpty(T)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Split of clause %d has no right branch.\n", + clause_Number(tab_SplitClause(T))); + misc_FinishUserErrorReport(); + } + + if (!tab_RightBranchIsEmpty(T) && tab_LeftBranchIsEmpty(T)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Split of clause %d has no left branch.\n", + clause_Number(tab_SplitClause(T))); + misc_FinishUserErrorReport(); + } + + pcheck_TableauSplitsComplete(tab_LeftBranch(T)); + pcheck_TableauSplitsComplete(tab_RightBranch(T)); +} + + +static void pcheck_RightSplitParents(CLAUSE SplitClause, CLAUSE RightSplitClause, + CLAUSE LeftSplitClause) +/************************************************************** + INPUT: A split clause, and its left and right successors + EFFECTS: Prints an error message if the split is not correctly + closed. +***************************************************************/ +{ + LIST Scan; + BOOL HasEmpty, ContainsSplitClause; + + HasEmpty = ContainsSplitClause = FALSE; + + for (Scan = clause_ParentClauses(RightSplitClause); + !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (clause_IsEmptyClause(list_Car(Scan))) + HasEmpty = TRUE; + if (clause_Number(list_Car(Scan)) == clause_Number(SplitClause)) + ContainsSplitClause = TRUE; + } + + if (!HasEmpty) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Right split clause %d has no empty clause as parent.\n", + clause_Number(SplitClause)); + misc_FinishUserErrorReport(); + } + + if (!ContainsSplitClause) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Right split clause %d", clause_Number(SplitClause)); + misc_UserErrorReport(" does not have its split parent as parent clause.\n"); + misc_FinishUserErrorReport(); + } +} + + + +/* EK: unused, only recursive */ +static void pcheck_SplitFormats(TABLEAU T) +/************************************************************** + INPUT : A tableau + RETURNS: TRUE iff all splits: + - have generated negations of the left split clause + if the left split clause is ground + - the conditions for right split clauses are + as demanded in pcheck_RightSplitParents +***************************************************************/ +{ + LIST Scan; + + if (tab_IsEmpty(T)) + return; + + /* for right splits, check that parents have an empty clause */ + /* and the split clause as a parent */ + + for (Scan = tab_RightSplitClauses(T); !list_Empty(Scan); + Scan = list_Cdr(Scan)) { + pcheck_RightSplitParents(tab_SplitClause(T), list_Car(Scan), + tab_LeftSplitClause(T)); + } + + pcheck_SplitFormats(tab_RightBranch(T)); + pcheck_SplitFormats(tab_LeftBranch(T)); +} + + +static void pcheck_SplitLevels(TABLEAU T) +/************************************************************** + INPUT : A Tableau + RETURNS: TRUE iff all clauses in the tableau that + are not splitting clauses have the max split + level of their parents. + CAUTION: We assume that <T> has correct and complete split + entries. See pcheck_SplitToProblems. +***************************************************************/ +{ + LIST Scan; + CLAUSE Clause; + int CorrectLevel; + + if (tab_IsEmpty(T)) + return; + + /* check split levels */ + for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Clause = list_Car(Scan); + if (!list_Empty(clause_ParentClauses(Clause)) + && !clause_IsFromSplitting(Clause)) { + + CorrectLevel = pcheck_MaxParentSplitLevel(Clause); + if (clause_SplitLevel(Clause) != CorrectLevel) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Split level of clause %d should be %d.\n", + clause_Number(Clause), CorrectLevel); + misc_FinishUserErrorReport(); + } + } + } + + pcheck_SplitLevels(tab_RightBranch(T)); + pcheck_SplitLevels(tab_LeftBranch(T)); +} + + +/* EK: unused, only recursive */ +static void pcheck_SplitPrecheck(TABLEAU T) +/************************************************************** + INPUT : A tableau. + EFFECTS: Stops and prints an error message if a left half + of a split does not subsume its parents, or + if negations have been generated for a non-ground + left split clause. +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return; + + if (!subs_Subsumes(tab_LeftSplitClause(T), tab_SplitClause(T), -1, -1)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Incorrect split of %d,", tab_SplitClause(T)); + misc_UserErrorReport(" left half of split does not subsume splitted clause.\n"); + misc_FinishUserErrorReport(); + } + + if (list_Length(tab_RightSplitClauses(T)) > 1 && + !clause_IsGround(tab_LeftSplitClause(T))) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Incorrect split of %d,", tab_SplitClause(T)); + misc_UserErrorReport(" non-ground split generated more than two clause.\n"); + misc_FinishUserErrorReport(); + } + + pcheck_SplitPrecheck(tab_LeftBranch(T)); + pcheck_SplitPrecheck(tab_RightBranch(T)); +} + + +BOOL pcheck_BuildTableauFromProof(LIST Proof, TABLEAU* Tableau) +/************************************************************** + INPUT : A list of clauses representing a proof, and a pointer + to a tableau used as return value. + RETURNS: TRUE iff no errors occurred, FALSE otherwise. + If TRUE is returned <Tableau> is set to a tableau + representing the proof. + EFFECTS: Errors are commented when they occur. +***************************************************************/ +{ + LIST ProofRest; + TABLEAU SplitPos; + TABPATH Path; + CLAUSE Clause; + int ClauseLevel, SplitLevel; + int ProofDepth; + + if (list_Empty(Proof)) { + *Tableau = tab_EmptyTableau(); + return TRUE; + } + + ProofDepth = pcheck_MaxSplitLevel(Proof); + *Tableau = tab_CreateNode(); + Path = tab_PathCreate(ProofDepth, *Tableau); + + ProofRest = Proof; + while (!list_Empty(ProofRest)) { + + SplitLevel = tab_PathLength(Path); + Clause = list_Car(ProofRest); + ClauseLevel = clause_SplitLevel(Clause); + + /* Special treatment for clauses that result from a splitting step */ + if (pcheck_ClauseIsFromSplit(Clause)) { + + if (ClauseLevel == 0) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Split level of split clause %d is 0.\n", clause_Number(Clause)); + misc_FinishUserErrorReport(); + } + + if (ClauseLevel > SplitLevel+1) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Split level of split clause %d", clause_Number(Clause)); + misc_UserErrorReport(" is not increment of current split level.\n"); + misc_FinishUserErrorReport(); + } + + SplitPos = tab_PathNthNode(Path, ClauseLevel-1); + + if (pcheck_ClauseIsFromLeftSplit(Clause)) { + /* Left branch of a splitting step */ + if (!tab_LeftBranchIsEmpty(SplitPos)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Multiple left splits for clause %d.\n", + clause_Number(tab_SplitClause(SplitPos))); + misc_FinishUserErrorReport(); + } + + Path = tab_PathPrefix(ClauseLevel-1, Path); + tab_SetSplitClause(SplitPos, list_Car(clause_ParentClauses(Clause))); + tab_SetLeftSplitClause(SplitPos, Clause); + tab_AddSplitAtCursor(Path, TRUE); + } else { + /* Right branch of a splitting step */ + if (tab_RightBranchIsEmpty(SplitPos)) { + + if (tab_LeftBranchIsEmpty(SplitPos)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Right split with incorrect split level, clause %d.\n", + clause_Number(Clause)); + misc_FinishUserErrorReport(); + } + + Path = tab_PathPrefix(ClauseLevel-1, Path); + tab_AddSplitAtCursor(Path, FALSE); + } + tab_AddRightSplitClause(SplitPos, Clause); + } /* clause from right split */ + } /* clause from split */ + + if (ClauseLevel > tab_PathLength(Path)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Split level of clause %d greater than current level.\n", + clause_Number(Clause)); + misc_FinishUserErrorReport(); + } + tab_AddClauseOnItsLevel(Clause, Path); + + ProofRest = list_Cdr(ProofRest); + } /* while proof is not empty */ + + + tab_PathDelete(Path); + + return TRUE; +} + + +static BOOL pcheck_TableauJustificationsRec(TABLEAU T, TABPATH Path) +/************************************************************** + INPUT : A Tableau <T>, a <Path> in the tableau + RETURNS: TRUE iff all clauses in the last node of the + path are correctly justified. +***************************************************************/ +{ + CLAUSE Clause; + LIST ScanClauses; + LIST ScanParents; + LIST Parents; + CLAUSE Parent; + BOOL Ok, RightSplit; + + if (tab_IsEmpty(T)) + return TRUE; + + Ok = TRUE; + + /* for each clause, check that its parents have been justified */ + + for (ScanClauses = tab_Clauses(tab_PathTop(Path)); + !list_Empty(ScanClauses); ScanClauses = list_Cdr(ScanClauses)) { + + Clause = list_Car(ScanClauses); + Parents = clause_ParentClauses(Clause); + + RightSplit = pcheck_ClauseIsFromRightSplit(Clause); + + /* check all parents */ + + for (ScanParents = Parents; !list_Empty(ScanParents); + ScanParents = list_Cdr(ScanParents)) { + + Parent = list_Car(ScanParents); + + if ((!(RightSplit && clause_IsEmptyClause(Parent)) && + !(RightSplit && pcheck_ClauseIsFromLeftSplit(Parent))) || + (clause_Number(Parent) > clause_Number(Clause)) ) { + if (!tab_PathContainsClause(Path, Parent)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Parent clause with number %d is not yet justified.\n", + clause_Number(Parent)); + misc_FinishUserErrorReport(); + } + } + } + } /* for all clauses in current node */ + + + /* Recursion */ + + if (!tab_LeftBranchIsEmpty(T)) { + Path = tab_PathPush(tab_LeftBranch(T), Path); + Ok = Ok && pcheck_TableauJustificationsRec(tab_LeftBranch(T), Path); + Path = tab_PathPop(Path); + } + + if (!tab_RightBranchIsEmpty(T)) { + Path = tab_PathPush(tab_RightBranch(T), Path); + Ok = Ok && pcheck_TableauJustificationsRec(tab_RightBranch(T), Path); + Path = tab_PathPop(Path); + } + + return Ok; +} + +static BOOL pcheck_TableauJustifications(TABLEAU T) +/************************************************************** + INPUT : A Tableau + RETURNS: TRUE iff for each clause in tableau, all its parent + clauses have been derived in a split on the same level + or below. +***************************************************************/ +{ + TABPATH Path; + BOOL Ok; + + Path = tab_PathCreate(tab_Depth(T),T); + Ok = pcheck_TableauJustificationsRec(T,Path); + tab_PathDelete(Path); + + return Ok; +} + +BOOL pcheck_TableauProof(TABLEAU* Tableau, LIST Proof) +/************************************************************** + INPUT: + RETURNS: +***************************************************************/ +{ + LIST RedundantClauses; + LIST EmptyClauses; + LIST UnmarkedSplits; + + tab_LabelNodes(*Tableau); + /* print out current tableau */ + if (pcheck_GenNamedCg) + tab_WriteTableau(*Tableau, pcheck_CgName, pcheck_GraphFormat); + + RedundantClauses = list_Nil(); + if (!pcheck_Quiet) { + fputs("pruning closed branches...", stdout); + fflush(stdout); + } + (*Tableau) = tab_PruneClosedBranches(*Tableau, &RedundantClauses); /* delete descendants of already closed branches */ + if (!pcheck_Quiet) + puts("finished."); + + if (!pcheck_Quiet) { + fputs("removing incomplete splits...", stdout); + fflush(stdout); + } + (*Tableau) = tab_RemoveIncompleteSplits(*Tableau, &RedundantClauses); /* reduce open node redundancies */ + if (!pcheck_Quiet) + puts("finished."); + + list_Delete(RedundantClauses); + + /* remove all clauses that are not needed for the empty clauses */ + /* of the proof or for the tableau structure (splits) */ + + EmptyClauses = list_Nil(); + tab_GetEarliestEmptyClauses(*Tableau, &EmptyClauses); + pcheck_ClauseListRemoveFlag(Proof, MARKED); + pcheck_MarkRecursive(EmptyClauses); + UnmarkedSplits = list_Nil(); + pcheck_CollectUnmarkedSplits(*Tableau, &UnmarkedSplits); + pcheck_MarkRecursive(UnmarkedSplits); + pcheck_RemoveUnmarkedFromTableau(*Tableau); + list_Delete(UnmarkedSplits); + list_Delete(EmptyClauses); + + /* print reduced graph */ + if (pcheck_GenRedCg) + tab_WriteTableau(*Tableau, pcheck_RedCgName, pcheck_GraphFormat); + + tab_SetSplitLevels(*Tableau); + pcheck_SplitLevels(*Tableau); + tab_CheckEmpties(*Tableau); + + if (!tab_IsClosed(*Tableau)) { + puts("\nerror: tableau is not closed."); + return FALSE; + } + + /* check justifications */ + if (!pcheck_Quiet) { + fputs("checking justifications...", stdout); + fflush(stdout); + } + if (!pcheck_TableauJustifications(*Tableau)) + return FALSE; + if (!pcheck_Quiet) + puts("finished."); + + return TRUE; +} + + +void pcheck_MarkRecursive(LIST Clauses) +/************************************************************** + INPUT: A list of clauses + RETURNS: Nothing. + EFFECTS: Marks all <Clauses> and its ancestors with the + MARKED clause flag. +***************************************************************/ +{ + CLAUSE Clause; + + for (; !list_Empty(Clauses); Clauses = list_Cdr(Clauses)) { + Clause = list_Car(Clauses); + if (!clause_GetFlag(Clause, MARKED)) { + pcheck_MarkRecursive(clause_ParentClauses(Clause)); + clause_SetFlag(Clause, MARKED); + } + } +} + + +static LIST pcheck_CollectTermVariables(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: A list of terms. For each variable in <Term> the list + contains exactly one term representing the variable. + EFFECT: Memory is allocated for the terms. +***************************************************************/ +{ + LIST Result, Scan; + + Result = term_VariableSymbols(Term); + for (Scan = Result; !list_Empty(Scan); Scan = list_Cdr(Scan)) + list_Rplaca(Scan, term_Create((SYMBOL)list_Car(Scan), list_Nil())); + + return Result; +} + + +static BOOL pcheck_IsRightSplitHalf(CLAUSE C) +/************************************************************** + INPUT : A clause. + RETURNS: TRUE iff the following conditions are fulfilled: + - the first parent clause is an empty clause + - the clause subsumes its second parent +***************************************************************/ +{ + LIST Parents; + BOOL Ok; + + Parents = list_Copy(clause_ParentClauses(C)); + Parents = list_PointerDeleteDuplicates(Parents); + + Ok = FALSE; + if (list_Length(Parents) == 2 && clause_IsEmptyClause(list_First(Parents))) + Ok = subs_Subsumes(C, list_Second(Parents), -1, -1); + + list_Delete(Parents); + + return Ok; +} + + +static TERM pcheck_UnivClosure(TERM T) +/************************************************************** + INPUT: A term, representing a formula. + RETURNS: The universal closure of the term. + EFFECTS: <T> is part of the returned term! +***************************************************************/ +{ + LIST Vars; + + Vars = pcheck_CollectTermVariables(T); + + if (list_Empty(Vars)) + return T; + return fol_CreateQuantifier(fol_All(), Vars, list_List(T)); +} + + +static TERM pcheck_ClauseToTerm(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: The clause represented as a TERM. +***************************************************************/ +{ + int LitScan; + LIST Args; + TERM Lit; + TERM ClauseTerm; + + Args = list_Nil(); + + for (LitScan = clause_FirstLitIndex(); LitScan <= clause_LastLitIndex(Clause); + LitScan++) { + Lit = clause_LiteralSignedAtom(clause_GetLiteral(Clause, LitScan)); + Args = list_Cons(term_Copy(Lit), Args); + } + + if (list_Empty(Args)) + Args = list_List(term_Create(fol_False(), list_Nil())); + + /* Build the disjunction of the literals */ + if (list_Empty(list_Cdr(Args))) { /* only one arg */ + ClauseTerm = list_Car(Args); + list_Delete(Args); + } else + ClauseTerm = term_Create(fol_Or(), Args); + ClauseTerm = pcheck_UnivClosure(ClauseTerm); + + return ClauseTerm; +} + + +static LIST pcheck_ClauseListToTermList(LIST Clauses) +/************************************************************** + INPUT : A list of clauses. + RETURNS: A new list containing the clauses represented as TERMs. +***************************************************************/ +{ + LIST Terms; + + Terms = list_Nil(); + for (; !list_Empty(Clauses); Clauses = list_Cdr(Clauses)) + Terms = list_Cons(pcheck_ClauseToTerm(list_Car(Clauses)), Terms); + + return Terms; +} + + +static void pcheck_SaveNumberedDFGProblem(int Number, LIST Axioms, + LIST Conjectures, + const char* ProofFileName, + const char* DestPrefix) +/************************************************************** + INPUT : A (clause) number, a list of axioms and conjectures, + and a filename (of the proof file of the currently + checked proof) + RETURNS: Nothing. + EFFECTS: Saves a DFG file containing <Axioms> and <Conjectures> + under the name "<DestPrefix><Number>_<ProofFileName>" +***************************************************************/ +{ + char *Filename, *Tmp, *NumStr; + FILE *File; + + NumStr = string_IntToString(Number); + Tmp = pcheck_GenericFilename(ProofFileName, NumStr); + Filename = string_Conc(DestPrefix, Tmp); + + File = misc_OpenFile(Filename, "w"); + fol_FPrintDFGProblem(File, "{*Sub Proof*}", "{* Proof Checker *}", + "unsatisfiable", + "{* The problem is the correctness test for a single proof line *}", + Axioms, Conjectures); + misc_CloseFile(File, Filename); + + string_StringFree(NumStr); + string_StringFree(Tmp); + string_StringFree(Filename); +} + + +static void pcheck_SplitToProblems(TABLEAU T, const char* ProofFileName, + const char* DestPrefix) +/************************************************************** + INPUT: A tableau, which isn't a leaf of the tableau tree, + the name of a proof file and a file name prefix used for + generating files. + RETURNS: Nothing. + EFFECT: This function generates proof check tasks for clauses + resulting from splitting steps and writes them to + output files. + CAUTION: We assume that we get non-null clauses when calling + tab_SplitClause and tab_LeftSplitClause. +***************************************************************/ +{ + TERM SplitClauseTerm, LeftClauseTerm, RightClauseTerm; + TERM Equiv, Disj, Tmp; + LIST Conj, Args, Negations; + +#ifdef CHECK + if (tab_IsLeaf(T)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In pcheck_SplitToProblems: Tableau is a leaf of the "); + misc_ErrorReport("tableau tree."); + misc_FinishErrorReport(); + } +#endif + + SplitClauseTerm = pcheck_ClauseToTerm(tab_SplitClause(T)); + LeftClauseTerm = pcheck_ClauseToTerm(tab_LeftSplitClause(T)); + + /* by default, take all right split clauses as negations */ + /* if the first clause is the second half of a split clause, */ + /* take only the rest of the right split clauses as negations. */ + + Negations = tab_RightSplitClauses(T); + if (!list_Empty(Negations) && pcheck_IsRightSplitHalf(list_Car(Negations))) { + /* EK: Meiner Meinung nach ist es eine Invariante, daß die erste */ + /* Elternklausel die rechte Hälfte eines Splittings ist??? */ + Negations = list_Cdr(Negations); + /* build C <=> C' v C'' */ + RightClauseTerm = pcheck_ClauseToTerm(list_Car(tab_RightSplitClauses(T))); + Disj = term_Create(fol_Or(), list_Cons(LeftClauseTerm, list_List(RightClauseTerm))); + Equiv = term_Create(fol_Equiv(), list_Cons(SplitClauseTerm, list_List(Disj))); + Conj = list_List(Equiv); + + pcheck_SaveNumberedDFGProblem(clause_Number(tab_LeftSplitClause(T)), + list_Nil(), Conj, ProofFileName, DestPrefix); + term_DeleteTermList(Conj); + } + + Args = list_Nil(); + + /* build conjunction of negations, if there are any. */ + if (!list_Empty(Negations)) { + LeftClauseTerm = pcheck_ClauseToTerm(tab_LeftSplitClause(T)); + Args = pcheck_ClauseListToTermList(Negations); + /* Build the conjunction */ + if (list_Empty(list_Cdr(Args))) { /* only one arg */ + Tmp = list_Car(Args); + list_Delete(Args); + } else + Tmp = term_Create(fol_And(), Args); + Tmp = term_Create(fol_Not(), list_List(Tmp)); + Equiv = term_Create(fol_Implies(),list_Cons(Tmp,list_List(LeftClauseTerm))); + Conj = list_List(Equiv); + + /* problem id is number of right part of split clause, if it exists, + number of first negation otherwise */ + pcheck_SaveNumberedDFGProblem(clause_Number(list_Car(tab_RightSplitClauses(T))), + list_Nil(), Conj, ProofFileName, DestPrefix); + term_DeleteTermList(Conj); + } +} + + +void pcheck_TableauToProofTask(TABLEAU T, const char* ProofFileName, + const char* DestPrefix) +/************************************************************** + INPUT: A Tableau, two strings for filename generation. + RETURNS: Nothing. + EFFECTS: Generates DFG problem files for each clause in the tableau. + The problem asserts that the clause follows from + its parents. For splits, see pcheck_SplitToProblems +***************************************************************/ +{ + LIST Scan; + LIST Axioms, Conj, Help; + CLAUSE Clause; + + if (tab_IsEmpty(T)) + return; + + /* treat the splitting clauses at inner nodes of the tableau tree */ + if (!tab_IsLeaf(T)) + pcheck_SplitToProblems(T, ProofFileName, DestPrefix); + + /* treat derived clauses that don't result from splitting */ + for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Clause = list_Car(Scan); + if (!clause_IsFromSplitting(Clause) && + !list_Empty(clause_ParentClauses(Clause))) { + Axioms = list_Copy(clause_ParentClauses(Clause)); + Axioms = list_PointerDeleteDuplicates(Axioms); + Help = Axioms; + Axioms = pcheck_ClauseListToTermList(Axioms); + list_Delete(Help); + Conj = list_List(pcheck_ClauseToTerm(Clause)); + pcheck_SaveNumberedDFGProblem(clause_Number(Clause), Axioms, Conj, + ProofFileName, DestPrefix); + term_DeleteTermList(Axioms); + term_DeleteTermList(Conj); + } + } + + /* recursion */ + pcheck_TableauToProofTask(tab_RightBranch(T), ProofFileName, DestPrefix); + pcheck_TableauToProofTask(tab_LeftBranch(T), ProofFileName, DestPrefix); +} + + +int pcheck_SeqProofDepth(LIST Proof) +/************************************************************** + INPUT : A sequential proof (list of clauses) + RETURNS: The maximum clause depth in the proof +***************************************************************/ +{ + int Max; + + Max = 0; + for ( ; !list_Empty(Proof); Proof = list_Cdr(Proof)) + if (clause_Depth(list_Car(Proof)) > Max) + Max = clause_Depth(list_Car(Proof)); + + return Max; +} + + +LIST pcheck_ReduceSPASSProof(LIST Proof) +/************************************************************** + INPUT: A list of clauses representing a SPASS proof. + Parents are pointers. + RETURNS: A list of clauses were incomplete splits + and closed branches with descendants have been + removed. +***************************************************************/ +{ + LIST EmptyClauses, RedundantClauses; + LIST ReducedProof; + TABLEAU Tableau; + LIST UnmarkedSplits; + + if (!pcheck_BuildTableauFromProof(Proof, &Tableau)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Proof could not be translated into a closed tableau.\n"); + misc_FinishUserErrorReport(); + } + + RedundantClauses = list_Nil(); + Tableau = tab_PruneClosedBranches(Tableau, &RedundantClauses); + Tableau = tab_RemoveIncompleteSplits(Tableau, &RedundantClauses); + list_Delete(RedundantClauses); + + tab_SetSplitLevels(Tableau); + + /* + * get minimal proof: First find earliest derived empty clauses, + * then recursively mark ancestors of these clauses. Put + * only marked clauses in <ReducedProof>. + */ + + EmptyClauses = list_Nil(); + tab_GetEarliestEmptyClauses(Tableau, &EmptyClauses); + pcheck_ClauseListRemoveFlag(Proof, MARKED); + pcheck_MarkRecursive(EmptyClauses); + UnmarkedSplits = list_Nil(); + pcheck_CollectUnmarkedSplits(Tableau, &UnmarkedSplits); + pcheck_MarkRecursive(UnmarkedSplits); + pcheck_RemoveUnmarkedFromTableau(Tableau); + list_Delete(UnmarkedSplits); + + ReducedProof = list_Nil(); + tab_ToClauseList(Tableau, &ReducedProof); + ReducedProof = pcheck_ClauseNumberMergeSort(ReducedProof); + + tab_Delete(Tableau); + list_Delete(EmptyClauses); + + return ReducedProof; +} + + +void pcheck_DeleteProof(LIST Proof) +/************************************************************** + INPUT: A Proof + RETURNS: Nothing. + EFFECTS: Frees memory associated with proof +**************************************************************/ +{ + LIST Line, Scan2, Scan1; + + Scan1 = Proof; + while (!list_Empty(Scan1)) { + Line = list_Car(Scan1); + + string_StringFree(list_Car(Line)); + if (list_Second(Line) != clause_Null()) /* clause */ + term_Delete(list_Second(Line)); + + /* delete labels in justification list and list itself */ + + for (Scan2 = list_Third(Line); !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) + string_StringFree(list_Car(Scan2)); + list_Delete(list_Third(Line)); + + /* now contents of line are deleted. Delete line. */ + list_Delete(Line); + Scan1 = list_Cdr(Scan1); + } + list_Delete(Proof); +} + + +char* pcheck_GenericFilename(const char* Filename, const char* Id) +/************************************************************** + INPUT: Two strings. + RETURNS: A string with Suffix as new extension to Filename + (Filename = name.ext -> name_<Id>.prf) + EFFECTS: Memory is allocated for the returned string. +**************************************************************/ +{ + char *Help1, *Help2; + int i; + + Help1 = string_Conc("_", Id); + Help2 = string_Conc(Help1, pcheck_ProofFileSuffix); + string_StringFree(Help1); + + /* remove filename extension */ + for (i = 0; Filename[i] != '.' && i < strlen(Filename); i++) + /* empty */; + Help1 = string_Prefix(Filename, i); + + return string_Nconc(Help1, Help2); /* Help1 and Help2 are freed, too */ +} + + +void pcheck_ClauseListRemoveFlag(LIST Clauses, CLAUSE_FLAGS Flag) +/************************************************************** + INPUT: A list of clauses and a clause flag + RETURNS: Nothing. + EFFECTS: Removes the <Flag> in all clauses in the list +**************************************************************/ +{ + for (; !list_Empty(Clauses); Clauses = list_Cdr(Clauses)) + clause_RemoveFlag(list_Car(Clauses), Flag); +} + + +LIST pcheck_ClauseNumberMergeSort(LIST L) +/************************************************************** + INPUT: A list of clauses + RETURNS: The sorted list: clause_Number(L[i]) < clause_Number(L[i+1]) + EFFECTS: Destructive +***************************************************************/ +{ + return clause_NumberSort(L); +} diff --git a/test/spass/proofcheck.h b/test/spass/proofcheck.h new file mode 100644 index 0000000000000000000000000000000000000000..4f697468dc7c1d08897c5eeb7273855ca42811af --- /dev/null +++ b/test/spass/proofcheck.h @@ -0,0 +1,82 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * PROOF CHECKING * */ +/* * * */ +/* * Copyright (C) 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ + +/* $RCSfile$ */ + +#ifndef _PROOFCHECK_H_ +#define _PROOFCHECK_H_ + +#include "options.h" + +#include <string.h> +#include <ctype.h> +#include <math.h> +#include "list.h" +#include "vector.h" + +#include "misc.h" +#include "dfg.h" +#include "foldfg.h" +#include "flags.h" +#include "clause.h" +#include "tableau.h" +#include "search.h" +#include "dfg.h" + + +LIST pcheck_ReduceSPASSProof(LIST); +char* pcheck_GenericFilename(const char*, const char*); +int pcheck_SeqProofDepth(LIST); +void pcheck_DeleteProof(LIST); +BOOL pcheck_BuildTableauFromProof(LIST, TABLEAU*); +LIST pcheck_ConvertTermListToClauseList(LIST, FLAGSTORE, PRECEDENCE); +void pcheck_TableauToProofTask(TABLEAU, const char*, const char*); +BOOL pcheck_TableauProof(TABLEAU*, LIST); +LIST pcheck_ParentPointersToParentNumbers(LIST); +LIST pcheck_ConvertParentsInSPASSProof(PROOFSEARCH, LIST); +void pcheck_MarkRecursive(LIST); +LIST pcheck_ClauseNumberMergeSort(LIST); +void pcheck_ClauseListRemoveFlag(LIST, CLAUSE_FLAGS); + +#endif + + + diff --git a/test/spass/ras.h b/test/spass/ras.h new file mode 100644 index 0000000000000000000000000000000000000000..9e3f4232da1a1e78bf37a5ddd48f342deb30445f --- /dev/null +++ b/test/spass/ras.h @@ -0,0 +1,298 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * RANDOM ACCESS STACK * */ +/* * * */ +/* * $Module: RAS * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +#ifndef _RAS_ +#define _RAS_ + + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "misc.h" +#include "memory.h" + + +/**************************************************************/ +/* Constants and types */ +/**************************************************************/ + +#define ras_alloc -1 /* index of size of allocated space */ +#define ras_top -2 /* index of next free element */ +#define ras_head 2 /* size of stack head for management purposes */ +#define ras_stdsize 16 /* standard stack size */ + + +typedef POINTER *RAS; + +/* A RAS (Random Access Stack) is a pointer to an array of elements */ +/* where the actual size of the stack and its current top pointer */ +/* are stored one and two cells before the array pointer. */ + + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +static __inline__ RAS ras_CreateWithSize(int size) +/**************************************************************** + INPUT: The maximal expected size of the stack to create. + RETURNS: A new empty stack. +*****************************************************************/ +{ + RAS result; + +#ifdef CHECK + if (size <= 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In ras_CreateWithSize: size not positive."); + misc_FinishErrorReport(); + } +#endif + + result = (RAS) memory_Malloc((size + ras_head) * sizeof(POINTER)); + result = result + ras_head; /* leave space for head */ + result[ras_alloc] = (POINTER) size; + result[ras_top] = (POINTER) 0; + return result; +} + + +static __inline__ RAS ras_Create(void) +{ + return ras_CreateWithSize(ras_stdsize); +} + + +static __inline__ void ras_Free(RAS ras) +{ + if (ras != NULL) { + memory_Free ( + ras - ras_head, + (ras_head + (int) ras[ras_alloc]) * sizeof(POINTER) + ); + } +} + + +static __inline__ RAS ras_InitWithSize(RAS ras, int size) +/**************************************************************** + INPUT: A random access stack the maximal expected size of the + stack to init. + RETURNS: The initialized and potentially new stack. + CAUTION: Because it potentially frees the old stack this + function must be called inside an assignment like: + stack = ras_InitWithSize(stack, ...) +*****************************************************************/ +{ + +#ifdef CHECK + if (size <= 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In ras_InitWithSize: size not positive."); + misc_FinishErrorReport(); + } +#endif + + if (size > (int) ras[ras_alloc]) { + ras_Free(ras); + ras = ras_CreateWithSize(size); + } + else + ras[ras_top] = (POINTER) 0; + return ras; +} + + +static __inline__ RAS ras_Init(RAS ras) +/**************************************************************** + INPUT: A random access stack. + RETURNS: The initialized and potentially new stack. + CAUTION: Because it potentially frees the old stack this + function must be called inside an assignment like: + stack = ras_InitWithSize(stack, ...) +*****************************************************************/ +{ + return ras_InitWithSize(ras, ras_stdsize); +} + + +static __inline__ int ras_Size(RAS ras) +{ + return (int) ras[ras_top]; +} + + +static __inline__ RAS ras_FastPush(RAS ras, POINTER entry) +/********************************************************* + INPUT: A random access stack and an element to push. + RETURNS: The modified stack. + CAUTION: The function does not care about stack overflow! +**********************************************************/ +{ + int top; + +#ifdef CHECK + if (ras_Size(ras) == (int) ras[ras_alloc]) { + misc_StartErrorReport(); + misc_ErrorReport("\n In ras_FastPush: stack overflow."); + misc_FinishErrorReport(); + } +#endif + + top = ras_Size(ras); + ras[top++] = entry; + ras[ras_top] = (POINTER) top; + return ras; +} + + +static __inline__ RAS ras_Push(RAS ras, POINTER entry) +/********************************************************* + INPUT: A random access stack and an element to push. + RETURNS: The modified and potentially new stack. + SUMMARY: Before the push the stack is checked for overflow + and in case of overflow its size is doubled while + elements are copied to the (new) stack. + CAUTION: Must be called inside an assignment: + stack = ras_Push(stack, ...) +**********************************************************/ +{ + RAS old; + int oldsize; + POINTER *oldscan, *scan; + + /* if not enough space allocated, double it: */ + if (ras_Size(ras) == (int) ras[ras_alloc]) { + old = ras; + oldsize = (int) old[ras_alloc]; + ras = ras_CreateWithSize(oldsize * 2); + ras[ras_top] = (POINTER) oldsize; + + /* copy entries: */ + for (oldscan = old + oldsize - 1,scan = ras + oldsize - 1; oldscan >= old; + oldscan--, scan--) + *scan = *oldscan; + + ras_Free(old); + } + + return ras_FastPush(ras, entry); +} + + +static __inline__ BOOL ras_LegalIndex(RAS ras, int index) +{ + return 0 <= index && index < ras_Size(ras); +} + + +static __inline__ POINTER ras_Get(RAS ras, int index) +{ +#ifdef CHECK + if (!ras_LegalIndex(ras, index)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In ras_Get: illegal stack index."); + misc_FinishErrorReport(); + } +#endif + + return ras[index]; +} + + +static __inline__ RAS ras_Set(RAS ras, int index, POINTER entry) +{ +#ifdef CHECK + if (!ras_LegalIndex(ras, index)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In ras_Set: illegal stack index."); + misc_FinishErrorReport(); + } +#endif + + ras[index] = entry; + return ras; +} + + +static __inline__ BOOL ras_Empty(RAS ras) +{ + return ras_Size(ras) == 0; +} + + +static __inline__ POINTER ras_Pop(RAS ras) +{ + int top; + +#ifdef CHECK + if (ras_Empty(ras)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In ras_Pop: empty stack."); + misc_FinishErrorReport(); + } +#endif + + top = ras_Size(ras) - 1; + ras[ras_top] = (POINTER) top; + return ras[top]; +} + + +static __inline__ POINTER ras_Top(RAS ras) +{ +#ifdef CHECK + if (ras_Empty(ras)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In ras_Top: empty stack."); + misc_FinishErrorReport(); + } +#endif + + return ras[ras_Size(ras) - 1]; +} + + +#endif + diff --git a/test/spass/renaming.c b/test/spass/renaming.c new file mode 100644 index 0000000000000000000000000000000000000000..55c89c5a7d7b47bf780efcd6eccc4abcff63f3d8 --- /dev/null +++ b/test/spass/renaming.c @@ -0,0 +1,1508 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * RENAMING * */ +/* * * */ +/* * $Module: RENAMING * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "renaming.h" + +static NAT ren_STAMPID; + +static BOOL ren_RootDistanceSmaller(RENAMING,RENAMING); +static BOOL ren_AFactorOk(TERM,TERM); +static BOOL ren_BFactorOk(TERM,TERM); +static BOOL ren_AExtraFactorOk(TERM,TERM); +static BOOL ren_BExtraFactorOk(TERM,TERM); +static BOOL ren_AFactorBigger3(TERM,TERM); +static BOOL ren_BFactorBigger3(TERM,TERM); +static TERM ren_FormulaRename(TERM, LIST, PRECEDENCE, LIST*); +static LIST ren_GetRenamings(TERM, TERM, int); +static BOOL ren_HasBenefit(TERM, TERM, int); +static int ren_Polarity(TERM); +static BOOL ren_PFactorOk(TERM); +static BOOL ren_PExtraFactorOk(TERM); +static BOOL ren_PFactorBigger3(TERM); +static BOOL ren_NotPFactorOk(TERM); +static BOOL ren_NotPExtraFactorOk(TERM); +static BOOL ren_NotPFactorBigger3(TERM); +static void ren_ResetTermStamp(TERM); + +void ren_Init(void) +/********************************************************** + INPUT: None. + RETURNS: void. + EFFECT: Initializes the renaming module, in particular + the stamp id used in this module. +***********************************************************/ +{ + ren_STAMPID = term_GetStampID(); +} + +static BOOL ren_RootDistanceSmaller(RENAMING Ren1, RENAMING Ren2) +{ + return term_RootDistanceSmaller(ren_Hit(Ren1), ren_Hit(Ren2)); +} + + +static void ren_ResetTermStamp(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: void. + EFFECT: The Term stamp of term as well as the stamps of + all its subterms (up to atom level) are reset. +***********************************************************/ +{ + SYMBOL Top; + + term_ResetTermStamp(Term); + Top = term_TopSymbol(Term); + + if (!symbol_IsPredicate(Top)) { + if (fol_IsQuantifier(Top)) + ren_ResetTermStamp(term_SecondArgument(Term)); + else { + LIST Scan; + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + ren_ResetTermStamp(list_Car(Scan)); + } + } +} + +static BOOL ren_HasNEquivFathers(TERM Term1, TERM Term2, NAT n) +/********************************************************** + INPUT: Two terms, where <Term2> is a proper subterm of <Term1> + and a number. + RETURNS: TRUE if <Term2> has a <n>-father that are equivalences + and below <Term1> +***********************************************************/ +{ + Term2 = term_Superterm(Term2); + + while (Term1 != Term2) { + if (symbol_Equal(term_TopSymbol(Term2),fol_Equiv())) { + n--; + if (n == 0) + return TRUE; + } + Term2 = term_Superterm(Term2); + } + + return FALSE; +} + + +static BOOL ren_PExtraFactorOk(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: TRUE if transforming the term <Term> in positive polarity context + results in more than two clauses. +***********************************************************/ +{ + SYMBOL Top; + TERM T1, T2; + BOOL Ok; + + /* if <Term> has the stamp, it will be renamed */ + if (term_HasTermStamp(Term) || term_IsAtom(Term)) + return FALSE; + + Top = term_TopSymbol(Term); + + if (fol_IsQuantifier(Top)) + return ren_PExtraFactorOk(term_SecondArgument(Term)); + + if (symbol_Equal(Top,fol_Not())) + return ren_NotPExtraFactorOk(term_FirstArgument(Term)); + + if (symbol_Equal(Top,fol_Equiv())) { + T1 = term_FirstArgument(Term); + T2 = term_SecondArgument(Term); + return (ren_PFactorOk(T1) || ren_NotPFactorOk(T2) || + ren_NotPFactorOk(T1) || ren_PFactorOk(T2)); + } + if (symbol_Equal(Top,fol_And())) { + return (list_Length(term_ArgumentList(Term)) > 2 || + ren_PFactorOk(term_FirstArgument(Term)) || + ren_PFactorOk(term_SecondArgument(Term))); + } + if (symbol_Equal(Top,fol_Implies())) { + T1 = term_FirstArgument(Term); + T2 = term_SecondArgument(Term); + Ok = ren_PFactorOk(T2); + return ((ren_NotPFactorOk(T1) && (Ok || ren_NotPExtraFactorOk(T1))) || + (Ok && ren_PExtraFactorOk(T2))); + } + + if (symbol_Equal(Top,fol_Or())) { + LIST Scan; + Ok = FALSE; /* is set to TRUE if a subterm with p factor >1 occurred */ + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (ren_PFactorOk(list_Car(Scan))) { + if (Ok || ren_PExtraFactorOk(list_Car(Scan))) + return TRUE; /* if two subterms with p>1 or one subterm with p>2 */ + Ok = TRUE; + } + } + + return FALSE; /* <Term> is a trivial disjunction */ +} + +static BOOL ren_PFactorOk(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: TRUE if transforming the term <Term> in positive polarity context + results in more than one clause. +***********************************************************/ +{ + SYMBOL Top; + + /* if <Term> has the stamp, it will be renamed */ + if (term_HasTermStamp(Term) || term_IsAtom(Term)) + return FALSE; + + Top = term_TopSymbol(Term); + + if (symbol_Equal(Top,fol_Equiv()) || symbol_Equal(Top,fol_And())) + return TRUE; + + if (symbol_Equal(Top,fol_Not())) + return ren_NotPFactorOk(term_FirstArgument(Term)); + + if (fol_IsQuantifier(Top)) + return ren_PFactorOk(term_SecondArgument(Term)); + + if (symbol_Equal(Top,fol_Implies())) + return (ren_NotPFactorOk(term_FirstArgument(Term)) || + ren_PFactorOk(term_SecondArgument(Term))); + + if (symbol_Equal(Top,fol_Or())) { + LIST Scan; + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (ren_PFactorOk(list_Car(Scan))) + return TRUE; + } + + return FALSE; /* <Term> is a trivial disjunction */ +} + + +static BOOL ren_NotPExtraFactorOk(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: TRUE if transforming the term <Term> in negative polarity context + results in more than two clauses. +***********************************************************/ +{ + SYMBOL Top; + + /* if <Term> has the stamp, it will be renamed */ + if (term_HasTermStamp(Term) || term_IsAtom(Term)) + return FALSE; + + Top = term_TopSymbol(Term); + + if (symbol_Equal(Top,fol_Not())) + return ren_PExtraFactorOk(term_FirstArgument(Term)); + + if (fol_IsQuantifier(Top)) + return ren_NotPExtraFactorOk(term_SecondArgument(Term)); + + if (symbol_Equal(Top,fol_Equiv())) { + TERM T1, T2; + T1 = term_FirstArgument(Term); + T2 = term_SecondArgument(Term); + return (ren_PFactorOk(T1) || ren_PFactorOk(T2) || + ren_NotPFactorOk(T1) || ren_NotPFactorOk(T2)); + } + if (symbol_Equal(Top,fol_Or())) { + if (list_Length(term_ArgumentList(Term))>2 || + ren_NotPFactorOk(term_FirstArgument(Term)) || + ren_NotPFactorOk(term_SecondArgument(Term))) + return TRUE; + else + return FALSE; + } + if (symbol_Equal(Top,fol_Implies())) { + if (ren_PFactorOk(term_FirstArgument(Term)) || + ren_NotPFactorOk(term_SecondArgument(Term))) + return TRUE; + else + return FALSE; + } + + if (symbol_Equal(Top,fol_And())) { + LIST Scan; + BOOL Ok; + Ok = FALSE; + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (ren_NotPFactorOk(list_Car(Scan))) { + if (Ok || ren_NotPExtraFactorOk(list_Car(Scan))) + return TRUE; /* if two subterms with -p>1 or one subterm with -p>2 */ + Ok = TRUE; + } + } + + return FALSE; /* Either <Term> is a trivial conjunction or an atom */ +} + + +static BOOL ren_NotPFactorOk(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: TRUE if transforming the term <Term> in negative polarity context + results in more than one clause. +***********************************************************/ +{ + SYMBOL Top; + + /* if <Term> has the stamp, it will be renamed */ + if (term_HasTermStamp(Term) || term_IsAtom(Term)) + return FALSE; + + Top = term_TopSymbol(Term); + + if (symbol_Equal(Top,fol_Equiv()) || symbol_Equal(Top,fol_Or()) || + symbol_Equal(Top,fol_Implies())) + return TRUE; + + if (symbol_Equal(Top,fol_Not())) + return ren_PFactorOk(term_FirstArgument(Term)); + + if (fol_IsQuantifier(Top)) + return ren_NotPFactorOk(term_SecondArgument(Term)); + + if (symbol_Equal(Top,fol_And())) { + LIST Scan; + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (ren_NotPFactorOk(list_Car(Scan))) + return TRUE; + } + + return FALSE; /* <Term> is a trivial conjunction */ +} + + +static BOOL ren_PFactorBigger3(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: TRUE if transforming the term <Term> in positive + polarity context results in more than three clauses. +***********************************************************/ +{ + SYMBOL Top; + TERM T1, T2; + LIST Scan; + BOOL Ok; + + /* if <Term> has the stamp, it will be renamed */ + if (term_HasTermStamp(Term) || term_IsAtom(Term)) + return FALSE; + + Top = term_TopSymbol(Term); + + if (fol_IsQuantifier(Top)) + return ren_PFactorBigger3(term_SecondArgument(Term)); + + if (symbol_Equal(Top, fol_Not())) + return ren_NotPFactorBigger3(term_FirstArgument(Term)); + + if (symbol_Equal(Top, fol_And())) { + unsigned char Limit; /* invariant: p >= Limit */ + Limit = list_Length(term_ArgumentList(Term)); + for (Scan=term_ArgumentList(Term); !list_Empty(Scan) && Limit<=3; + Scan=list_Cdr(Scan)) + if (ren_PFactorOk(list_Car(Scan))) { + Limit++; + if (Limit<=3 && ren_PExtraFactorOk(list_Car(Scan))) { + Limit++; + if (Limit<=3 && ren_PFactorBigger3(list_Car(Scan))) + Limit++; /* works for unary conjunction, too */ + } + } + return (Limit>3); + } + if (symbol_Equal(Top, fol_Or())) { + Ok = FALSE; /* is set to TRUE if a subterm with p factor >1 occurred */ + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (ren_PFactorOk(list_Car(Scan))) { + if (Ok || ren_PFactorBigger3(list_Car(Scan))) + return TRUE; /* if two subterms with p>1 or one subterm with p>3 */ + Ok = TRUE; + } + return FALSE; + } + + T1 = term_FirstArgument(Term); + T2 = term_SecondArgument(Term); + + if (symbol_Equal(Top, fol_Implies())) { + Ok = ren_PFactorOk(T2); + /* return TRUE if -p(T1)>3 || p(T2)>3 || (-p(T1)>1 && p(T2)>1) */ + return ((ren_NotPFactorOk(T1) && (Ok || ren_NotPFactorBigger3(T1))) || + (Ok && ren_PFactorBigger3(T2))); + } + if (symbol_Equal(Top, fol_Equiv())) { + unsigned char T1Limit, T2Limit, NotT1Limit, NotT2Limit; + T1Limit = ren_PFactorOk(T1) ? 1 : 0; + NotT1Limit = ren_NotPFactorOk(T1) ? 1 : 0; + T2Limit = ren_PFactorOk(T2) ? 1 : 0; + NotT2Limit = ren_NotPFactorOk(T2) ? 1 : 0; + /* return TRUE, if p(T1)>2 || p(T2)>2 || -p(T1)>2 || -p(T2)>2 or at */ + /* least two values out of { p(T1),p(T2),-p(T1),-p(T2) } are > 1 */ + return ((T1Limit + NotT2Limit + NotT1Limit + T2Limit >= 2) || + (T1Limit!=0 && ren_PExtraFactorOk(T1)) || + (T2Limit!=0 && ren_PExtraFactorOk(T2)) || + (NotT1Limit!=0 && ren_NotPExtraFactorOk(T1)) || + (NotT2Limit!=0 && ren_NotPExtraFactorOk(T2))); + } + misc_StartErrorReport(); + misc_ErrorReport(" \n In ren_PFactorBigger3: unknown first order operator."); + misc_FinishErrorReport(); + return FALSE; +} + + +static BOOL ren_NotPFactorBigger3(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: TRUE if transforming the term <Term> in negative + polarity context results in more than three clauses. +***********************************************************/ +{ + SYMBOL Top; + TERM T1, T2; + LIST Scan; + BOOL Ok; + + /* if <Term> has the stamp, it will be renamed */ + if (term_HasTermStamp(Term) || term_IsAtom(Term)) + return FALSE; + + Top = term_TopSymbol(Term); + + if (fol_IsQuantifier(Top)) + return ren_NotPFactorBigger3(term_SecondArgument(Term)); + + if (symbol_Equal(Top, fol_Not())) + return ren_PFactorBigger3(term_FirstArgument(Term)); + + if (symbol_Equal(Top, fol_Or())) { + unsigned char Limit; /* invariant: -p >= Limit */ + Limit = list_Length(term_ArgumentList(Term)); + for (Scan=term_ArgumentList(Term); !list_Empty(Scan) && Limit<=3; + Scan=list_Cdr(Scan)) + if (ren_NotPFactorOk(list_Car(Scan))) { + Limit++; + if (Limit<=3 && ren_NotPExtraFactorOk(list_Car(Scan))) { + Limit++; + if (Limit<=3 && ren_NotPFactorBigger3(list_Car(Scan))) + Limit++; /* works for unary disjunction, too */ + } + } + return (Limit>3); + } + if (symbol_Equal(Top, fol_And())) { + Ok = FALSE; /* is set to TRUE if a subterm with -p factor >1 occurred */ + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (ren_NotPFactorOk(list_Car(Scan))) { + if (Ok || ren_NotPFactorBigger3(list_Car(Scan))) + return TRUE; /* if two subterms with -p>1 or one subterm with -p>3 */ + Ok = TRUE; + } + return FALSE; + } + + T1 = term_FirstArgument(Term); + T2 = term_SecondArgument(Term); + + if (symbol_Equal(Top, fol_Implies())) { + Ok = ren_NotPFactorOk(T2); + /* return TRUE if p(T1)>2 || -p(T2)>2 || (p(T1)>1 && -p(T2)>1) */ + return ((ren_PFactorOk(T1) && (Ok || ren_PExtraFactorOk(T1))) || + (Ok && ren_NotPExtraFactorOk(T2))); + } + if (symbol_Equal(Top, fol_Equiv())) { + unsigned char T1Limit, T2Limit, NotT1Limit, NotT2Limit; + T1Limit = ren_PFactorOk(T1) ? 1 : 0; + NotT1Limit = ren_NotPFactorOk(T1) ? 1 : 0; + T2Limit = ren_PFactorOk(T2) ? 1 : 0; + NotT2Limit = ren_NotPFactorOk(T2) ? 1 : 0; + /* return TRUE, if p(T1)>2 || p(T2)>2 || -p(T1)>2 || -p(T2)>2 or at */ + /* least two values out of { p(T1),p(T2),-p(T1),-p(T2) } are > 1 */ + return ((T1Limit + NotT2Limit + NotT1Limit + T2Limit >= 2) || + (T1Limit!=0 && ren_PExtraFactorOk(T1)) || + (T2Limit!=0 && ren_PExtraFactorOk(T2)) || + (NotT1Limit!=0 && ren_NotPExtraFactorOk(T1)) || + (NotT2Limit!=0 && ren_NotPExtraFactorOk(T2))); + } + misc_StartErrorReport(); + misc_ErrorReport(" \n In ren_NotPFactorBigger3: unknown first order operator."); + misc_FinishErrorReport(); + return FALSE; +} + + +static BOOL ren_AFactorOk(TERM Term1, TERM Term2) +/********************************************************** + INPUT: Two terms where <Term1> is a superterm of <Term2> + RETURNS: TRUE if the A-Factor of Term2 in Term1 is larger than one. +***********************************************************/ +{ + SYMBOL Top; + TERM Super; + + if (Term1 == Term2) + return FALSE; + + Super = term_Superterm(Term2); + Top = term_TopSymbol(Super); + + if (symbol_Equal(Top,fol_And()) || fol_IsQuantifier(Top)) + return ren_AFactorOk(Term1, Super); + + if (symbol_Equal(Top,fol_Not())) + return ren_BFactorOk(Term1, Super); + + if (symbol_Equal(Top,fol_Or())) { + LIST Scan; + TERM Sub; + for (Scan=term_ArgumentList(Super);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Sub = (TERM)list_Car(Scan); + if (Sub != Term2 && ren_PFactorOk(Sub)) + return TRUE; + } + return ren_AFactorOk(Term1, Super); + } + + if (symbol_Equal(Top,fol_Implies())) { + if (Term2 == term_FirstArgument(Super)) + return ren_BFactorOk(Term1, Super); + else + return (ren_NotPFactorOk(term_FirstArgument(Super)) || ren_AFactorOk(Term1, Super)); + } + if (symbol_Equal(Top,fol_Equiv())) { + int Pol; + Pol = ren_Polarity(Super); + if (Pol == 0) + return TRUE; + if (Term2 == term_FirstArgument(Super)) + Term2 = term_SecondArgument(Super); + else + Term2 = term_FirstArgument(Super); + + if (Pol == 1) + return (ren_NotPFactorOk(Term2) || ren_AFactorOk(Term1,Super)); + else + return (ren_PFactorOk(Term2) || ren_BFactorOk(Term1,Super)); + } + misc_StartErrorReport(); + misc_ErrorReport("In ren_AFactorOk: Unknown first order operator."); + misc_FinishErrorReport(); + return FALSE; +} + +static BOOL ren_AExtraFactorOk(TERM Term1, TERM Term2) +/********************************************************** + INPUT: Two terms where <Term1> is a superterm of <Term2> + RETURNS: TRUE if the A-Factor of Term2 in Term1 is larger than two. +***********************************************************/ +{ + SYMBOL Top; + TERM Super; + BOOL Ok; + + if (Term1 == Term2) + return FALSE; + + Super = term_Superterm(Term2); + Top = term_TopSymbol(Super); + + if (symbol_Equal(Top,fol_And()) || fol_IsQuantifier(Top)) + return ren_AExtraFactorOk(Term1, Super); + + if (symbol_Equal(Top,fol_Not())) + return ren_BExtraFactorOk(Term1, Super); + + if (symbol_Equal(Top,fol_Or())) { + LIST Scan; + TERM Sub; + Ok = FALSE; + for (Scan=term_ArgumentList(Super);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Sub = (TERM)list_Car(Scan); + if (Sub != Term2 && ren_PFactorOk(Sub)) { + if (Ok || ren_PExtraFactorOk(Sub)) + return TRUE; + Ok = TRUE; + } + } + /* return TRUE if (p>1 for one subterm and a>1) or a>2 */ + return (ren_AFactorOk(Term1,Super) && + (Ok || ren_AExtraFactorOk(Term1, Super))); + } + + if (symbol_Equal(Top,fol_Implies())) { + if (Term2 == term_FirstArgument(Super)) + return ren_BExtraFactorOk(Term1, Super); + else { + TERM T1; + T1 = term_FirstArgument(Super); + Ok = ren_AFactorOk(Term1, Super); + /* return TRUE if (-p>1 and a>1) or -p>2 or a>2 */ + return ((ren_NotPFactorOk(T1) && (Ok || ren_NotPExtraFactorOk(T1))) || + (Ok && ren_AExtraFactorOk(Term1,Super))); + } + } + if (symbol_Equal(Top,fol_Equiv())) { + if (Term2 == term_FirstArgument(Super)) + Term2 = term_SecondArgument(Super); + else + Term2 = term_FirstArgument(Super); + + switch (ren_Polarity(Super)) { + case 0: + return (ren_PFactorOk(Term2) || ren_NotPFactorOk(Term2) || + ren_AFactorOk(Term1,Super) || ren_BFactorOk(Term1,Super)); + case 1: + Ok = ren_AFactorOk(Term1, Super); + return ((ren_NotPFactorOk(Term2) && (Ok || ren_NotPExtraFactorOk(Term2))) || + (Ok && ren_AExtraFactorOk(Term1,Super))); + case -1: + Ok = ren_BFactorOk(Term1, Super); + return ((ren_PFactorOk(Term2) && (Ok || ren_PExtraFactorOk(Term2))) || + (Ok && ren_BExtraFactorOk(Term1,Super))); + } + } + misc_StartErrorReport(); + misc_ErrorReport("In ren_AExtraFactorOk: Unknown first order operator."); + misc_FinishErrorReport(); + return FALSE; +} + + +static BOOL ren_AFactorBigger3(TERM Term1, TERM Term2) +/********************************************************** + INPUT: Two terms where <Term1> is a superterm of <Term2> + RETURNS: TRUE if the A-Factor of Term2 in Term1 is larger than three. +***********************************************************/ +{ + TERM Super; + SYMBOL Top; + BOOL Ok; + + if (Term1 == Term2) + return FALSE; + + Super = term_Superterm(Term2); + Top = term_TopSymbol(Super); + + if (symbol_Equal(Top,fol_And()) || fol_IsQuantifier(Top)) + return ren_AFactorBigger3(Term1, Super); + + if (symbol_Equal(Top,fol_Not())) + return ren_BFactorBigger3(Term1, Super); + + if (symbol_Equal(Top, fol_Or())) { + LIST Scan; + TERM Sub; + Ok = FALSE; /* is set to TRUE if a subterm with p factor >1 occurred */ + for (Scan=term_ArgumentList(Super);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Sub = list_Car(Scan); + if (Term2 != Sub && ren_PFactorOk(Sub)) { + if (Ok || ren_PFactorBigger3(Sub)) + return TRUE; /* if two subterms with p>1 or one subterm with p>3 */ + Ok = TRUE; + } + } + return (ren_AFactorOk(Term1, Super) && + (Ok || ren_AFactorBigger3(Term1, Super))); + } + if (symbol_Equal(Top,fol_Implies())) { + if (Term2 == term_FirstArgument(Super)) + return ren_BFactorBigger3(Term1, Super); + else { + TERM T1; + T1 = term_FirstArgument(Super); + Ok = ren_AFactorOk(Term1, Super); + /* return TRUE if (-p>1 and a>1) or -p>3 or a>3 */ + return ((ren_NotPFactorOk(T1) && (Ok || ren_NotPFactorBigger3(T1))) || + (Ok && ren_AFactorBigger3(Term1, Super))); + } + } + if (symbol_Equal(Top,fol_Equiv())) { + if (Term2 == term_FirstArgument(Super)) + Term2 = term_SecondArgument(Super); + else + Term2 = term_FirstArgument(Super); + + switch (ren_Polarity(Super)) { + case 0: { + unsigned ALimit, BLimit, PLimit, NotPLimit; + ALimit = ren_AFactorOk(Term1, Super) ? 1 : 0; + BLimit = ren_BFactorOk(Term1, Super) ? 1 : 0; + PLimit = ren_PFactorOk(Term2) ? 1 : 0; + NotPLimit = ren_NotPFactorOk(Term2) ? 1 : 0; + /* return TRUE if a>2 || b>2 || p>2 || -p>2 or at least */ + /* two values out of { a, b, p, -p } are > 1 */ + return ((ALimit + BLimit + PLimit + NotPLimit >= 2) || + (PLimit!=0 && ren_PExtraFactorOk(Term2)) || + (NotPLimit!=0 && ren_NotPExtraFactorOk(Term2)) || + (ALimit!=0 && ren_AExtraFactorOk(Term1,Super)) || + (BLimit!=0 && ren_BExtraFactorOk(Term1,Super))); + } + case 1: + Ok = ren_AFactorOk(Term1, Super); + /* return TRUE if a>3 || -p>3 || (a>1 && -p>1) */ + return ((ren_NotPFactorOk(Term2) && (Ok || ren_NotPFactorBigger3(Term2))) || + (Ok && ren_AFactorBigger3(Term1, Super))); + case -1: + Ok = ren_BFactorOk(Term1, Super); + /* return TRUE if b>3 || p>3 || (b>1 && p>1) */ + return ((ren_PFactorOk(Term2) && (Ok || ren_PFactorBigger3(Term2))) || + (Ok && ren_BFactorBigger3(Term1, Super))); + } + } + misc_StartErrorReport(); + misc_ErrorReport("In ren_AFactorBigger3: Unknown first order operator."); + misc_FinishErrorReport(); + return FALSE; +} + + +static BOOL ren_BFactorOk(TERM Term1, TERM Term2) +/********************************************************** + INPUT: Two terms where <Term1> is a superterm of <Term2> + RETURNS: TRUE if the B-Factor of Term2 in Term1 is larger than one. +***********************************************************/ +{ + SYMBOL Top; + TERM Super; + + if (Term1 == Term2) + return FALSE; + + Super = term_Superterm(Term2); + Top = term_TopSymbol(Super); + + if (symbol_Equal(Top,fol_Or()) || fol_IsQuantifier(Top)) + return ren_BFactorOk(Term1, Super); + + if (symbol_Equal(Top,fol_Not())) + return ren_AFactorOk(Term1, Super); + + if (symbol_Equal(Top,fol_And())) { + LIST Scan; + TERM Sub; + for (Scan=term_ArgumentList(Super);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Sub = (TERM)list_Car(Scan); + if (Sub != Term2 && ren_NotPFactorOk(Sub)) + return TRUE; + } + return ren_BFactorOk(Term1, Super); + } + + if (symbol_Equal(Top,fol_Implies())) { + if (Term2 == term_FirstArgument(Super)) + return (ren_PFactorOk(term_SecondArgument(Super)) || ren_AFactorOk(Term1, Super)); + else + return ren_BFactorOk(Term1, Super); + } + if (symbol_Equal(Top,fol_Equiv())) { + int Pol; + Pol = ren_Polarity(Super); + if (Pol == 0) + return TRUE; + if (Term2 == term_FirstArgument(Super)) + Term2 = term_SecondArgument(Super); + else + Term2 = term_FirstArgument(Super); + + if (Pol == 1) + return (ren_PFactorOk(Term2) || ren_AFactorOk(Term1,Super)); + else + return (ren_NotPFactorOk(Term2) || ren_BFactorOk(Term1,Super)); + } + misc_StartErrorReport(); + misc_ErrorReport("In ren_BFactorOk: Unknown first order operator."); + misc_FinishErrorReport(); + return FALSE; +} + +static BOOL ren_BExtraFactorOk(TERM Term1, TERM Term2) +/********************************************************** + INPUT: Two terms where <Term1> is a superterm of <Term2> + RETURNS: TRUE if the B-Factor of Term2 in Term1 is larger than two. +***********************************************************/ +{ + SYMBOL Top; + TERM Super; + BOOL Ok; + + if (Term1 == Term2) + return FALSE; + + Super = term_Superterm(Term2); + Top = term_TopSymbol(Super); + + if (symbol_Equal(Top,fol_Or()) || fol_IsQuantifier(Top)) + return ren_BExtraFactorOk(Term1, Super); + + if (symbol_Equal(Top,fol_Not())) + return ren_AExtraFactorOk(Term1, Super); + + if (symbol_Equal(Top,fol_And())) { + LIST Scan; + TERM Sub; + Ok = FALSE; + for (Scan=term_ArgumentList(Super);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Sub = (TERM)list_Car(Scan); + if (Sub != Term2 && ren_NotPFactorOk(Sub)) { + if (Ok || ren_NotPExtraFactorOk(Sub)) + return TRUE; + Ok = TRUE; + } + } + /* return TRUE if (-p>1 for one subterm and b>1) or b>2 */ + return (ren_BFactorOk(Term1,Super) && + (Ok || ren_BExtraFactorOk(Term1, Super))); + } + + if (symbol_Equal(Top,fol_Implies())) { + if (Term2 == term_FirstArgument(Super)) { + TERM T2; + T2 = term_SecondArgument(Super); + Ok = ren_AFactorOk(Term1, Super); + /* return TRUE if (p>1 and a>1) or p>2 or a>2 */ + return ((ren_PFactorOk(T2) && (Ok || ren_PExtraFactorOk(T2))) || + (Ok && ren_AExtraFactorOk(Term1, Super))); + } + else + return ren_BExtraFactorOk(Term1, Super); + } + if (symbol_Equal(Top,fol_Equiv())) { + if (Term2 == term_FirstArgument(Super)) + Term2 = term_SecondArgument(Super); + else + Term2 = term_FirstArgument(Super); + + switch (ren_Polarity(Super)) { + case 0: + return (ren_PFactorOk(Term2) || ren_NotPFactorOk(Term2) || + ren_AFactorOk(Term1,Super) || ren_BFactorOk(Term1,Super)); + case 1: + Ok = ren_AFactorOk(Term1, Super); + return ((ren_PFactorOk(Term2) && (Ok || ren_PExtraFactorOk(Term2))) || + (Ok && ren_AExtraFactorOk(Term1,Super))); + case -1: + Ok = ren_BFactorOk(Term1, Super); + return ((ren_NotPFactorOk(Term2) && (Ok || ren_NotPExtraFactorOk(Term2))) || + (Ok && ren_BExtraFactorOk(Term1,Super))); + } + } + misc_StartErrorReport(); + misc_ErrorReport("In ren_BExtraFactorOk: Unknown first order operator."); + misc_FinishErrorReport(); + return FALSE; +} + +static BOOL ren_BFactorBigger3(TERM Term1, TERM Term2) +/********************************************************** + INPUT: Two terms where <Term1> is a superterm of <Term2> + RETURNS: TRUE if the B-Factor of Term2 in Term1 is larger than three. +***********************************************************/ +{ + TERM Super; + SYMBOL Top; + BOOL Ok; + + if (Term1 == Term2) + return FALSE; + + Super = term_Superterm(Term2); + Top = term_TopSymbol(Super); + + if (fol_IsQuantifier(Top) || symbol_Equal(Top, fol_Or())) + return ren_BFactorBigger3(Term1, Super); + + if (symbol_Equal(Top, fol_Not())) + return ren_AFactorBigger3(Term1, Super); + + if (symbol_Equal(Top, fol_And())) { + LIST Scan; + TERM Sub; + Ok = FALSE; /* is set to TRUE if a subterm with -p factor >1 occurred */ + for (Scan=term_ArgumentList(Super);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Sub = list_Car(Scan); + if (Term2 != Sub && ren_NotPFactorOk(Sub)) { + if (Ok || ren_NotPFactorBigger3(Sub)) + return TRUE; /* if two subterms with -p>1 or one subterm with -p>3 */ + Ok = TRUE; + } + } + return (ren_BFactorOk(Term1, Super) && + (Ok || ren_BFactorBigger3(Term1, Super))); + } + if (symbol_Equal(Top,fol_Implies())) { + if (Term2 == term_FirstArgument(Super)) { + TERM T2; + T2 = term_SecondArgument(Super); + Ok = ren_AFactorOk(Term1, Super); + /* return TRUE if (p>1 and a>1) or p>3 or a>3 */ + return ((ren_PFactorOk(T2) && (Ok || ren_PFactorBigger3(T2))) || + (Ok && ren_AFactorBigger3(Term1, Super))); + } + else + return ren_BFactorBigger3(Term1, Super); + } + if (symbol_Equal(Top,fol_Equiv())) { + if (Term2 == term_FirstArgument(Super)) + Term2 = term_SecondArgument(Super); + else + Term2 = term_FirstArgument(Super); + + switch (ren_Polarity(Super)) { + case 0: { + unsigned ALimit, BLimit, PLimit, NotPLimit; + ALimit = ren_AFactorOk(Term1, Super) ? 1 : 0; + BLimit = ren_BFactorOk(Term1, Super) ? 1 : 0; + PLimit = ren_PFactorOk(Term2) ? 1 : 0; + NotPLimit = ren_NotPFactorOk(Term2) ? 1 : 0; + /* return TRUE if a>2 || b>2 || p>2 || -p>2 or at least */ + /* two values out of { a, b, p, -p } are > 1 */ + return ((ALimit + BLimit + PLimit + NotPLimit >= 2) || + (PLimit!=0 && ren_PExtraFactorOk(Term2)) || + (NotPLimit!=0 && ren_NotPExtraFactorOk(Term2)) || + (ALimit!=0 && ren_AExtraFactorOk(Term1,Super)) || + (BLimit!=0 && ren_BExtraFactorOk(Term1,Super))); + } + case 1: + Ok = ren_AFactorOk(Term1, Super); + /* return TRUE if a>3 || -p>3 || (a>1 && -p>1) */ + return ((ren_PFactorOk(Term2) && (Ok || ren_PFactorBigger3(Term2))) || + (Ok && ren_AFactorBigger3(Term1, Super))); + case -1: + Ok = ren_BFactorOk(Term1, Super); + /* return TRUE if b>3 || p>3 || (b>1 && p>1) */ + return ((ren_NotPFactorOk(Term2) && (Ok || ren_NotPFactorBigger3(Term2))) || + (Ok && ren_BFactorBigger3(Term1, Super))); + } + } + misc_StartErrorReport(); + misc_ErrorReport("In ren_BFactorBigger3: Unknown first order operator."); + misc_FinishErrorReport(); + return FALSE; +} + + +static BOOL ren_HasBenefit(TERM Term1, TERM Term2, int Pol) +/********************************************************** + INPUT: Two terms and the polarity of the 2nd term in the overall formula. + RETURNS: TRUE if renaming <Term1> in <Term2> results in a positive benefit. + CAUTION: It is assumed that all superterms are set ! +***********************************************************/ +{ + BOOL PFacOk, NotPFacOk, AFacOk, BFacOk; + + switch (Pol) { + + case 0: + PFacOk = ren_PFactorOk(Term2); + NotPFacOk = ren_NotPFactorOk(Term2); + AFacOk = ren_AFactorOk(Term1,Term2); + BFacOk = ren_BFactorOk(Term1,Term2); + return ((AFacOk && BFacOk && PFacOk && NotPFacOk) || + (AFacOk && PFacOk && (ren_PExtraFactorOk(Term2) || ren_AExtraFactorOk(Term1,Term2))) || + (BFacOk && NotPFacOk && (ren_NotPExtraFactorOk(Term2) || ren_BExtraFactorOk(Term1,Term2)))); + break; + + case 1: + return (ren_PFactorOk(Term2) && ren_AFactorOk(Term1,Term2)); + break; + + case -1: + return (ren_NotPFactorOk(Term2) && ren_BFactorOk(Term1,Term2)); + break; + } + misc_StartErrorReport(); + misc_ErrorReport("In ren_HasBenefit: Unknown polarity."); + misc_FinishErrorReport(); + return FALSE; +} + +static BOOL ren_HasNonZeroBenefit(TERM Term1, int Pol1, TERM Term2, int Pol2) +/********************************************************** + INPUT: Two terms and the polarity of the terms in the overall formula. + RETURNS: TRUE if renaming <Term1> in <Term2> results in non-zero positive benefit. + CAUTION: It is assumed that all superterms are set ! +***********************************************************/ +{ + BOOL PFacOk, NotPFacOk, AFacOk, BFacOk, PEFacOk, NotPEFacOk, AEFacOk, BEFacOk; + switch (Pol2) { + case 0: + PFacOk = ren_PFactorOk(Term2); + NotPFacOk = ren_NotPFactorOk(Term2); + AFacOk = ren_AFactorOk(Term1,Term2); + BFacOk = ren_BFactorOk(Term1,Term2); + PEFacOk = PFacOk && ren_PExtraFactorOk(Term2); + NotPEFacOk = NotPFacOk && ren_NotPExtraFactorOk(Term2); + AEFacOk = AFacOk && ren_AExtraFactorOk(Term1,Term2); + BEFacOk = BFacOk && ren_BExtraFactorOk(Term1,Term2); + + return ((AFacOk && BFacOk && PFacOk && NotPFacOk && (AEFacOk || BEFacOk || PEFacOk || NotPEFacOk)) || + (PEFacOk && AEFacOk) || (NotPEFacOk && BEFacOk) || + (AFacOk && ren_PFactorBigger3(Term2)) || + (BFacOk && ren_NotPFactorBigger3(Term2)) || + (PFacOk && ren_AFactorBigger3(Term1, Term2)) || + (NotPFacOk && ren_BFactorBigger3(Term1, Term2)) || + /* The following conditions don't imply benefit > 0, but allow */ + /* some additional renamings with benefit 0. */ + (Pol1 == 0 && (symbol_Equal(term_TopSymbol(Term2),fol_Equiv()) || + ren_HasNEquivFathers(Term1,Term2,1))) || + ren_HasNEquivFathers(Term1,Term2,2)); + break; + + case 1: + /* return TRUE if (p>1 && a>2) || (p>2 && a>1) */ + AFacOk = ren_AFactorOk(Term1,Term2); + return ((ren_PFactorOk(Term2) && (AFacOk || ren_AFactorOk(Term1,Term2))) || + (AFacOk && ren_AExtraFactorOk(Term1,Term2))); + break; + + case -1: + /* return TRUE if (-p>1 && b>2) || (-p>2 && b>1) */ + BFacOk = ren_BFactorOk(Term1,Term2); + return ((ren_NotPFactorOk(Term2) && (BFacOk || ren_NotPExtraFactorOk(Term2))) || + (BFacOk && ren_BExtraFactorOk(Term1,Term2))); + break; + } + misc_StartErrorReport(); + misc_ErrorReport("In ren_HasNonZeroBenefit: Unknown polarity."); + misc_FinishErrorReport(); + return FALSE; +} + + +static LIST ren_GetRenamings(TERM Term1, TERM Term2, int Pol) +/********************************************************** + INPUT: Two terms and the polarity of the 2nd term in the overall formula. + RETURNS: The list of subterms below <Term2> that have a positive renaming + benefit. + EFFECT: All renamed formulae are stamped. +***********************************************************/ +{ + SYMBOL Top; + LIST Result,Scan; + + Result = list_Nil(); + + /* Don't rename formulae starting with "not" */ + while (symbol_Equal(term_TopSymbol(Term2), fol_Not())) { + Term2 = term_FirstArgument(Term2); + Pol = -Pol; + } + + if (term_IsAtom(Term2)) + return Result; + + Top = term_TopSymbol(Term2); + + /* Don't rename arguments of a quantifier */ + if (term_Superterm(Term2) && + !fol_IsQuantifier(term_TopSymbol(term_Superterm(Term2))) && + ren_HasBenefit(Term1, Term2, Pol)) { + Result = list_Cons(Term2,Result); + term_SetTermStamp(Term2); + Term1 = Term2; + } + + if (fol_IsQuantifier(Top)) + Result = list_Nconc(Result,ren_GetRenamings(Term1, term_SecondArgument(Term2), Pol)); + else if (symbol_Equal(Top,fol_And()) || symbol_Equal(Top,fol_Or())) + for (Scan=term_ArgumentList(Term2);!list_Empty(Scan);Scan=list_Cdr(Scan)) + Result = list_Nconc(Result,ren_GetRenamings(Term1,list_Car(Scan),Pol)); + else if (symbol_Equal(Top,fol_Implies())) { + Result = list_Nconc(Result,ren_GetRenamings(Term1,term_FirstArgument(Term2),-Pol)); + Result = list_Nconc(Result,ren_GetRenamings(Term1,term_SecondArgument(Term2),Pol)); + } else if (symbol_Equal(Top,fol_Equiv())) { + Result = list_Nconc(Result, ren_GetRenamings(Term1,term_FirstArgument(Term2),0)); + Result = list_Nconc(Result, ren_GetRenamings(Term1,term_SecondArgument(Term2),0)); + } else { + misc_StartErrorReport(); + misc_ErrorReport("In ren_GetRenamings: Unknown first-order operator."); + misc_FinishErrorReport(); + } + + return Result; +} + +static int ren_Polarity(TERM Term) +/********************************************************** + INPUT: A term where the existence of superterms is assumed!. + RETURNS: The polarity of Term with respect to its superterms. +***********************************************************/ +{ + TERM SuperTerm; + + SuperTerm = term_Superterm(Term); + + if (SuperTerm) { + SYMBOL Top; + Top = term_TopSymbol(SuperTerm); + if (symbol_Equal(Top,fol_And()) || symbol_Equal(Top,fol_Or()) || + fol_IsQuantifier(Top)) + return ren_Polarity(SuperTerm); + if (symbol_Equal(Top,fol_Not())) + return (-ren_Polarity(SuperTerm)); + if (symbol_Equal(Top,fol_Equiv())) + return 0; + if (symbol_Equal(Top,fol_Implies())) { + if (Term == term_FirstArgument(SuperTerm)) + return (-ren_Polarity(SuperTerm)); + else + return ren_Polarity(SuperTerm); + } + misc_StartErrorReport(); + misc_ErrorReport("In ren_Polarity: Unknown first-order operator."); + misc_FinishErrorReport(); + } + + return 1; +} + + +static LIST ren_RemoveTerm(TERM Term, LIST Renamings) +/********************************************************** + INPUT: A formula and a list of renamings. + RETURNS: The renaming list where <Term> is removed from + the renamings. + CAUTION: The list and the renamings are destructively changed. +***********************************************************/ +{ + LIST Scan; + RENAMING Renaming; + + /* Remove the Term from all renamings. In case the Hit term equals <Term> */ + /* turn the renaming into a general renaming */ + for (Scan=Renamings;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Renaming = (RENAMING)list_Car(Scan); + if (ren_Hit(Renaming) == Term) { + if (list_Empty(ren_Matches(Renaming))) { + ren_Delete(Renaming); + list_Rplaca(Scan, NULL); + } + else + ren_SetGeneral(Renaming, TRUE); + } + else + ren_SetMatches(Renaming, list_PointerDeleteElement(ren_Matches(Renaming), Term)); + } + + /* Take care for the NULL pointers */ + Renamings = list_PointerDeleteElement(Renamings, NULL); + + return Renamings; +} + +static LIST ren_RemoveAllSubterms(TERM Term, LIST Renamings) +/********************************************************** + INPUT: A formula and a list of renamings. + RETURNS: The renaming list where <Term> and all its subterms are + removed from the renamings. + CAUTION: The list and the renamings are destructively changed. +***********************************************************/ +{ + Renamings = ren_RemoveTerm(Term, Renamings); + + if (!symbol_IsPredicate(term_TopSymbol(Term))) { + if (fol_IsQuantifier(term_TopSymbol(Term))) + Renamings = ren_RemoveAllSubterms(term_SecondArgument(Term), Renamings); + else { + LIST Scan; + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + Renamings = ren_RemoveAllSubterms(list_Car(Scan), Renamings); + } + } + + return Renamings; +} + + + +static LIST ren_SolveDependencies(LIST Renamings) +/********************************************************** + INPUT: A list of renamings sorted by depth of the hits. + RETURNS: The renaming list where dependences are solved, i.e., if + a formula occurs in the matches of some renaming, then + all its subterms are removed from other renamings, since + the formulae of additional matches completely disappear + after application of the renaming. + In case a subterm is the hit of another renaming but this + renaming has further matches, the further matches are turned + into new individual renamings. + CAUTION: The list and the renamings are destructively changed. +***********************************************************/ +{ + LIST Scan; + RENAMING Renaming; + TERM ActMatch; + + if (list_Empty(Renamings)) + return Renamings; + + Renaming = (RENAMING)list_Car(Renamings); + for (Scan=ren_Matches(Renaming);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + ActMatch = (TERM)list_Car(Scan); + list_Rplacd(Renamings, ren_RemoveAllSubterms(ActMatch, list_Cdr(Renamings))); + } + list_Rplacd(Renamings, ren_SolveDependencies(list_Cdr(Renamings))); + + return Renamings; +} + + +static TERM ren_FormulaRename(TERM Term, LIST Renamings, PRECEDENCE Precedence, + LIST *SkolemSymbols) +/********************************************************** + INPUT: A term and a list of renamings where all + dependencies between the renaming terms are + solved and a precedence. + RETURNS: The renamed formula with respect to the renaming + list and all newly introduced Skolem symbols for + renamings are added to <SkolemSymbols>. + EFFECT: New Skolem predicates are created, and their precedence + is set in <Precedence>. + CAUTION: The formula <Term> is destructively changed. + The renamings are destructively changed. +***********************************************************/ +{ + TERM Result,ActTerm,Hit,DefTerm,Superterm,NewTerm; + LIST Scan,FreeVariables,Args,AllMatches; + SYMBOL ActSymbol; + RENAMING Renaming; + + DefTerm = (TERM)NULL; + AllMatches = list_Nil(); + + if (!list_Empty(Renamings)) + Result = term_Create(fol_And(),list_List(Term)); + else + return Term; + + ActSymbol = 0; + + while (!list_Empty(Renamings)) { + + Renaming = (RENAMING)list_Car(Renamings); + Renamings = list_Cdr(Renamings); + Hit = ren_Hit(Renaming); + Superterm = term_Superterm(Hit); + FreeVariables = fol_FreeVariables(Hit); + ActSymbol = symbol_CreateSkolemPredicate(list_Length(FreeVariables), + Precedence); + *SkolemSymbols = list_Cons((POINTER)ActSymbol,*SkolemSymbols); + + /* printf("\n");fol_PrettyPrintDFG(ren_Hit(Renaming));printf("\n");*/ + + /* Install Definition */ + if (ren_General(Renaming)) /* for general renamings the hit formula will be eventually deleted */ + Hit = term_Copy(Hit); + NewTerm = term_Create(ActSymbol, term_CopyTermList(FreeVariables)); + switch (ren_OverallPolarity(Renaming)) { + case 0: + DefTerm = term_Create(fol_Equiv(),list_Cons(term_Copy(NewTerm),list_List(Hit))); + break; + + case 1: + DefTerm = term_Create(fol_Implies(),list_Cons(term_Copy(NewTerm),list_List(Hit))); + break; + + case -1: + DefTerm = term_Create(fol_Implies(),list_Cons(Hit,list_List(term_Copy(NewTerm)))); + break; + } + term_RplacSuperterm(term_FirstArgument(DefTerm),DefTerm); + term_RplacSuperterm(term_SecondArgument(DefTerm),DefTerm); + if (!list_Empty(FreeVariables)) + DefTerm = fol_CreateQuantifier(fol_All(), term_CopyTermList(FreeVariables), + list_List(DefTerm)); + term_RplacArgumentList(Result,list_Nconc(term_ArgumentList(Result),list_List(DefTerm))); + + /* Replace hit if renaming is not general */ + if (!ren_General(Renaming)) { + term_RplacSuperterm(NewTerm, Superterm); + for (Args=term_ArgumentList(Superterm);!list_Empty(Args); Args=list_Cdr(Args)) + if ((TERM)list_Car(Args) == Hit) { + list_Rplaca(Args, NewTerm); + break; + } + } + else + term_Delete(NewTerm); + + + for (Scan=ren_Matches(Renaming); !list_Empty(Scan); Scan=list_Cdr(Scan)) { + + ActTerm = (TERM)list_Car(Scan); + Superterm = term_Superterm(ActTerm); + + /* Always make new predicate term */ + NewTerm = term_Create(ActSymbol, term_CopyTermList(FreeVariables)); + /* Bind the variables correctly */ + /*puts("\n"); fol_PrettyPrintDFG(Result); + printf("\n Hit:\n"); term_PrettyPrint(Hit); + printf("\n ActTerm:\n"); term_PrettyPrint(ActTerm); printf("\n");*/ + cont_StartBinding(); + if (unify_MatchFlexible(cont_LeftContext(), Hit, ActTerm)) + cont_ApplyBindingsModuloMatching(cont_LeftContext(), NewTerm, TRUE); + else { + misc_StartErrorReport(); + misc_ErrorReport("\n In ren_FormulaRename: Further match is no instance of hit.\n"); + misc_FinishErrorReport(); + } + cont_BackTrack(); + + /* Now replace match */ + term_RplacSuperterm(NewTerm, Superterm); + for (Args=term_ArgumentList(Superterm);!list_Empty(Args); Args=list_Cdr(Args)) + if (list_Car(Args) == ActTerm) { + list_Rplaca(Args, NewTerm); + break; + } + } + AllMatches = list_Nconc(ren_Matches(Renaming), AllMatches); /* Delete later due to dependencies */ + ren_SetMatches(Renaming, list_Nil()); + list_Delete(FreeVariables); + } + list_DeleteWithElement(AllMatches, (void (*)(POINTER)) term_Delete); + return Result; +} + +static LIST ren_FreeRenaming(LIST Renamings) +/********************************************************** + INPUT: A list of renamings. + RETURNS: The list of candidates without renamings that have + benefit zero. + CAUTION: Destructive. +***********************************************************/ +{ + LIST Scan; + TERM Father, Term; + RENAMING Candidate; + + for (Scan=Renamings;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Candidate = (RENAMING)list_Car(Scan); + if (list_Empty(ren_Matches(Candidate))) { + Term = ren_Hit(Candidate); + Father = term_Superterm(Term); + while (!term_HasTermStamp(Father) && term_Superterm(Father)) { + Father = term_Superterm(Father); + } + + term_ResetTermStamp(Term); /* Needed for P-Factor check */ + if (ren_General(Candidate) || /* a general renaming without matches is useless */ + !ren_HasNonZeroBenefit(Father, ren_Polarity(Father), + Term, ren_OverallPolarity(Candidate))) { + ren_Delete(Candidate); + list_Rplaca(Scan,NULL); + } else { + /* Term will be renamed */ + term_SetTermStamp(Term); /* Undo temporary change */ + } + } + } + + Renamings = list_PointerDeleteElement(Renamings,NULL); + + return Renamings; +} + +static LIST ren_FurtherMatches(TERM Formula, LIST Formulas) +/********************************************************** + INPUT: A formula and a list of formulas that are candidates + for renaming inside the formula. + RETURNS: A list of renamings where additional matches of + the already found formulas in <Formula> are considered. + First the most general formula <Hit> of any renaming inside + <Formula> is computed, then all instances of <Hit> inside + <Formula> built the actual renaming. + No formula occurs twice in the resulting renamings. +***********************************************************/ +{ + LIST Scan1, Scan2, Allmatches, Matchables, Renamings; + TERM Hit; + int Polarity, NewPol; + + Allmatches = list_Nil(); + Renamings = list_Nil(); + + for (Scan1=Formulas; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { + Hit = (TERM)list_Car(Scan1); + + if (!list_PointerMember(Allmatches, Hit)) { + Matchables = list_Cons(Hit, fol_Generalizations(Formula, Hit)); + Hit = fol_MostGeneralFormula(Matchables); /* Could be further improved: construct it ! */ + list_Delete(Matchables); + + if (!list_PointerMember(Allmatches, Hit)) { /* Potentially <Hit> is now different */ + Allmatches = list_Cons(Hit,Allmatches); + Matchables = fol_Instances(Formula, Hit); + Polarity = ren_Polarity(Hit); + + for (Scan2=Matchables; !list_Empty(Scan2); Scan2=list_Cdr(Scan2)) { + if (list_PointerMember(Allmatches, list_Car(Scan2))) + list_Rplaca(Scan2, NULL); + else { + NewPol = ren_Polarity(list_Car(Scan2)); + if (NewPol != Polarity) + Polarity = 0; + } + } + Matchables = list_PointerDeleteElement(Matchables, NULL); + Allmatches = list_Nconc(list_Copy(Matchables), Allmatches); + Renamings = list_Cons(ren_Create(Hit, Matchables, Polarity),Renamings); + } + } + } + list_Delete(Allmatches); + + return Renamings; +} + + +TERM ren_Rename(TERM Term, PRECEDENCE Precedence, LIST *SkolemSymbols, + BOOL Document, BOOL Match) +/********************************************************** + INPUT: A term, a precedence, a pointer to a list of + Skolem symbols, a flag indicating whether the + renamings should be documented and a flag + indicating whether matching subterms should be + renamed using the same predicate. + RETURNS: The possibly changed Term where subformulae are renamed + if this results in a smaller clause normal form, with + respect to the number of clauses. The newly introduced + Skolem predicates are added to <SkolemSymbols>. + The precedence of the new symbols is set in <Precedence>. + CAUTION: Formulae are changed destructively. + This function expects that both conjunctions and disjunction + have at least two arguments! +***********************************************************/ +{ + LIST Renamings, Scan, Formulas; + + Renamings = list_Nil(); + Formulas = list_Nil(); + + if (term_StampOverflow(ren_STAMPID)) + ren_ResetTermStamp(Term); + +#ifdef CHECK + fol_CheckFatherLinks(Term); +#endif + + term_StartStamp(); + + Formulas = ren_GetRenamings(Term, Term, 1); + + /* Formulas = list_GreaterNumberSort(Formulas, (NAT (*)(POINTER)) fol_Depth); */ + + if (Match) + Renamings = ren_FurtherMatches(Term, Formulas); + else { + for (Scan=Formulas;!list_Empty(Scan);Scan=list_Cdr(Scan)) + Renamings = list_Cons(ren_Create(list_Car(Scan),list_Nil(),ren_Polarity(list_Car(Scan))),Renamings); + } + + Renamings = ren_FreeRenaming(Renamings); + + Renamings = list_Sort(Renamings, (BOOL (*) (POINTER, POINTER))ren_RootDistanceSmaller); + /* for dependencies sort renamings top down */ + + Renamings = ren_SolveDependencies(Renamings); /* dependencies in further matches */ + + Renamings = ren_FreeRenaming(Renamings); /* possibly depency solving has created non-zero benefit renamings */ + + if (!list_Empty(Renamings) && Document) { + puts("\n\n\t Renaming term:"); + fol_PrettyPrintDFG(Term); + for (Scan=Renamings;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + puts("\n"); + ren_PrettyPrint((RENAMING)list_Car(Scan)); + } + puts("\n"); + } + + Term = ren_FormulaRename(Term, Renamings, Precedence, SkolemSymbols); + + if (!list_Empty(Renamings) && Document) { + puts("\n\n\t Renamed term:"); + fol_PrettyPrintDFG(Term); + puts("\n"); + } + + list_DeleteWithElement(Renamings, (void (*)(POINTER)) ren_Delete); + list_Delete(Formulas); + + term_StopStamp(); + + return Term; +} + +void ren_PrettyPrint(RENAMING Ren) +/********************************************************** + INPUT: A renaming. + EFFECT: pretty prints the renaming to <stdout> +***********************************************************/ +{ + LIST Matches; + + puts("\t Renaming:"); + puts("\n\t ========= \n"); + fol_PrettyPrintDFG(ren_Hit(Ren)); + puts("\n\n\t Instances:"); + for (Matches=ren_Matches(Ren); !list_Empty(Matches); Matches=list_Cdr(Matches)) { + fol_PrettyPrintDFG(list_Car(Matches)); + puts("\n"); + } + printf("\n\t Polarity: %d\n", ren_OverallPolarity(Ren)); + printf("\n\t General : %d\n", (ren_General(Ren) ? 1 : 0)); +} diff --git a/test/spass/renaming.h b/test/spass/renaming.h new file mode 100644 index 0000000000000000000000000000000000000000..663363e3005ebd105bcf645b2357f3066f290d6b --- /dev/null +++ b/test/spass/renaming.h @@ -0,0 +1,168 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * RENAMING * */ +/* * * */ +/* * $Module: REN * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + + +#ifndef _SPASS_RENAMING_ +#define _SPASS_RENAMING_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "misc.h" +#include "foldfg.h" +#include "unify.h" +#include "vector.h" + +/**************************************************************/ +/* Data Structures and Constants */ +/**************************************************************/ + +typedef struct { + TERM hit; + LIST matches; + BOOL general; + int polarity; +} *RENAMING, RENAMING_NODE; + +/* <hit> is the formula that has a positive benefit */ +/* <matches> are further matches of <hit> in the overall formula */ +/* <general> is TRUE iff the <hit> formula must not be replaced but */ +/* is a generalzation of the matches formulae that are to */ +/* be replaced */ +/* <polarity> is the most general polarity of <hit> and all <matches> */ + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + + +static __inline__ int ren_OverallPolarity(RENAMING ren) +{ + return ren->polarity; +} + +static __inline__ TERM ren_Hit(RENAMING ren) +{ + return ren->hit; +} + +static __inline__ LIST ren_Matches(RENAMING ren) +{ + return ren->matches; +} + +static __inline__ BOOL ren_General(RENAMING ren) +{ + return ren->general; +} + +static __inline__ void ren_SetMatches(RENAMING ren, LIST matches) +{ + ren->matches = matches; +} + +static __inline__ void ren_SetHit(RENAMING ren, TERM hit) +{ + ren->hit = hit; +} + +static __inline__ void ren_SetOverallPolarity(RENAMING ren, int polarity) +{ + ren->polarity = polarity; +} + +static __inline__ void ren_SetGeneral(RENAMING ren, BOOL general) +{ + ren->general = general; +} + + + +static __inline__ RENAMING ren_Create(TERM hit, LIST matches, int polarity) +/************************************************************** + INPUT: A formula, a list of further matching formulae + and the overall polarity of the <hit> and the further <matches>. + RETURNS: A new renaming object, which is initialized. + General is set to false. + MEMORY: Allocates memory for the RENAMING. +***************************************************************/ +{ + RENAMING Result; + + Result = (RENAMING)memory_Malloc(sizeof(RENAMING_NODE)); + Result->hit = hit; + Result->matches = matches; + Result->polarity = polarity; + Result->general = FALSE; + + return Result; +} + +static __inline__ void ren_Delete(RENAMING ren) +/************************************************************** + INPUT: A renaming. + RETURNS: void. + MEMORY: Frees memory for the RENAMING and the matches list. + Formulae are not deleted. +***************************************************************/ +{ + list_Delete(ren->matches); + memory_Free(ren,sizeof(RENAMING_NODE)); +} + + +/**************************************************************/ +/* Function Prototypes */ +/**************************************************************/ + +void ren_Init(void); +TERM ren_Rename(TERM, PRECEDENCE, LIST*,BOOL, BOOL); +void ren_PrettyPrint(RENAMING); + +#endif diff --git a/test/spass/resolution.c b/test/spass/resolution.c new file mode 100644 index 0000000000000000000000000000000000000000..96e4bff580338831db6573160a210b0c15f276c5 --- /dev/null +++ b/test/spass/resolution.c @@ -0,0 +1,178 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * RESOLUTION * */ +/* * * */ +/* * $Module: RESOLUTION * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "resolution.h" + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + + +void res_InsertClauseIndex(CLAUSE clause, st_INDEX stindex) +/********************************************************** + INPUT: A st_INDEX and a clause. + RETURNS: Inserts the clause in the st_INDEX stindex. + CAUTION: None. +***********************************************************/ +{ + int n,j; + + n = clause_Length(clause); + for (j = 0; j < n; j++) + st_EntryCreate(stindex, + clause_GetLiteral(clause,j), + clause_GetLiteralTerm(clause,j), + cont_LeftContext()); +} + + +void res_DeleteClauseIndex(CLAUSE clause, st_INDEX stindex) +/********************************************************** + INPUT: A st_INDEX and a clause. + RETURNS: Deletes the clause from the st_INDEX stindex. + CAUTION: None. +***********************************************************/ +{ + int n, j; + + n = clause_Length(clause); + for (j = 0; j < n; j++) + if (!st_EntryDelete(stindex, + clause_GetLiteral(clause,j), + clause_GetLiteralTerm(clause,j), + cont_LeftContext())) + misc_DumpCore(); +} + + + +CLAUSE res_SelectLightestClause(LIST clauselist) +/********************************************************** + INPUT: A list of clauses. + RETURNS: The lightest clause of the clauselist. + CAUTION: None. +***********************************************************/ +{ + CLAUSE clause; + LIST scan; + int min; + + clause = list_Car(clauselist); + min = clause_Weight(clause); + + for (scan=list_Cdr(clauselist); !list_Empty(scan); scan=list_Cdr(scan)) { + if (clause_Weight(list_Car(scan)) < min) { + clause = list_Car(scan); + min = clause_Weight(clause); + } + } + return clause; +} + + +BOOL res_HasTautology(CLAUSE clause) +/********************************************************** + INPUT: A clauses. + RETURNS: TRUE if the clause contains a complementary + literal pair and FALSE otherwise. + CAUTION: None. +***********************************************************/ +{ + BOOL found; + TERM literal1; + int i, j, n; + + found = FALSE; + n = clause_Length(clause); + + for (i = 0; i < n && !found; i++) { + literal1 = fol_ComplementaryTerm(clause_GetLiteralTerm(clause,i)); + for (j = 0; j < n && !found; j++) + if (j != i && term_Equal(literal1, clause_GetLiteralTerm(clause,j))) + found = TRUE; + + term_Delete(literal1); + } + return found; +} + + + +BOOL res_BackSubWithLength(CLAUSE clause, st_INDEX stindex) +/********************************************************** + INPUT: A clauses and an index. + RETURNS: TRUE if a clause of the index subsumes the clause clause + and length(clause) >= length(clause of index). + CAUTION: None. +***********************************************************/ +{ + int n,i; + LIST scan,generals; + TERM term; + LITERAL litres; + + n = clause_Length(clause); + for (i = 0; i < n; i++) { + term = clause_GetLiteralTerm(clause,i); + generals = st_GetGen(cont_LeftContext(), stindex, term); + for (scan = generals; !list_Empty(scan); scan = list_Cdr(scan)) { + litres = (LITERAL) list_Car(scan); + if (litres == clause_GetLiteral(clause_LiteralOwningClause(litres),0) && + clause_Length(clause) >= clause_Length(clause_LiteralOwningClause(litres)) && + clause_Weight(clause) >= clause_Weight(clause_LiteralOwningClause(litres)) && + subs_Idc(clause_LiteralOwningClause(litres),clause)) { + list_Delete(generals); + return TRUE; + } + } + list_Delete(generals); + } + return FALSE; +} + + diff --git a/test/spass/resolution.h b/test/spass/resolution.h new file mode 100644 index 0000000000000000000000000000000000000000..1b29779091a50db01d7782769bf60501fbe3883e --- /dev/null +++ b/test/spass/resolution.h @@ -0,0 +1,73 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * RESOLUTION * */ +/* * * */ +/* * $Module: RESOLUTION * */ +/* * * */ +/* * Copyright (C) 1996, 1998, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/* $RCSfile$ */ + +#ifndef _RESOLUTION_ +#define _RESOLUTION_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "misc.h" +#include "unify.h" +#include "symbol.h" +#include "foldfg.h" +#include "st.h" +#include "subsumption.h" +#include "condensing.h" + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + + +void res_InsertClauseIndex(CLAUSE, st_INDEX); /* used by cnf */ +void res_DeleteClauseIndex(CLAUSE, st_INDEX); /* used by cnf */ +CLAUSE res_SelectLightestClause(LIST); /* used by cnf */ +BOOL res_BackSubWithLength(CLAUSE, st_INDEX); /* used by cnf */ +BOOL res_HasTautology(CLAUSE); /* used by cnf */ + +#endif diff --git a/test/spass/rpos.c b/test/spass/rpos.c new file mode 100644 index 0000000000000000000000000000000000000000..edd1b8b702063de9db607560b407c7f4a8baf3d2 --- /dev/null +++ b/test/spass/rpos.c @@ -0,0 +1,521 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * RECURSIVE PATH ORDERING WITH STATUS * */ +/* * * */ +/* * $Module: RPOS * */ +/* * * */ +/* * Copyright (C) 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "rpos.h" + + +/**************************************************************/ +/* Top Down Version */ +/**************************************************************/ + +static LIST rpos_MultisetDifference(TERM T1, TERM T2) +/************************************************************** + INPUT: Two terms. + RETURNS: The multiset difference between the arguments + of both terms with respect to rpos_Equal. +***************************************************************/ +{ + LIST result; + + result = list_Copy(term_ArgumentList(T1)); + result = list_NMultisetDifference(result, term_ArgumentList(T2), + (BOOL (*)(POINTER,POINTER)) rpos_Equal); + return result; +} + + +static ord_RESULT rpos_MulGreaterEqual(TERM T1, TERM T2) +/************************************************************** + INPUT: Two terms with equal top symbols and multiset status. + RETURNS: ord_GREATER_THAN if <T1> is greater than <T2>, + ord_EQUAL if both terms are equal and + ord_UNCOMPARABLE otherwise. +***************************************************************/ +{ + LIST l1, l2; + + l1 = rpos_MultisetDifference(T1, T2); + if (list_Empty(l1)) + /* If |M| = |N| and M-N = {} then N-M = {} */ + return ord_Equal(); /* Terms are equal */ + else { + LIST scan; + BOOL greater; + + l2 = rpos_MultisetDifference(T2, T1); + + for (greater = TRUE; !list_Empty(l2) && greater; l2 = list_Pop(l2)) { + for (scan = l1, greater = FALSE; !list_Empty(scan) && !greater; scan = list_Cdr(scan)) + greater = rpos_Greater(list_Car(scan), list_Car(l2)); + } + list_Delete(l1); /* l2 was freed in the outer for loop */ + if (greater) + return ord_GreaterThan(); + else + return ord_Uncomparable(); + } +} + +static ord_RESULT rpos_LexGreaterEqual(TERM T1, TERM T2) +/************************************************************** + INPUT: Two terms with equal top symbols and lexicographic status. + RETURNS: ord_GREATER_THAN if <T1> is greater than <T2>, + ord_EQUAL if both terms are equal and + ord_UNCOMPARABLE otherwise. +***************************************************************/ +{ + ord_RESULT result; + LIST l1, l2, scan1, scan2; + + if (symbol_HasProperty(term_TopSymbol(T1), ORDRIGHT)) { + l1 = list_Reverse(term_ArgumentList(T1)); /* Create new lists */ + l2 = list_Reverse(term_ArgumentList(T2)); + } else { + l1 = term_ArgumentList(T1); + l2 = term_ArgumentList(T2); + } + /* First ignore equal arguments */ + result = ord_Equal(); + for (scan1 = l1, scan2 = l2; !list_Empty(scan1); + scan1 = list_Cdr(scan1), scan2 = list_Cdr(scan2)) { + result = rpos_GreaterEqual(list_Car(scan1), list_Car(scan2)); + if (!ord_IsEqual(result)) + break; + } + + if (ord_IsEqual(result)) /* All arguments are equal, so the terms */ + /* empty */; /* are equal with respect to RPOS */ + else if (ord_IsGreaterThan(result)) { + /* Check if T1 > each remaining argument of T2 */ + for (scan2 = list_Cdr(scan2); !list_Empty(scan2) && rpos_Greater(T1, list_Car(scan2)); + scan2 = list_Cdr(scan2)); /* Empty body */ + if (list_Empty(scan2)) + result = ord_GreaterThan(); + else + result = ord_Uncomparable(); + } + else { + /* Argument of T1 was not >= argument of T2. */ + + /* Try to find an argument of T1 that is >= T2 */ + for (scan1 = list_Cdr(scan1), result = ord_Uncomparable(); + !list_Empty(scan1) && !ord_IsGreaterThan(result); + scan1 = list_Cdr(scan1)) { + if (!ord_IsUncomparable(rpos_GreaterEqual(list_Car(scan1), T2))) + result = ord_GreaterThan(); + } + } + + if (symbol_HasProperty(term_TopSymbol(T1), ORDRIGHT)) { + list_Delete(l1); /* Delete the lists create above */ + list_Delete(l2); + } + return result; +} + + +BOOL rpos_Equal(TERM T1, TERM T2) +/************************************************************** + INPUT: Two terms. + RETURNS: TRUE, if <T1> is equal to <T2> and + FALSE otherwise. +***************************************************************/ +{ + LIST l1, l2; + + if (!term_EqualTopSymbols(T1, T2)) + return FALSE; + else if (!term_IsComplex(T1)) /* Equal variable or constant */ + return TRUE; + else { + if (symbol_HasProperty(term_TopSymbol(T1), ORDMUL)) { /* MUL case */ + l1 = rpos_MultisetDifference(T1, T2); + if (list_Empty(l1)) + return TRUE; + else { + list_Delete(l1); + return FALSE; + } + } else { /* LEX case */ + for (l1 = term_ArgumentList(T1), l2 = term_ArgumentList(T2); + !list_Empty(l1) && rpos_Equal(list_Car(l1), list_Car(l2)); + l1 = list_Cdr(l1), l2 = list_Cdr(l2)) + /* empty */; + return list_Empty(l1); /* All arguments were equal */ + } + } +} + + +ord_RESULT rpos_GreaterEqual(TERM T1, TERM T2) +/************************************************************** + INPUT: Two terms. + RETURNS: ord_GREATER_THAN if <T1> is greater than <T2> + ord_EQUAL if both terms are equal + ord_UNCOMPARABLE otherwise. + CAUTION: The precedence from the order module is used to determine + the precedence of symbols! +***************************************************************/ +{ + LIST scan; + + if (term_IsVariable(T1)) { + if (term_EqualTopSymbols(T1, T2)) + return ord_Equal(); /* T2 is the same variable */ + else + /* A variable can't be greater than another term */ + return ord_Uncomparable(); + } else if (term_IsVariable(T2)) { /* T1 isn't a variable */ + if (term_ContainsSymbol(T1, term_TopSymbol(T2))) + return ord_GreaterThan(); + else + return ord_Uncomparable(); + } else if (term_EqualTopSymbols(T1, T2)) { + if (symbol_HasProperty(term_TopSymbol(T1), ORDMUL)) + return rpos_MulGreaterEqual(T1, T2); + else + return rpos_LexGreaterEqual(T1, T2); + } else { + if (symbol_PrecedenceGreater(ord_PRECEDENCE, term_TopSymbol(T1), + term_TopSymbol(T2))) { + /* Different top symbols, symbol of T1 > symbol of T2. */ + /* Try if T1 > each argument of T2. */ + for (scan = term_ArgumentList(T2); !list_Empty(scan); scan = list_Cdr(scan)) + if (!rpos_Greater(T1, list_Car(scan))) + return ord_Uncomparable(); + return ord_GreaterThan(); + } else { + /* Try to find an argument of T1 that is >= T2 */ + for (scan = term_ArgumentList(T1); !list_Empty(scan); scan = list_Cdr(scan)) + if (!ord_IsUncomparable(rpos_GreaterEqual(list_Car(scan), T2))) + return ord_GreaterThan(); /* Argument of T1 >= T2 */ + return ord_Uncomparable(); + } + } +} + +ord_RESULT rpos_Compare(TERM T1, TERM T2) +/************************************************************** + INPUT: Two terms. + RETURNS: The relation between the two terms with respect to the + RPOS ordering: + ord_GREATER_THAN if <T1> is greater than <T2>, + ord_EQUAL if both terms are equal, + ord_SMALLER_THAN if <T2> is greater than <T1> and + ord_UNCOMPARABLE otherwise. + CAUTION: The precedence from the order module is used to determine + the precedence of symbols! +***************************************************************/ +{ + ord_RESULT result; + + result = rpos_GreaterEqual(T1, T2); + if (!ord_IsUncomparable(result)) + return result; + else if (rpos_Greater(T2, T1)) + return ord_SmallerThan(); + else + return ord_UNCOMPARABLE; +} + +/**************************************************************/ +/* Term comparison with respect to bindings */ +/**************************************************************/ + +static LIST rpos_ContMultisetDifference(CONTEXT C1, TERM T1, CONTEXT C2, TERM T2) +/************************************************************** + INPUT: Two contexts and two terms. + RETURNS: The multiset difference between the arguments + of both terms with respect to rpos_ContEqual. + EFFECT: Variable bindings are considered. +***************************************************************/ +{ + LIST result, scan1, scan2; + + /* Don't apply bindings at top level, since that happened */ + /* in rpos_ContGreaterEqual */ + + /* We can't use list_NMultisetDifference, since that function */ + /* expects an equality functions for terms that takes two terms */ + /* as arguments. We also need the two contexts resolve variable */ + /* bindings. */ + result = list_Copy(term_ArgumentList(T1)); + for (scan2 = term_ArgumentList(T2); !list_Empty(scan2); + scan2 = list_Cdr(scan2)) { + /* Delete at most one occurrence of the */ + /* current element of list2 from list1 */ + for (scan1 = result; !list_Empty(scan1); scan1 = list_Cdr(scan1)) { + if (list_Car(scan1) != NULL && + rpos_ContEqual(C1, list_Car(scan1), C2, list_Car(scan2))) { + /* arg of list1 wasn't deleted earlier and terms are equal */ + list_Rplaca(scan1, NULL); /* Mark argument of T1 as deleted */ + break; + } + } + } + return list_PointerDeleteElement(result, NULL); /* Delete all marked terms */ +} + + +static ord_RESULT rpos_ContMulGreaterEqual(CONTEXT C1, TERM T1, + CONTEXT C2, TERM T2) +/************************************************************** + INPUT: Two contexts and two terms with equal top symbols + and multiset status. + RETURNS: ord_GREATER_THAN if <T1> is greater than <T2>, + ord_EQUAL if both terms are equal and + ord_UNCOMPARABLE otherwise. + EFFECT: Variable bindings are considered. +***************************************************************/ +{ + LIST l1, l2; + + /* Don't apply bindings at top level, since that happened */ + /* in rpos_ContGreaterEqual. */ + + l1 = rpos_ContMultisetDifference(C1, T1, C2, T2); + if (list_Empty(l1)) + /* If |M| = |N| and M-N = {} then N-M = {} */ + return ord_Equal(); /* Terms are equal */ + else { + LIST scan; + BOOL greater; + + l2 = rpos_ContMultisetDifference(C2, T2, C1, T1); + + for (greater = TRUE; !list_Empty(l2) && greater; l2 = list_Pop(l2)) { + for (scan = l1, greater = FALSE; !list_Empty(scan) && !greater; + scan = list_Cdr(scan)) + greater = rpos_ContGreater(C1, list_Car(scan), C2, list_Car(l2)); + } + list_Delete(l1); /* l2 was freed in the outer for loop */ + if (greater) + return ord_GreaterThan(); + else + return ord_Uncomparable(); + } +} + +static ord_RESULT rpos_ContLexGreaterEqual(CONTEXT C1, TERM T1, + CONTEXT C2, TERM T2) +/************************************************************** + INPUT: Two contexts and two terms with equal top symbols + and lexicographic status. + RETURNS: ord_GREATER_THAN if <T1> is greater than <T2>, + ord_EQUAL if both terms are equal and + ord_UNCOMPARABLE otherwise. + EFFECT: Variable bindings are considered. +***************************************************************/ +{ + ord_RESULT result; + LIST l1, l2, scan1, scan2; + + /* Don't apply bindings at top level, since that happened */ + /* in rpos_ContGreaterEqual */ + + if (symbol_HasProperty(term_TopSymbol(T1), ORDRIGHT)) { + l1 = list_Reverse(term_ArgumentList(T1)); /* Create new lists */ + l2 = list_Reverse(term_ArgumentList(T2)); + } else { + l1 = term_ArgumentList(T1); + l2 = term_ArgumentList(T2); + } + /* First ignore equal arguments */ + result = ord_Equal(); + for (scan1 = l1, scan2 = l2; !list_Empty(scan1); + scan1 = list_Cdr(scan1), scan2 = list_Cdr(scan2)) { + result = rpos_ContGreaterEqual(C1, list_Car(scan1), C2, list_Car(scan2)); + if (!ord_IsEqual(result)) + break; + } + + if (ord_IsEqual(result)) /* All arguments are equal, so the terms */ + /* empty */; /* are equal with respect to RPOS */ + else if (ord_IsGreaterThan(result)) { + /* Check if T1 > each remaining argument of T2 */ + for (scan2 = list_Cdr(scan2); + !list_Empty(scan2) && rpos_ContGreater(C1, T1, C2, list_Car(scan2)); + scan2 = list_Cdr(scan2)); /* Empty body */ + if (list_Empty(scan2)) + result = ord_GreaterThan(); + else + result = ord_Uncomparable(); + } + else { + /* Argument of T1 was not >= argument of T2. */ + /* Try to find an argument of T1 that is >= T2 */ + for (scan1 = list_Cdr(scan1), result = ord_Uncomparable(); + !list_Empty(scan1) && !ord_IsGreaterThan(result); + scan1 = list_Cdr(scan1)) { + if (!ord_IsUncomparable(rpos_ContGreaterEqual(C1,list_Car(scan1),C2,T2))) + result = ord_GreaterThan(); + } + } + + if (symbol_HasProperty(term_TopSymbol(T1), ORDRIGHT)) { + list_Delete(l1); /* Delete the lists create above */ + list_Delete(l2); + } + return result; +} + + +BOOL rpos_ContEqual(CONTEXT C1, TERM T1, CONTEXT C2, TERM T2) +/************************************************************** + INPUT: Two contexts and two terms. + RETURNS: TRUE, if <T1> is equal to <T2> and + FALSE otherwise. + EFFECT: Variable bindings are considered. +***************************************************************/ +{ + LIST l1, l2; + + T1 = cont_Deref(&C1, T1); + T2 = cont_Deref(&C2, T2); + + if (!term_EqualTopSymbols(T1, T2)) + return FALSE; + else if (!term_IsComplex(T1)) + return TRUE; + else { + if (symbol_HasProperty(term_TopSymbol(T1), ORDMUL)) { + l1 = rpos_ContMultisetDifference(C1, T1, C2, T2); + if (list_Empty(l1)) + return TRUE; + else { + list_Delete(l1); + return FALSE; + } + } else { /* LEX case */ + for (l1 = term_ArgumentList(T1), l2 = term_ArgumentList(T2); + !list_Empty(l1) && rpos_ContEqual(C1,list_Car(l1),C2,list_Car(l2)); + l1 = list_Cdr(l1), l2 = list_Cdr(l2)); /* empty body */ + return list_Empty(l1); /* All arguments were equal */ + } + } +} + + +ord_RESULT rpos_ContGreaterEqual(CONTEXT C1, TERM T1, CONTEXT C2, TERM T2) +/************************************************************** + INPUT: Two contexts and two terms. + RETURNS: ord_GREATER_THAN if <T1> is greater than <T2> + ord_EQUAL if both terms are equal + ord_UNCOMPARABLE otherwise. + EFFECT: Variable bindings are considered. + CAUTION: The precedence from the order module is used to determine + the precedence of symbols! +***************************************************************/ +{ + LIST scan; + + T1 = cont_Deref(&C1, T1); + T2 = cont_Deref(&C2, T2); + + if (term_IsVariable(T1)) { + if (term_EqualTopSymbols(T1, T2)) + return ord_Equal(); /* T2 is the same variable */ + else + /* A variable can't be greater than another term */ + return ord_Uncomparable(); + } else if (term_IsVariable(T2)) { /* T1 isn't a variable */ + if (cont_TermContainsSymbol(C1, T1, term_TopSymbol(T2))) + return ord_GreaterThan(); + else + return ord_Uncomparable(); + } else if (term_EqualTopSymbols(T1, T2)) { + if (symbol_HasProperty(term_TopSymbol(T1), ORDMUL)) + return rpos_ContMulGreaterEqual(C1, T1, C2, T2); + else + return rpos_ContLexGreaterEqual(C1, T1, C2, T2); + } else { + if (symbol_PrecedenceGreater(ord_PRECEDENCE, term_TopSymbol(T1), + term_TopSymbol(T2))) { + /* Different top symbols, symbol of T1 > symbol of T2. */ + /* Try if T1 > each argument of T2. */ + for (scan = term_ArgumentList(T2); !list_Empty(scan); scan = list_Cdr(scan)) + if (!rpos_ContGreater(C1, T1, C2, list_Car(scan))) + return ord_Uncomparable(); + return ord_GreaterThan(); + } else { + /* Try to find an argument of T1 that is >= T2 */ + for (scan = term_ArgumentList(T1); !list_Empty(scan); scan = list_Cdr(scan)) + if (!ord_IsUncomparable(rpos_ContGreaterEqual(C1,list_Car(scan),C2,T2))) + return ord_GreaterThan(); /* Argument of T1 >= T2 */ + return ord_Uncomparable(); + } + } +} + +ord_RESULT rpos_ContCompare(CONTEXT C1, TERM T1, CONTEXT C2, TERM T2) +/************************************************************** + INPUT: Two contexts and two terms. + RETURNS: The relation between the two terms with respect to the + RPOS ordering: + ord_GREATER_THAN if <T1> is greater than <T2>, + ord_EQUAL if both terms are equal, + ord_SMALLER_THAN if <T2> is greater than <T1> and + ord_UNCOMPARABLE otherwise. + EFFECT: Variable bindings are considered. + CAUTION: The precedence from the order module is used to determine + the precedence of symbols! +***************************************************************/ +{ + ord_RESULT result; + + T1 = cont_Deref(&C1, T1); + T2 = cont_Deref(&C2, T2); + + result = rpos_ContGreaterEqual(C1, T1, C2, T2); + if (!ord_IsUncomparable(result)) + return result; + else if (rpos_ContGreater(C2, T2, C1, T1)) + return ord_SmallerThan(); + else + return ord_UNCOMPARABLE; +} + diff --git a/test/spass/rpos.h b/test/spass/rpos.h new file mode 100644 index 0000000000000000000000000000000000000000..6cef9e86998777595f2c24ca724d9a9c2a535057 --- /dev/null +++ b/test/spass/rpos.h @@ -0,0 +1,82 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * RECURSIVE PATH ORDERING WITH STATUS * */ +/* * * */ +/* * $Module: RPOS * */ +/* * * */ +/* * Copyright (C) 1997, 1998 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _RPOS_ +#define _RPOS_ + +#include "misc.h" +#include "term.h" +#include "order.h" +#include "context.h" + +/**************************************************************/ +/* Function Prototypes */ +/**************************************************************/ + +BOOL rpos_Equal(TERM, TERM); +ord_RESULT rpos_GreaterEqual(TERM, TERM); +ord_RESULT rpos_Compare(TERM, TERM); + +BOOL rpos_ContEqual(CONTEXT, TERM, CONTEXT, TERM); +ord_RESULT rpos_ContGreaterEqual(CONTEXT, TERM, CONTEXT, TERM); +ord_RESULT rpos_ContCompare(CONTEXT, TERM, CONTEXT, TERM); + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +static __inline__ BOOL rpos_Greater(TERM T1, TERM T2) +{ + return ord_IsGreaterThan(rpos_GreaterEqual(T1, T2)); +} + +static __inline__ BOOL rpos_ContGreater(CONTEXT C1, TERM T1, + CONTEXT C2, TERM T2) +{ + return ord_IsGreaterThan(rpos_ContGreaterEqual(C1, T1, C2, T2)); +} + +#endif diff --git a/test/spass/rules-inf.c b/test/spass/rules-inf.c new file mode 100644 index 0000000000000000000000000000000000000000..38bbaa6ba469c92757ae02c326acf7b7daac3a21 --- /dev/null +++ b/test/spass/rules-inf.c @@ -0,0 +1,4281 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INFERENCE RULES * */ +/* * * */ +/* * $Module: INFRULES * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "rules-inf.h" + + +/**************************************************************/ +/* Some auxiliary functions for testing postconditions */ +/**************************************************************/ + +static BOOL inf_LitMax(CLAUSE Clause, int i, int j, SUBST Subst, BOOL Strict, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, the index of a maximal literal, another + literal index, a substitution, a boolean flag, a + flag store and a precedence. + RETURNS: If <Strict>=FALSE the function returns TRUE iff the + literal at index <i> is still maximal in the + instantiated clause. + If <Strict>=TRUE the function returns TRUE iff the + literal is STRICTLY maximal in the instantiated + clause. The literal at index j is omitted at literal + comparison. + However, setting j to a negative number ensures that + all literals are compared with the literal at + index <i>. + CAUTION: DON'T call this function with a clause with selected + literals! +***************************************************************/ +{ + TERM Max, LitTerm; + LITERAL Lit; + ord_RESULT Compare; + int k, l; + +#ifdef CHECK + if (!clause_LiteralIsMaximal(clause_GetLiteral(Clause, i)) || + (Strict && + !clause_LiteralGetFlag(clause_GetLiteral(Clause, i), STRICTMAXIMAL))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_LitMax: Literal %d isn't %smaximal.", + i, Strict ? "strictly " : ""); + misc_FinishErrorReport(); + } + if (i < clause_FirstAntecedentLitIndex(Clause) || + i > clause_LastSuccedentLitIndex(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_LitMax: Literal index %d is out of range.", i); + misc_FinishErrorReport(); + } + /* If literal <i> is selected, there's no need to check for maximality, */ + /* if <i> isn't selected, but there're other literals selected, */ + /* inferences with literal <i> are forbidden. */ + if (clause_GetFlag(Clause, CLAUSESELECT)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_LitMax: There're selected literals.", i); + misc_FinishErrorReport(); + } +#endif + + Lit = clause_GetLiteral(Clause, i); + /* Check necessary condition */ + if (!clause_LiteralIsMaximal(Lit) || + (Strict && !clause_LiteralGetFlag(Lit, STRICTMAXIMAL))) + return FALSE; + /* Only antecedent and succedent literals are compared, so if there's */ + /* only one such literal, it's maximal. */ + /* If the substitution is empty, the necessary condition tested above */ + /* is sufficient, too. */ + if ((clause_NumOfAnteLits(Clause) + clause_NumOfSuccLits(Clause) == 1) || + subst_Empty(Subst)) + return TRUE; + + l = clause_LastSuccedentLitIndex(Clause); + Max = subst_Apply(Subst,term_Copy(clause_GetLiteralTerm(Clause,i))); + + for (k = clause_FirstAntecedentLitIndex(Clause); k <= l; k++) + if (k != i && k != j && + clause_LiteralIsMaximal(clause_GetLiteral(Clause, k))) { + /* Only compare with maximal literals, since for every non-maximal */ + /* literal, there's at least one maximal literal, that is bigger. */ + LitTerm = subst_Apply(Subst,term_Copy(clause_GetLiteralTerm(Clause,k))); + Compare = ord_LiteralCompare(Max, + clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause,i)), + LitTerm, + clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause,k)), + TRUE, Flags, Precedence); + if (Compare == ord_SmallerThan() || (Strict && Compare == ord_Equal())) { + term_Delete(Max); + term_Delete(LitTerm); + return FALSE; + } + term_Delete(LitTerm); + } + term_Delete(Max); + + return TRUE; +} + + +static BOOL inf_LiteralsMax(CLAUSE Clause, int i, SUBST Subst, + CLAUSE PartnerClause, int j, SUBST PartnerSubst, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: The parents of a resolution inference, the respective + literal indices and substitutions, a flag store and + a precedence. + RETURNS: TRUE iff the positive/negative literals are still + strictly maximal/maximal in the instantiated clause. + If a negative literal is selected, no comparison + is made. +***************************************************************/ +{ +#ifdef CHECK + if ((clause_GetFlag(Clause, CLAUSESELECT) && + !clause_LiteralGetFlag(clause_GetLiteral(Clause,i),LITSELECT)) || + (clause_GetFlag(PartnerClause, CLAUSESELECT) && + !clause_LiteralGetFlag(clause_GetLiteral(PartnerClause,j),LITSELECT))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_LiteralsMax: Another literal is selected."); + misc_FinishErrorReport(); + } +#endif + + if (!clause_GetFlag(Clause, CLAUSESELECT) && + !inf_LitMax(Clause,i,-1,Subst, + i>clause_LastAntecedentLitIndex(Clause),Flags, Precedence)) + return FALSE; + if (!clause_GetFlag(PartnerClause, CLAUSESELECT) && + !inf_LitMax(PartnerClause,j,-1,PartnerSubst, + j>clause_LastAntecedentLitIndex(PartnerClause), Flags, Precedence)) + return FALSE; + + return TRUE; +} + + +static BOOL inf_LitMaxWith2Subst(CLAUSE Clause, int i, int j, SUBST Subst2, + SUBST Subst1, BOOL Strict, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, the index of a maximal literal, another + literal index, two substitutions, a boolean flag, + a flag store and a precedence. + RETURNS: In contrast to the function inf_LitMax this function + compares the literals with respect to the composition + of the two substitutions Subst2 ° Subst1. + If <Strict>=FALSE the function returns TRUE iff the + literal at index <i> is still maximal in the + instantiated clause. + If <Strict>=TRUE the function returns TRUE iff the + literal is STRICTLY maximal in the instantiated + clause. + The literal at index j is omitted at literal + comparison. + However, setting j to a negative number ensures that + all literals are compared with the literal at + index <i>. + CAUTION: DON'T call this function with a clause with selected + literals! +***************************************************************/ +{ + TERM Max, LitTerm; + LITERAL Lit; + ord_RESULT Compare; + int k, l; + +#ifdef CHECK + if (!clause_LiteralIsMaximal(clause_GetLiteral(Clause, i)) || + (Strict && + !clause_LiteralGetFlag(clause_GetLiteral(Clause, i), STRICTMAXIMAL))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_LitMaxWith2Subst: Literal %d isn't %smaximal.", + i, Strict ? "strictly " : ""); + misc_FinishErrorReport(); + } + if (i < clause_FirstAntecedentLitIndex(Clause) || + i > clause_LastSuccedentLitIndex(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_LitMaxWith2Subst: Literal index %d is out of range.", i); + misc_FinishErrorReport(); + } + /* If literal <i> is selected, there's no need to check for maximality, */ + /* if <i> isn't selected, but there're other literals selected, */ + /* inferences with literal <i> are forbidden. */ + if (clause_GetFlag(Clause, CLAUSESELECT)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_LitMaxWith2Subst: There're selected literals.", i); + misc_FinishErrorReport(); + } +#endif + + Lit = clause_GetLiteral(Clause, i); + /* Check necessary condition */ + if (!clause_LiteralIsMaximal(Lit) || + (Strict && !clause_LiteralGetFlag(Lit, STRICTMAXIMAL))) + return FALSE; + /* Only antecedent and succedent literals are compared, so if there's */ + /* only one such literal, it's maximal. */ + /* If both substitutions are empty, the necessary condition tested above */ + /* is sufficient, too. */ + if ((clause_NumOfAnteLits(Clause) + clause_NumOfSuccLits(Clause) == 1) || + (subst_Empty(Subst1) && subst_Empty(Subst2))) + return TRUE; + + l = clause_LastSuccedentLitIndex(Clause); + Max = subst_Apply(Subst1, term_Copy(clause_GetLiteralTerm(Clause,i))); + Max = subst_Apply(Subst2, Max); + + for (k = clause_FirstAntecedentLitIndex(Clause); k <= l; k++) + if (k != i && k != j && + clause_LiteralIsMaximal(clause_GetLiteral(Clause, k))) { + /* Only compare with maximal literals, since for every non-maximal */ + /* literal, there's at least one maximal literal, that is bigger. */ + LitTerm = subst_Apply(Subst1,term_Copy(clause_GetLiteralTerm(Clause,k))); + LitTerm = subst_Apply(Subst2, LitTerm); + Compare = ord_LiteralCompare(Max, + clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause,i)), + LitTerm, + clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause,k)), + TRUE, Flags, Precedence); + if (Compare == ord_SmallerThan() || (Strict && Compare == ord_Equal())) { + term_Delete(Max); + term_Delete(LitTerm); + return FALSE; + } + term_Delete(LitTerm); + } + term_Delete(Max); + + return TRUE; +} + + +static BOOL inf_LiteralsMaxWith2Subst(CLAUSE Clause, int i, CLAUSE PartnerClause, + int j, SUBST Subst2, SUBST Subst1, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: The parents of a resolution inference, the + respective literal indices and substitutions, a + flag store and a precedence. + RETURNS: In contrast to the function inf_LiteralsMax + the composition Subst2 ° Subst1 is applied to both + clauses. + The function returns TRUE iff the positive/negative + literals are still strictly maximal/maximal in the + instantiated clause. + If a negative literal is selected, no comparison + is made. +***************************************************************/ +{ +#ifdef CHECK + if ((clause_GetFlag(Clause, CLAUSESELECT) && + !clause_LiteralGetFlag(clause_GetLiteral(Clause,i),LITSELECT)) || + (clause_GetFlag(PartnerClause, CLAUSESELECT) && + !clause_LiteralGetFlag(clause_GetLiteral(PartnerClause,j),LITSELECT))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_LiteralsMaxWith2Subst: Another literal is selected."); + misc_FinishErrorReport(); + } +#endif + + if (!clause_GetFlag(Clause, CLAUSESELECT) && + !inf_LitMaxWith2Subst(Clause, i, -1, Subst2, Subst1, + i>clause_LastAntecedentLitIndex(Clause), Flags, Precedence)) + return FALSE; + if (!clause_GetFlag(PartnerClause, CLAUSESELECT) && + !inf_LitMaxWith2Subst(PartnerClause, j, -1, Subst2, Subst1, + j>clause_LastAntecedentLitIndex(PartnerClause), Flags, Precedence)) + return FALSE; + + return TRUE; +} + + +/**************************************************************/ +/* Inference rules */ +/**************************************************************/ + +LIST inf_EqualityResolution(CLAUSE GivenClause, BOOL Ordered, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause and a flag determining whether ordering + constraints apply. + For <Ordered>=TRUE the function makes Equality Resolution + inferences, for <Ordered>=FALSE Reflexivity Resolution + inferences are made. + A flag store. + A precedence. + RETURNS: A list of clauses inferred from the GivenClause by + Equality/Reflexivity Resolution. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result; + LITERAL ActLit; + int i, last; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_EqualityResolution: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (clause_HasEmptyAntecedent(GivenClause) || + !clause_HasSolvedConstraint(GivenClause)) { + return list_Nil(); + } + + Result = list_Nil(); + last = clause_LastAntecedentLitIndex(GivenClause); + + for (i = clause_FirstAntecedentLitIndex(GivenClause); i <= last; i++) { + ActLit = clause_GetLiteral(GivenClause, i); + + if (clause_LiteralIsEquality(ActLit) && + (clause_LiteralGetFlag(ActLit,LITSELECT) || + (!clause_GetFlag(GivenClause,CLAUSESELECT) && + (!Ordered || clause_LiteralIsMaximal(ActLit))))) { + TERM Atom; + + Atom = clause_GetLiteralAtom(GivenClause, i); + + cont_Check(); + if (unify_UnifyCom(cont_LeftContext(), + term_FirstArgument(Atom), + term_SecondArgument(Atom))) { + SUBST mgu; + CLAUSE NewClause; + int j, k, bound; + + subst_ExtractUnifierCom(cont_LeftContext(), &mgu); + /* Check postcondition */ + if (clause_LiteralGetFlag(ActLit,LITSELECT) || + !Ordered || inf_LitMax(GivenClause, i, -1, mgu, + FALSE, Flags, Precedence)) { + + NewClause = clause_CreateBody(clause_Length(GivenClause) - 1); + clause_SetNumOfConsLits(NewClause, clause_NumOfConsLits(GivenClause)); + clause_SetNumOfAnteLits(NewClause, + (clause_NumOfAnteLits(GivenClause) - 1)); + clause_SetNumOfSuccLits(NewClause, clause_NumOfSuccLits(GivenClause)); + + bound = clause_LastLitIndex(GivenClause); + /* j iterates over the given clause, k iterates over the new one */ + for (j = k = clause_FirstLitIndex(); j <= bound; j++) { + if (j != i) { + clause_SetLiteral(NewClause, k, + clause_LiteralCreate(subst_Apply(mgu, + term_Copy(clause_GetLiteralTerm(GivenClause,j))),NewClause)); + k++; + } + } + clause_SetDataFromFather(NewClause, GivenClause, i, Flags, Precedence); + clause_SetFromEqualityResolution(NewClause); + + Result = list_Cons(NewClause, Result); + } + subst_Delete(mgu); + } + cont_Reset(); + } /* end of if 'ActLit is maximal'. */ + } /*end of for 'all literals'. */ + return(Result); +} + +static CLAUSE inf_ApplyEqualityFactoring(CLAUSE Clause, TERM Left, TERM Right, + int i, int j, SUBST Subst, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, two terms, two indices in the clause, + a substitution, a flag store and a precedence. + RETURNS: A new clause, where <Left>=<Right> is added as antecedent atom, + the <i>th literal is deleted, the <j>th kept and + <Subst> is applied to a copy of <clause>. +***************************************************************/ +{ + CLAUSE NewClause; + TERM Atom; + int k,c,a,s; + + NewClause = clause_CreateBody(clause_Length(Clause)); + + c = clause_LastConstraintLitIndex(Clause); + clause_SetNumOfConsLits(NewClause, clause_NumOfConsLits(Clause)); + a = clause_LastAntecedentLitIndex(Clause); + clause_SetNumOfAnteLits(NewClause, clause_NumOfAnteLits(Clause) + 1); + s = clause_LastSuccedentLitIndex(Clause); + clause_SetNumOfSuccLits(NewClause, clause_NumOfSuccLits(Clause) - 1); + + for (k = clause_FirstLitIndex(); k <= c; k++) { + clause_SetLiteral(NewClause, k, + clause_LiteralCreate(subst_Apply(Subst, + term_Copy(clause_GetLiteralTerm(Clause, k))),NewClause)); + } + + for ( ; k <= a; k++) { + clause_SetLiteral(NewClause, k, + clause_LiteralCreate(subst_Apply(Subst, + term_Copy(clause_GetLiteralTerm(Clause, k))),NewClause)); + } + + Atom = term_Create(fol_Equality(), + list_Cons(term_Copy(Left),list_List(term_Copy(Right)))); + + clause_SetLiteral(NewClause, k, clause_LiteralCreate( + term_Create(fol_Not(), list_List(subst_Apply(Subst,Atom))), NewClause)); + + a = 1; /* Shift */ + + for ( ; k <= s; k++) { + if (k == i) + a = 0; + else { + clause_SetLiteral(NewClause, (k + a), + clause_LiteralCreate(subst_Apply(Subst, + term_Copy(clause_GetLiteralTerm(Clause, k))),NewClause)); + } + } + + clause_AddParentClause(NewClause, clause_Number(Clause)); + clause_AddParentLiteral(NewClause, j); + clause_SetDataFromFather(NewClause, Clause, i, Flags, Precedence); + + clause_SetFromEqualityFactoring(NewClause); + + return NewClause; +} + + +static BOOL inf_EqualityFactoringApplicable(CLAUSE Clause, int i, TERM Left, + TERM Right, SUBST Subst, + FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause <Clause>, the index <i> of a maximal + equality literal in <Clause> <j>, <Left> and + <Right> are the left and right side of the literal, + where <Right> is not greater than <Left> wrt the + ordering, a unifier <Subst>, a flag store and a + precedence. + RETURNS: TRUE iff the literal at index <i> is strictly + maximal in the instantiated clause and <Right> is + not greater than or equal to <Left> after + application of the substitution. + Otherwise, the function returns FALSE. +***************************************************************/ +{ + ord_RESULT Help; + + /* Literal oriented? */ + if (!clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause, i))) { + TERM NLeft, NRight; + NLeft = subst_Apply(Subst, term_Copy(Left)); + NRight = subst_Apply(Subst, term_Copy(Right)); + if ((Help = ord_Compare(NLeft,NRight,Flags, Precedence)) == ord_SmallerThan() || + Help == ord_Equal()) { + term_Delete(NLeft); + term_Delete(NRight); + return FALSE; + } + term_Delete(NLeft); + term_Delete(NRight); + } + /* Literal maximal? */ + return inf_LitMax(Clause, i, -1, Subst, FALSE, Flags, Precedence); +} + + +LIST inf_EqualityFactoring(CLAUSE GivenClause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a flag store and a precedence. + RETURNS: A list of clauses derivable from 'GivenClause' by EF. +***************************************************************/ +{ + LIST Result; + LITERAL ActLit; + int i, j, last; + SUBST mgu; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_EqualityFactoring: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (clause_HasEmptySuccedent(GivenClause) || + clause_GetFlag(GivenClause, CLAUSESELECT) || + !clause_HasSolvedConstraint(GivenClause)) { + return list_Nil(); + } + + Result = list_Nil(); + + last = clause_LastSuccedentLitIndex(GivenClause); + + for (i = clause_FirstSuccedentLitIndex(GivenClause); i <= last; i++) { + + ActLit = clause_GetLiteral(GivenClause, i); + + if (clause_LiteralIsMaximal(ActLit) && + clause_LiteralIsEquality(ActLit)) { + TERM Atom, Left, Right; + LITERAL PartnerLit; + + Atom = clause_LiteralAtom(ActLit); + Left = term_FirstArgument(Atom); + Right = term_SecondArgument(Atom); + + for (j = clause_FirstSuccedentLitIndex(GivenClause); j <= last; j++) { + PartnerLit = clause_GetLiteral(GivenClause, j); + if (i != j && clause_LiteralIsEquality(PartnerLit)) { + /* i==j can be excluded since this inference would either generate */ + /* a copy of the given clause (if one side of the equality is */ + /* unified with itself), or generate a tautology (if different */ + /* sides of the equality are unified). */ + TERM PartnerAtom, PartnerLeft, PartnerRight; + + PartnerAtom = clause_LiteralAtom(PartnerLit); + PartnerLeft = term_FirstArgument(PartnerAtom); + PartnerRight = term_SecondArgument(PartnerAtom); + + /* try <Left> and <PartnerLeft> */ + cont_Check(); + if (unify_UnifyCom(cont_LeftContext(), Left, PartnerLeft)) { + subst_ExtractUnifierCom(cont_LeftContext(), &mgu); + if (inf_EqualityFactoringApplicable(GivenClause, i, Left, Right, + mgu, Flags, Precedence)) + Result = list_Cons(inf_ApplyEqualityFactoring(GivenClause,Right, + PartnerRight,i,j, + mgu,Flags, + Precedence), + Result); + subst_Delete(mgu); + } + cont_Reset(); + + /* try <Left> and <PartnerRight> */ + cont_Check(); + if (unify_UnifyCom(cont_LeftContext(), Left, PartnerRight)) { + subst_ExtractUnifierCom(cont_LeftContext(), &mgu); + + if (inf_EqualityFactoringApplicable(GivenClause, i, Left, Right, + mgu, Flags, Precedence)) + Result = list_Cons(inf_ApplyEqualityFactoring(GivenClause,Right, + PartnerLeft,i,j, + mgu,Flags, + Precedence), + Result); + subst_Delete(mgu); + } + cont_Reset(); + + if (!clause_LiteralIsOrientedEquality(ActLit)) { + /* try <Right> and <PartnerLeft> */ + cont_Check(); + if (unify_UnifyCom(cont_LeftContext(), Right, PartnerLeft)) { + subst_ExtractUnifierCom(cont_LeftContext(), &mgu); + + if (inf_EqualityFactoringApplicable(GivenClause, i, Right, Left, + mgu, Flags, Precedence)) + Result = list_Cons(inf_ApplyEqualityFactoring(GivenClause,Left, + PartnerRight,i,j, + mgu,Flags, + Precedence), + Result); + subst_Delete(mgu); + } + cont_Reset(); + + /* try <Right> and <PartnerRight> */ + cont_Check(); + if (unify_UnifyCom(cont_LeftContext(), Right, PartnerRight)) { + subst_ExtractUnifierCom(cont_LeftContext(), &mgu); + + if (inf_EqualityFactoringApplicable(GivenClause, i, Right, Left, + mgu, Flags, Precedence)) + Result = list_Cons(inf_ApplyEqualityFactoring(GivenClause,Left, + PartnerLeft,i,j, + mgu,Flags, + Precedence), + Result); + subst_Delete(mgu); + } + cont_Reset(); + } + } + } + } + } + return Result; +} + + +/* START of block with new term replacement */ + +static BOOL inf_NAllTermsRplac(TERM Term, TERM TestTerm, TERM RplacTerm, + SUBST Subst) +/************************************************************** + INPUT: Three terms, a substitution and an integer. + All occurrences of <TestTerm> in <Term> are replaced + by <RplacTerm>. The substitution <Subst> is applied to <Term>. + RETURNS: TRUE, if TestTerm was replaced by RplacTerm, + FALSE otherwise. + EFFECT: <Term> is destructively changed! +***************************************************************/ +{ + LIST ArgListNode; + BOOL Replaced; + int Bottom; + + Replaced = FALSE; + + /* check if whole term must be replaced */ + if (term_Equal(Term, TestTerm)) { + term_RplacTop(Term,term_TopSymbol(RplacTerm)); + ArgListNode = term_ArgumentList(Term); + term_RplacArgumentList(Term, term_CopyTermList(term_ArgumentList(RplacTerm))); + term_DeleteTermList(ArgListNode); + return TRUE; + } + + if (term_IsVariable(Term)) + subst_Apply(Subst, Term); + + /* if not, scan whole term. */ + if (!list_Empty(term_ArgumentList(Term))) { + + Bottom = stack_Bottom(); + stack_Push(term_ArgumentList(Term)); + + while (!stack_Empty(Bottom)) { + ArgListNode = stack_Top(); + Term = (TERM)list_Car(ArgListNode); + stack_RplacTop(list_Cdr(ArgListNode)); + + if (term_Equal(Term, TestTerm)) { + Replaced = TRUE; + list_Rplaca(ArgListNode, term_Copy(RplacTerm)); + term_Delete(Term); + } + else { + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + else if (term_IsVariable(Term)) + subst_Apply(Subst,Term); + } + + /* remove empty lists (corresponding to scanned terms) */ + while (!stack_Empty(Bottom) && list_Empty(stack_Top())) + stack_Pop(); + } + } + return Replaced; +} + + +static TERM inf_AllTermsRplac(TERM Term, TERM TestTerm, TERM RplacTerm, + SUBST Subst) +/************************************************************** + INPUT: Three terms, a substitution. + All occurrences of <TestTerm> in A COPY of <Term> are replaced + by <RplacTerm>. The substitution <Subst> is applied to + the copy of <Term>. If no occurrence is found, + NULL is returned. + This function is not destructive + like NAllTermRplac. + RETURNS: TRUE, if TestTerm was replaced by RplacTerm, + FALSE otherwise. +***************************************************************/ +{ + TERM ActTerm = term_Copy(Term); + + if (!inf_NAllTermsRplac(ActTerm,TestTerm, RplacTerm, Subst )) { + term_Delete(ActTerm); + ActTerm = NULL; + } + + return(ActTerm); +} + +static TERM inf_AllTermsSideRplacs(TERM Term, TERM TestTerm, TERM RplacTerm, + SUBST Subst, BOOL Right) +/************************************************************** + INPUT: Three terms, a substitution and a boolean flag. + <Term> is typically an equality term. + RETURNS: If <TestTerm> occurs in the right (Right=TRUE) or + left side (Right=FALSE) of <Term>: + + A copy of the term where all occurrences of <TestTerm> + in the ENTIRE <Term> are replaced by <RplacTerm> and + the substitution <Subst> is applied to all other subterms. + + If <TestTerm> does not occur in the right/left side of + <Term>, NULL is returned. + + In non-equality terms, The 'sides' correspond to the + first and second argument of the term. +***************************************************************/ +{ + TERM ActTerm = term_Copy(Term); + TERM ReplSide, OtherSide; /* ReplSide is the side in which terms are + replaced */ + + if (Right) { + ReplSide = term_SecondArgument(ActTerm); + OtherSide = term_FirstArgument(ActTerm); + } + else { + ReplSide = term_FirstArgument(ActTerm); + OtherSide = term_SecondArgument(ActTerm); + } + + if (inf_NAllTermsRplac(ReplSide, TestTerm, RplacTerm, Subst)) + /* If <TestTerm> occurs in <ReplSide> also replace it in <OtherSide>. */ + inf_NAllTermsRplac(OtherSide, TestTerm, RplacTerm, Subst); + else { + term_Delete(ActTerm); + ActTerm = NULL; + } + + return ActTerm; +} + + +static TERM inf_AllTermsRightRplac(TERM Term, TERM TestTerm, TERM RplacTerm, + SUBST Subst) +/************************************************************** + INPUT: Three terms, a substitution. + <Term> is typically an equality term. + RETURNS: See inf_AllTermSideRplac with argument + 'Right' set to TRUE +**************************************************************/ +{ + return(inf_AllTermsSideRplacs(Term, TestTerm, RplacTerm, Subst, TRUE)); +} + + +static TERM inf_AllTermsLeftRplac(TERM Term, TERM TestTerm, TERM RplacTerm, + SUBST Subst) +/************************************************************** + INPUT: Three terms, a substitution. + <Term> is typically an equality term. + RETURNS: See inf_AllTermSideRplac with argument + 'Right' set to FALSE. +***************************************************************/ +{ + return(inf_AllTermsSideRplacs(Term, TestTerm, RplacTerm, Subst, FALSE)); +} + + +/* END of block with new term replacement */ + + +static CLAUSE inf_ApplyGenSuperposition(CLAUSE Clause, int ci, SUBST Subst, + CLAUSE PartnerClause, int pci, + SUBST PartnerSubst, TERM SupAtom, + BOOL Right, BOOL OrdPara, BOOL MaxPara, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: Two clauses where a generalized superposition inference can be + applied using the positive equality literal <i> from <Clause> with + subst <Subst> using the literal <j> from <PartnerClause> with subst + <PartnerSubst> where SupAtom is a derivable atom. Returns + NULL if SupAtom is NULL. + + Right is TRUE if the inference is a superposition right inference + Right is FALSE if the inference is a superposition left inference, + + where the inference is selected by MaxPara and OrdPara: + (see also inf_GenSuperpositionLeft) + + OrdPara=TRUE, MaxPara=TRUE + -> Superposition (Left or Right) + + OrdPara=TRUE, MaxPara=FALSE + -> ordered Paramodulation + + OrdPara=FALSE, MaxPara=FALSE + -> simple Paramodulation + + OrdPara=FALSE, MaxPara=TRUE + -> not defined + + A flag store. + A precedence. + RETURNS: The new clause. + MEMORY: Memory for the new clause is allocated. +***************************************************************/ +{ + CLAUSE NewClause; + int j,lc,la,ls,pls,pla,plc,help; + +#ifdef CHECK + if (!OrdPara && MaxPara) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_ApplyGenSuperposition : Illegal inference"); + misc_ErrorReport("\n rule selection, OrdPara=FALSE and MaxPara=TRUE."); + misc_FinishErrorReport(); + } + if (SupAtom == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_ApplyGenSuperposition: Atom is NULL."); + misc_FinishErrorReport(); + return clause_Null(); + } +#endif + + pls = clause_LastSuccedentLitIndex(PartnerClause); + pla = clause_LastAntecedentLitIndex(PartnerClause); + plc = clause_LastConstraintLitIndex(PartnerClause); + + ls = clause_LastSuccedentLitIndex(Clause); + la = clause_LastAntecedentLitIndex(Clause); + lc = clause_LastConstraintLitIndex(Clause); + + + NewClause = clause_CreateBody(clause_Length(Clause) - 1 + + clause_Length(PartnerClause)); + + clause_SetNumOfConsLits(NewClause, (clause_NumOfConsLits(Clause) + + clause_NumOfConsLits(PartnerClause))); + clause_SetNumOfAnteLits(NewClause, (clause_NumOfAnteLits(Clause) + + clause_NumOfAnteLits(PartnerClause))); + clause_SetNumOfSuccLits(NewClause, ((clause_NumOfSuccLits(Clause) -1)+ + clause_NumOfSuccLits(PartnerClause))); + + /* First set the literals from the Clause : */ + + for (j = clause_FirstLitIndex(); j <= lc; j++) { + clause_SetLiteral(NewClause, j, + clause_LiteralCreate(subst_Apply(Subst, term_Copy( + clause_GetLiteralTerm(Clause, j))),NewClause)); + } + + /* help = number of literals to leave empty */ + help = clause_NumOfConsLits(PartnerClause); + + for ( ; j <= la; j++) { + clause_SetLiteral(NewClause, (j + help), + clause_LiteralCreate(subst_Apply(Subst, term_Copy( + clause_GetLiteralTerm(Clause, j))),NewClause)); + } + + /* help = number of literals to leave empty */ + help += clause_NumOfAnteLits(PartnerClause); + + for ( ; j <= ls; j++) { + if (j != ci) { + /* The literal used in the inference isn't copied */ + clause_SetLiteral(NewClause, (j + help), + clause_LiteralCreate(subst_Apply(Subst, + term_Copy(clause_GetLiteralTerm(Clause, j))),NewClause)); + + } else { + /*the index has to be decreased to avoid an empty literal! */ + help--; + } + } + + /* Now we consider the PartnerClause : */ + + /* help = number of already set constraint (Clause) literals */ + help = clause_NumOfConsLits(Clause); + + for (j = clause_FirstLitIndex(); j <= plc; j++) { + clause_SetLiteral(NewClause, (j + help), + clause_LiteralCreate(subst_Apply(PartnerSubst, + term_Copy(clause_GetLiteralTerm(PartnerClause, j))),NewClause)); + } + + /* help = number of already set constraint and antecedent Given-literals */ + help += clause_NumOfAnteLits(Clause); + + for ( ; j <= pla; j++) { + if (j != pci) { + clause_SetLiteral(NewClause, (j + help), + clause_LiteralCreate(subst_Apply(PartnerSubst, + term_Copy(clause_GetLiteralTerm(PartnerClause, j))),NewClause)); + } else { + /* The PartnerLit is modified appropriately! */ + clause_SetLiteral(NewClause, (j + help), clause_LiteralCreate( + term_Create(fol_Not(),list_List(SupAtom)), NewClause)); + } + } + + + /* help = number of already set Given-literals */ + help = clause_Length(Clause) - 1; + + for ( ; j <= pls; j++) { + if (j != pci) { + /* The PartnerLit isn't copied! */ + clause_SetLiteral(NewClause, (j + help), + clause_LiteralCreate(subst_Apply(PartnerSubst, + term_Copy(clause_GetLiteralTerm(PartnerClause, j))),NewClause)); + + } else { + /* The PartnerLit is modified appropriately! */ + clause_SetLiteral(NewClause, (j + help), + clause_LiteralCreate(SupAtom, NewClause)); + } + } + + /* + * Set inference type. Note that, in the case of (ordered) paramodulation, + * we do not distinguish which side was paramodulated into, as compared + * to the case of superposition. + */ + + if (OrdPara && MaxPara) { + if (Right) + clause_SetFromSuperpositionRight(NewClause); + else + clause_SetFromSuperpositionLeft(NewClause); + } + else if (OrdPara && !MaxPara) + clause_SetFromOrderedParamodulation(NewClause); + else + clause_SetFromParamodulation(NewClause); + + clause_SetDataFromParents(NewClause, PartnerClause, pci, Clause, ci, Flags, + Precedence); + + return NewClause; +} + + +/* START of block with new superposition right rule */ + +static LIST inf_GenLitSPRight(CLAUSE Clause, TERM Left, TERM Right, int i, + SHARED_INDEX ShIndex, BOOL OrdPara, BOOL MaxPara, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause (unshared) with a positive equality literal + at position <i> where <Left> and <Right> are the arguments + of just that literal and <Right> is not greater wrt. the + ordering than <Left>, + two boolean flags for controlling inference + preconditions (see inf_GenSuperpositionRight), + a flag store and a precedence. + RETURNS: A list of clauses derivable with the literals owning + clause by general superposition right wrt. the Index. + (see inf_GenSuperpositionRight for selection of inference + rule by OrdPara/MaxPara) + MEMORY: The list of clauses is extended, where memory for the + list and the clauses is allocated. +***************************************************************/ +{ + LIST Result, Terms; + + Result = list_Nil(); + Terms = st_GetUnifier(cont_LeftContext(), sharing_Index(ShIndex), + cont_RightContext(), Left); + + for ( ; !list_Empty(Terms); Terms = list_Pop(Terms)) { + LIST Lits; + TERM Term; + + Term = (TERM)list_First(Terms); + + if (!term_IsVariable(Term) && !symbol_IsPredicate(term_TopSymbol(Term))) { + + Lits = sharing_GetDataList(Term, ShIndex); + + for ( ; !list_Empty(Lits); Lits = list_Pop(Lits)) { + LITERAL PartnerLit; + TERM PartnerAtom; + CLAUSE PartnerClause; + int pli; + + PartnerLit = (LITERAL)list_Car(Lits); + PartnerAtom = clause_LiteralAtom(PartnerLit); + pli = clause_LiteralGetIndex(PartnerLit); + PartnerClause = clause_LiteralOwningClause(PartnerLit); + + if (!clause_GetFlag(PartnerClause,CLAUSESELECT) && + (!MaxPara || clause_LiteralGetFlag(PartnerLit,STRICTMAXIMAL)) && + !clause_GetFlag(PartnerClause,NOPARAINTO) && + clause_LiteralIsPositive(PartnerLit) && + clause_HasSolvedConstraint(PartnerClause)) { + + SUBST Subst, PartnerSubst; + TERM NewLeft,NewRight; + SYMBOL PartnerMaxVar; + TERM SupAtom; + + SupAtom = (TERM)NULL; + + PartnerMaxVar = clause_MaxVar(PartnerClause); + NewLeft = Left; + clause_RenameVarsBiggerThan(Clause, PartnerMaxVar); + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(), Left, cont_RightContext(), Term); + subst_ExtractUnifier(cont_LeftContext(), &Subst, cont_RightContext(), &PartnerSubst); + cont_Reset(); + if (!MaxPara || + inf_LiteralsMax(Clause, i, Subst, PartnerClause, pli, + PartnerSubst, Flags, Precedence)) { + NewRight = subst_Apply(Subst, term_Copy(Right)); + if (OrdPara && + !clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause,i))) + NewLeft = subst_Apply(Subst, term_Copy(Left)); + if (!OrdPara || + NewLeft == Left || /* TRUE, if oriented */ + ord_Compare(NewLeft,NewRight, Flags, Precedence) != ord_SmallerThan()) { + if (!MaxPara || clause_LiteralIsPredicate(PartnerLit)) { + SupAtom = inf_AllTermsRplac(PartnerAtom, Term, + NewRight, PartnerSubst); + } else { + /* Superposition and <PartnerLit> is equality */ + if (clause_LiteralIsOrientedEquality(PartnerLit)) + SupAtom = inf_AllTermsLeftRplac(PartnerAtom, Term, + NewRight, PartnerSubst); + else { + TERM NewPartnerLeft,NewPartnerRight; + NewPartnerLeft = + subst_Apply(PartnerSubst, + term_Copy(term_FirstArgument(PartnerAtom))); + NewPartnerRight = + subst_Apply(PartnerSubst, + term_Copy(term_SecondArgument(PartnerAtom))); + switch (ord_Compare(NewPartnerLeft,NewPartnerRight, + Flags, Precedence)) { + case ord_SMALLER_THAN: + SupAtom = inf_AllTermsRightRplac(PartnerAtom,Term, + NewRight,PartnerSubst); + break; + case ord_GREATER_THAN: + SupAtom = inf_AllTermsLeftRplac(PartnerAtom,Term, + NewRight,PartnerSubst); + break; + default: + SupAtom = inf_AllTermsRplac(PartnerAtom,Term, + NewRight,PartnerSubst); + } + term_Delete(NewPartnerLeft); + term_Delete(NewPartnerRight); + } + } + + if (SupAtom != NULL) + Result = + list_Cons(inf_ApplyGenSuperposition(Clause, i, Subst, + PartnerClause, pli, + PartnerSubst, SupAtom, + TRUE, OrdPara, MaxPara, + Flags, Precedence), + Result); + } + if (NewLeft != Left) + term_Delete(NewLeft); + term_Delete(NewRight); + } + subst_Delete(Subst); + subst_Delete(PartnerSubst); + } + } + } + } + return Result; +} + + +static LIST inf_GenSPRightEqToGiven(CLAUSE Clause, int i, BOOL Left, + SHARED_INDEX ShIndex, BOOL OrdPara, + BOOL MaxPara, BOOL Unit, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: An unshared clause, the index of a succedent literal + that is an equality literal and a boolean value which + argument to use: + If Left==TRUE then the left argument is used + otherwise the right argument. + Three boolean flags for controlling inference + preconditions (see inf_GenSuperpositionRight). + A flag store. + A precedence. + RETURNS: A list of clauses derivable from general superposition right on the + GivenCopy wrt. the Index. + (see inf_GenSuperpositionRight for selection of inference + rule by OrdPara/MaxPara) + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result, TermList, Parents; + int Bottom; + LITERAL Lit; + TERM Atom, Term, PartnerTerm, PartnerEq; + + Result = list_Nil(); + Lit = clause_GetLiteral(Clause,i); + Atom = clause_LiteralAtom(Lit); + +#ifdef CHECK + if (!fol_IsEquality(Atom) || + (MaxPara && clause_LiteralIsOrientedEquality(Lit) && !Left) || + (MaxPara && !clause_LiteralGetFlag(Lit, STRICTMAXIMAL))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSPRightEqToGiven: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Bottom = stack_Bottom(); + if (Left) /* Top Level considered in inf_LitSPRight */ + sharing_PushListOnStack(term_ArgumentList(term_FirstArgument(Atom))); + else + sharing_PushListOnStack(term_ArgumentList(term_SecondArgument(Atom))); + + while (!stack_Empty(Bottom)) { + Term = (TERM)stack_PopResult(); + if (!term_IsVariable(Term)) { + /* Superposition into variables is not necessary */ + TermList = st_GetUnifier(cont_LeftContext(), sharing_Index(ShIndex), + cont_RightContext(), Term); + for ( ; !list_Empty(TermList); TermList = list_Pop(TermList)) { + PartnerTerm = (TERM)list_Car(TermList); + for (Parents = term_SupertermList(PartnerTerm); + !list_Empty(Parents); Parents = list_Cdr(Parents)) { + PartnerEq = (TERM)list_Car(Parents); + if (fol_IsEquality(PartnerEq)) { + CLAUSE PartnerClause; + LITERAL PartnerLit; + LIST Scl; + int j; + for (Scl = sharing_NAtomDataList(PartnerEq); + !list_Empty(Scl); Scl = list_Cdr(Scl)) { + PartnerLit = (LITERAL)list_Car(Scl); + j = clause_LiteralGetIndex(PartnerLit); + PartnerClause = clause_LiteralOwningClause(PartnerLit); + if (!clause_GetFlag(PartnerClause,CLAUSESELECT) && + (!MaxPara || + clause_LiteralGetFlag(PartnerLit,STRICTMAXIMAL)) && + (!OrdPara || PartnerTerm==term_FirstArgument(PartnerEq) || + !clause_LiteralIsOrientedEquality(PartnerLit)) && + clause_LiteralIsPositive(PartnerLit) && + clause_Number(PartnerClause) != clause_Number(Clause) && + (!Unit || clause_Length(PartnerClause) == 1) && + clause_HasSolvedConstraint(PartnerClause)) { + /* We exclude the same clause since that inference will be */ + /* made by the "forward" function inf_GenLitSPRight. */ + SYMBOL MaxVar; + SUBST Subst, PartnerSubst; + + MaxVar = clause_MaxVar(PartnerClause); + clause_RenameVarsBiggerThan(Clause, MaxVar); + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(), Term, cont_RightContext(), + PartnerTerm); + subst_ExtractUnifier(cont_LeftContext(), &Subst, + cont_RightContext(), &PartnerSubst); + cont_Reset(); + if (!MaxPara || + inf_LiteralsMax(Clause, i, Subst, PartnerClause, j, + PartnerSubst, Flags, Precedence)) { + TERM PartnerLeft,PartnerRight; + BOOL Check, PartnerCheck; + PartnerLeft = PartnerRight = NULL; + PartnerCheck = Check = TRUE; + if (OrdPara && + !clause_LiteralIsOrientedEquality(PartnerLit)) { + /* Check post condition for partner literal */ + if (PartnerTerm == term_FirstArgument(PartnerEq)) + PartnerRight = term_SecondArgument(PartnerEq); + else + PartnerRight = term_FirstArgument(PartnerEq); + PartnerLeft = subst_Apply(PartnerSubst, + term_Copy(PartnerTerm)); + PartnerRight = subst_Apply(PartnerSubst, + term_Copy(PartnerRight)); + PartnerCheck = (ord_Compare(PartnerLeft, PartnerRight, + Flags, Precedence) + != ord_SmallerThan()); + } + if (PartnerCheck && + MaxPara && !clause_LiteralIsOrientedEquality(Lit)) { + /* Check post condition for literal in given clause */ + TERM NewLeft, NewRight; + if (Left) { + NewLeft = term_FirstArgument(Atom); + NewRight = term_SecondArgument(Atom); + } else { + NewLeft = term_SecondArgument(Atom); + NewRight = term_FirstArgument(Atom); + } + NewLeft = subst_Apply(Subst, term_Copy(NewLeft)); + NewRight = subst_Apply(Subst, term_Copy(NewRight)); + Check = (ord_Compare(NewLeft, NewRight, Flags, Precedence) + != ord_SmallerThan()); + term_Delete(NewLeft); + term_Delete(NewRight); + } + if (Check && PartnerCheck) { + /* Make inference only if both tests were successful */ + TERM SupAtom; + SupAtom = NULL; + if (PartnerRight == NULL) { + if (PartnerTerm==term_FirstArgument(PartnerEq)) + PartnerRight = term_SecondArgument(PartnerEq); + else + PartnerRight = term_FirstArgument(PartnerEq); + PartnerRight = subst_Apply(PartnerSubst, + term_Copy(PartnerRight)); + } + if (Left) + SupAtom = inf_AllTermsLeftRplac(Atom, Term, + PartnerRight, Subst); + else + SupAtom = inf_AllTermsRightRplac(Atom, Term, + PartnerRight, Subst); +#ifdef CHECK + if (SupAtom == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSPRightEqToGiven:"); + misc_ErrorReport(" replacement wasn't possible."); + misc_FinishErrorReport(); + } +#endif + Result = + list_Cons(inf_ApplyGenSuperposition(PartnerClause, j, + PartnerSubst, Clause, + i, Subst, SupAtom, + TRUE,OrdPara,MaxPara, + Flags, Precedence), + Result); + } + if (PartnerLeft != term_Null()) + term_Delete(PartnerLeft); + if (PartnerRight != term_Null()) + term_Delete(PartnerRight); + } + subst_Delete(Subst); + subst_Delete(PartnerSubst); + } + } + } + } + } + } + } + return Result; +} + + +static LIST inf_GenSPRightLitToGiven(CLAUSE Clause, int i, TERM Atom, + SHARED_INDEX ShIndex, BOOL OrdPara, + BOOL MaxPara, BOOL Unit, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: An unshared clause, the index of a succedent literal + that is not an equality literal and its atom, + three boolean flags for controlling inference + preconditions (see inf_GenSuperpositionRight), + a flag store and a precedence. + RETURNS: A list of clauses derivable from general superposition right on the + GivenCopy wrt. the Index. + (see inf_GenSuperpositionRight for selection of inference + rule by OrdPara/MaxPara) + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result, TermList, ParentList; + int Bottom; + TERM Term, PartnerTerm, PartnerEq; + + Result = list_Nil(); + + Bottom = stack_Bottom(); + sharing_PushListOnStack(term_ArgumentList(Atom)); + + while (!stack_Empty(Bottom)) { + Term = (TERM)stack_PopResult(); + if (!term_IsVariable(Term)) { + /* Superposition into variables is not necessary */ + TermList = st_GetUnifier(cont_LeftContext(), sharing_Index(ShIndex), + cont_RightContext(), Term); + for ( ; !list_Empty(TermList); TermList=list_Pop(TermList)) { + PartnerTerm = (TERM)list_Car(TermList); + for (ParentList = term_SupertermList(PartnerTerm); + !list_Empty(ParentList); ParentList = list_Cdr(ParentList)) { + PartnerEq = (TERM)list_Car(ParentList); + if (fol_IsEquality(PartnerEq)) { + CLAUSE PartnerClause; + LITERAL PartnerLit; + LIST Scl; + int j; + for (Scl = sharing_NAtomDataList(PartnerEq); + !list_Empty(Scl); Scl = list_Cdr(Scl)) { + PartnerLit = (LITERAL)list_Car(Scl); + j = clause_LiteralGetIndex(PartnerLit); + PartnerClause = clause_LiteralOwningClause(PartnerLit); + if (!clause_GetFlag(PartnerClause,CLAUSESELECT) && + (!MaxPara || + clause_LiteralGetFlag(PartnerLit,STRICTMAXIMAL)) && + (!OrdPara || PartnerTerm==term_FirstArgument(PartnerEq) || + !clause_LiteralIsOrientedEquality(PartnerLit)) && + clause_LiteralIsPositive(PartnerLit) && + clause_Number(PartnerClause) != clause_Number(Clause) && + (!Unit || clause_Length(PartnerClause) == 1) && + clause_HasSolvedConstraint(PartnerClause)) { + /* We exclude the same clause since that inference will be */ + /* made by the "forward" function inf_GenLitSPRight. */ + SYMBOL MaxVar; + TERM PartnerLeft,PartnerRight; + SUBST Subst, PartnerSubst; + TERM SupAtom; + + SupAtom = (TERM)NULL; + MaxVar = clause_MaxVar(PartnerClause); + clause_RenameVarsBiggerThan(Clause,MaxVar); + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(), Term, + cont_RightContext(),PartnerTerm); + subst_ExtractUnifier(cont_LeftContext(), &Subst, + cont_RightContext(),&PartnerSubst); + cont_Reset(); + + if (!MaxPara || + inf_LiteralsMax(Clause, i, Subst, PartnerClause, j, + PartnerSubst, Flags, Precedence)) { + PartnerLeft = subst_Apply(PartnerSubst, + term_Copy(PartnerTerm)); + if (PartnerTerm == term_FirstArgument(PartnerEq)) + PartnerRight = + subst_Apply(PartnerSubst, + term_Copy(term_SecondArgument(PartnerEq))); + else + PartnerRight = + subst_Apply(PartnerSubst, + term_Copy(term_FirstArgument(PartnerEq))); + + if (!OrdPara || + clause_LiteralIsOrientedEquality(PartnerLit) || + ord_Compare(PartnerLeft,PartnerRight, Flags, Precedence) + != ord_SmallerThan()) { + SupAtom = inf_AllTermsRplac(Atom,Term,PartnerRight,Subst); +#ifdef CHECK + if (SupAtom == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSPRightLitToGiven:"); + misc_ErrorReport(" replacement wasn't possible."); + misc_FinishErrorReport(); + } +#endif + Result = + list_Cons(inf_ApplyGenSuperposition(PartnerClause, j, + PartnerSubst, Clause, + i, Subst, SupAtom, + TRUE,OrdPara,MaxPara, + Flags, Precedence), + Result); + + } + term_Delete(PartnerLeft); + term_Delete(PartnerRight); + } + subst_Delete(Subst); + subst_Delete(PartnerSubst); + } + } + } + } + } + } + } + return Result; +} + + +static LIST inf_GenSPRightToGiven(CLAUSE Clause, int i, SHARED_INDEX ShIndex, + BOOL OrdPara, BOOL MaxPara, BOOL Unit, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: An unshared clause, the index of a succedent literal + and an index of shared clauses, + three boolean flags for controlling inference + preconditions (see inf_GenSuperpositionRight), + a flag store and a precedence. + RETURNS: A list of clauses derivable from superposition right on the + GivenCopy wrt. the Index. + (see inf_GenSuperpositionRight for selection of inference + rule by OrdPara/MaxPara) + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + TERM Atom; + LIST Result; + +#ifdef CHECK + if (clause_GetFlag(Clause, NOPARAINTO) || + clause_GetFlag(Clause, CLAUSESELECT) || + (MaxPara && + !clause_LiteralGetFlag(clause_GetLiteral(Clause,i), STRICTMAXIMAL))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSPRightToGiven: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Result = list_Nil(); + Atom = clause_LiteralAtom(clause_GetLiteral(Clause,i)); + + if (fol_IsEquality(Atom)) { + Result = list_Nconc(inf_GenSPRightEqToGiven(Clause,i,TRUE,ShIndex,OrdPara, + MaxPara,Unit,Flags, Precedence), + Result); + + if (!MaxPara || + !clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause,i))) + /* For SPm and OPm always try other direction, for SpR try it */ + /* only if the literal is not oriented. */ + Result = list_Nconc(inf_GenSPRightEqToGiven(Clause, i, FALSE, ShIndex, + OrdPara,MaxPara,Unit, + Flags, Precedence), + Result); + } else + Result = list_Nconc(inf_GenSPRightLitToGiven(Clause,i,Atom,ShIndex, + OrdPara,MaxPara,Unit, + Flags, Precedence), + Result); + + return Result; +} + + +LIST inf_GenSuperpositionRight(CLAUSE GivenClause, SHARED_INDEX ShIndex, + BOOL OrdPara, BOOL MaxPara, BOOL Unit, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause and an Index, usually the WorkedOffIndex, + three boolean flags for controlling inference + preconditions, a flag store and a precedence. + RETURNS: A list of clauses derivable from the given clause by + superposition right wrt. the Index. + + OrdPara=TRUE, MaxPara=TRUE + -> Superposition Right + + OrdPara=TRUE, MaxPara=FALSE + -> ordered Paramodulation + + OrdPara=FALSE, MaxPara=FALSE + -> simple Paramodulation + + OrdPara=FALSE, MaxPara=TRUE + -> not defined + + If <Unit>==TRUE the clause with the maximal equality + additionally must be a unit clause. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result; + TERM Atom; + CLAUSE Copy; + int i, n; + LITERAL ActLit; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSuperpositionRight: Illegal input."); + misc_FinishErrorReport(); + } + if (!OrdPara && MaxPara) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSuperpositionRight: Illegal inference"); + misc_ErrorReport("\n rule selection, OrdPara=FALSE & MaxPara=TRUE."); + misc_FinishErrorReport(); + } +#endif + + if (clause_GetFlag(GivenClause,CLAUSESELECT) || + clause_HasEmptySuccedent(GivenClause) || + !clause_HasSolvedConstraint(GivenClause)) + return list_Nil(); + + Result = list_Nil(); + + Copy = clause_Copy(GivenClause); + n = clause_LastSuccedentLitIndex(Copy); + + for (i = clause_FirstSuccedentLitIndex(Copy); i <= n; i++) { + + ActLit = clause_GetLiteral(Copy, i); + Atom = clause_LiteralSignedAtom(ActLit); + + if (!MaxPara || + clause_LiteralGetFlag(ActLit,STRICTMAXIMAL)) { + if (fol_IsEquality(Atom) && + (!Unit || clause_Length(GivenClause) == 1)) { + + Result = list_Nconc(inf_GenLitSPRight(Copy, term_FirstArgument(Atom), + term_SecondArgument(Atom), i, + ShIndex,OrdPara,MaxPara,Flags, + Precedence), + Result); + + if (!OrdPara || + !clause_LiteralIsOrientedEquality(ActLit)) + Result = list_Nconc(inf_GenLitSPRight(Copy, + term_SecondArgument(Atom), + term_FirstArgument(Atom), i, + ShIndex,OrdPara,MaxPara,Flags, + Precedence), + Result); + } + if (!clause_GetFlag(Copy, NOPARAINTO)) + Result = list_Nconc(inf_GenSPRightToGiven(Copy, i, ShIndex, OrdPara, + MaxPara,Unit,Flags,Precedence), + Result); + } + } + clause_Delete(Copy); + + return Result; +} + + + +/* END of block with new superposition right rule */ + + +static LIST inf_ApplyMParamod(CLAUSE C1, CLAUSE C2, int i, int j, int k, + TERM u_tau, TERM v, TERM s2, TERM t, + TERM v2_sigma, SUBST tau, SUBST rho, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: Two clauses, <i> is a literal index in <C1>, <j> and <k> + are literal indices in <C2>, <u_tau> with <rho> applied + is used as left side of the two new literals, <v> with + subterm <s2> replaced by <t> is used as right side of + the first new literal, <v2_sigma> as right side of the + second new literal, two substitutions and a flag store. + The substitution <rho> is applied after <tau>. + A flag store. + A precedence. + RETURNS: A list containing one clause derived from the given + clauses and literals by merging paramodulation. + MEMORY: Memory for the list and the clause is allocated. +***************************************************************/ +{ + CLAUSE newClause; + TERM u_sigma; + int m, lc, la, ls, pls, pla, plc, help; + + pls = clause_LastSuccedentLitIndex(C2); + pla = clause_LastAntecedentLitIndex(C2); + plc = clause_LastConstraintLitIndex(C2); + + ls = clause_LastSuccedentLitIndex(C1); + la = clause_LastAntecedentLitIndex(C1); + lc = clause_LastConstraintLitIndex(C1); + + newClause = clause_CreateBody(clause_Length(C1) + clause_Length(C2) - 1); + + clause_SetNumOfConsLits(newClause, (clause_NumOfConsLits(C1) + + clause_NumOfConsLits(C2))); + clause_SetNumOfAnteLits(newClause, (clause_NumOfAnteLits(C1) + + clause_NumOfAnteLits(C2))); + clause_SetNumOfSuccLits(newClause, (clause_NumOfSuccLits(C1) - 1 + + clause_NumOfSuccLits(C2))); + + for (m = clause_FirstLitIndex(); m <= lc; m++) + clause_SetLiteral(newClause, m, + clause_LiteralCreate(subst_Apply(rho, subst_Apply(tau, + term_Copy(clause_GetLiteralTerm(C1, m)))), newClause)); + + /* help = number of literals to leave empty */ + help = clause_NumOfConsLits(C2); + + for ( ; m <= la; m++) + clause_SetLiteral(newClause, (m + help), + clause_LiteralCreate(subst_Apply(rho, subst_Apply(tau, + term_Copy(clause_GetLiteralTerm(C1, m)))), newClause)); + + /* help = number of literals to leave empty */ + help += clause_NumOfAnteLits(C2); + + for ( ; m <= ls; m++) { + if (m != i) + /* The literal used in the inference isn't copied */ + clause_SetLiteral(newClause, (m + help), + clause_LiteralCreate(subst_Apply(rho, subst_Apply(tau, + term_Copy(clause_GetLiteralTerm(C1, m)))),newClause)); + else + /* the index has to be decreased to avoid an empty literal! */ + help--; + } + + /* Now we consider the PartnerClause : */ + + /* help = number of already set constraint (Clause) literals */ + help = clause_NumOfConsLits(C1); + + for (m = clause_FirstLitIndex(); m <= plc; m++) + clause_SetLiteral(newClause, (m + help), + clause_LiteralCreate(subst_Apply(rho, subst_Apply(tau, + term_Copy(clause_GetLiteralTerm(C2, m)))),newClause)); + + /* help = number of already set constraint and antecedent Given-literals */ + help += clause_NumOfAnteLits(C1); + + for ( ; m <= pla; m++) + clause_SetLiteral(newClause, (m + help), + clause_LiteralCreate(subst_Apply(rho, subst_Apply(tau, + term_Copy(clause_GetLiteralTerm(C2, m)))),newClause)); + + /* help = number of already set literals */ + help += clause_NumOfSuccLits(C1) - 1; + /*help = clause_Length(Clause) - 1;*/ + + u_sigma = subst_Apply(rho, term_Copy(u_tau)); + + for ( ; m <= pls; m++) { + TERM newAtom; + + if (m == j) { + /* The first partner literal is modified appropriately! */ + TERM right; + if (v == s2) + /* Necessary because term_ReplaceSubtermBy doesn't treat top level */ + right = term_Copy(t); + else { + right = term_Copy(v); + term_ReplaceSubtermBy(right, s2, t); + } + newAtom = term_Create(fol_Equality(), list_Cons(term_Copy(u_sigma), + list_List(subst_Apply(rho, subst_Apply(tau, right))))); + } else if (m == k) { + /* The second partner lit is modified appropriately! */ + newAtom = term_Create(fol_Equality(), list_Cons(term_Copy(u_sigma), + list_List(term_Copy(v2_sigma)))); + } else { + /* Apply substitutions to all other literals */ + newAtom = subst_Apply(rho, subst_Apply(tau, + term_Copy(clause_GetLiteralTerm(C2, m)))); + } + + clause_SetLiteral(newClause, (m + help), + clause_LiteralCreate(newAtom, newClause)); + } + + term_Delete(u_sigma); + + clause_SetFromMergingParamodulation(newClause); + + clause_AddParentClause(newClause, clause_Number(C2)); + clause_AddParentLiteral(newClause, k); + clause_SetDataFromParents(newClause, C2, j, C1, k, Flags, Precedence); + + return list_List(newClause); +} + + +static LIST inf_Lit2MParamod(CLAUSE C1, CLAUSE C2, int i, int j, TERM s, TERM t, + TERM s2, TERM v, TERM u_tau, SUBST tau, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: Two clauses, the index <i> of a strict maximal literal + in <C1>, the index <j> of a strict maximal index in <C2>, + <s> and <t> are from literal <i>, <s2> is a subterm + of <v>, <v> is from literal <j>, <u_tau> is <u> with + substitution <tau> applied, a flag store, and a precedence. + <u_tau> must be greater than <v>tau wrt. the ordering. + RETURNS: A list of clauses derivable from the given data + by merging paramodulation. + This function searches <C2> for a second positive literal + u'=v', where u' is unifiable with <u_tau>. + MEMORY: Memory is allocated for the list and the clauses. +***************************************************************/ +{ + LIST result; + int k, last; + + result = list_Nil(); + + /* Now find the 3rd literal u' = v' in C2 */ + last = clause_LastSuccedentLitIndex(C2); /* Last index */ + for (k = clause_FirstSuccedentLitIndex(C2); k <= last; k++) { + LITERAL partnerLit2 = clause_GetLiteral(C2, k); + TERM partnerAtom2 = clause_LiteralSignedAtom(partnerLit2); + + if (k != j && fol_IsEquality(partnerAtom2)) { + /* partnerLit2: u' = v' or v' = u' */ + SUBST rho; + TERM pLeft2, pRight2, s_sigma, t_sigma, v2_sigma; + ord_RESULT ordResult; + BOOL checkPassed; + + pLeft2 = subst_Apply(tau, term_Copy(term_FirstArgument(partnerAtom2))); + pRight2 = subst_Apply(tau, term_Copy(term_SecondArgument(partnerAtom2))); + + /* First try unification with left side */ + cont_Check(); + + if (unify_UnifyCom(cont_LeftContext(), u_tau, pLeft2)) { + subst_ExtractUnifierCom(cont_LeftContext(), &rho); + + s_sigma = t_sigma = (TERM) NULL; + checkPassed = TRUE; + + if (!clause_LiteralIsOrientedEquality(clause_GetLiteral(C1,i))) { + s_sigma = subst_Apply(rho, subst_Apply(tau, term_Copy(s))); + t_sigma = subst_Apply(rho, subst_Apply(tau, term_Copy(t))); + ordResult = ord_Compare(s_sigma, t_sigma, Flags, Precedence); + if (ordResult == ord_SmallerThan() || ordResult == ord_Equal()) + checkPassed = FALSE; + } + + if (checkPassed && inf_LiteralsMaxWith2Subst(C1,i,C2,j,rho,tau, + Flags, Precedence)) { + v2_sigma = subst_Apply(rho, term_Copy(pRight2)); + result = list_Nconc(inf_ApplyMParamod(C1,C2,i,j,k,u_tau,v,s2, + t,v2_sigma,tau,rho, + Flags, Precedence), + result); + term_Delete(v2_sigma); + } + /* Now cleanup */ + if (s_sigma != NULL) { /* Also t_sigma != NULL */ + term_Delete(s_sigma); + term_Delete(t_sigma); + } + subst_Delete(rho); + } + + cont_Reset(); + + /* Now try unification with right side */ + if (unify_UnifyCom(cont_LeftContext(), u_tau, pRight2)) { + subst_ExtractUnifierCom(cont_LeftContext(), &rho); + + s_sigma = t_sigma = (TERM) NULL; + checkPassed = TRUE; + + if (!clause_LiteralIsOrientedEquality(clause_GetLiteral(C1,i))) { + s_sigma = subst_Apply(rho, subst_Apply(tau, term_Copy(s))); + t_sigma = subst_Apply(rho, subst_Apply(tau, term_Copy(t))); + ordResult = ord_Compare(s_sigma, t_sigma, Flags, Precedence); + if (ordResult == ord_SmallerThan() || ordResult == ord_Equal()) + checkPassed = FALSE; + } + + if (checkPassed && inf_LiteralsMaxWith2Subst(C1,i,C2,j,rho,tau, + Flags, Precedence)) { + v2_sigma = subst_Apply(rho, term_Copy(pLeft2)); + result = list_Nconc(inf_ApplyMParamod(C1,C2,i,j,k,u_tau,v,s2, + t,v2_sigma,tau,rho, + Flags, Precedence), + result); + term_Delete(v2_sigma); + } + /* Now cleanup */ + if (s_sigma != NULL) { /* Also t_sigma != NULL */ + term_Delete(s_sigma); + term_Delete(t_sigma); + } + subst_Delete(rho); + } + + cont_Reset(); + + term_Delete(pLeft2); + term_Delete(pRight2); + } /* k != j */ + } /* for k */ + + return result; +} + + +static LIST inf_LitMParamod(CLAUSE Clause, int i, BOOL Turn, + SHARED_INDEX ShIndex, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause with a strict maximal equality literal at + position <i>, a boolean value, a shared index, a + flag store and a precedence. + If <Turn> is TRUE, the left and right term of the + equality are exchanged. + RETURNS: A list of clauses derivable from the given clause + by merging paramodulation. + This function searches a second clause with at least + two positive equalities, where the first equation + has a subterm s', that is unifiable with the left + (or right) side of the given equation. +***************************************************************/ +{ + LIST result, unifiers, literals; + LITERAL actLit; + TERM s, t, help; + + actLit = clause_GetLiteral(Clause, i); + s = term_FirstArgument(clause_LiteralSignedAtom(actLit)); + t = term_SecondArgument(clause_LiteralSignedAtom(actLit)); + if (Turn) { + /* Exchange s and t */ + help = s; + s = t; + t = help; + } + result = list_Nil(); + + unifiers = st_GetUnifier(cont_LeftContext(), sharing_Index(ShIndex), + cont_RightContext(), s); + + for ( ; !list_Empty(unifiers); unifiers = list_Pop(unifiers)) { + TERM s2 = (TERM) list_Car(unifiers); /* Unifiable with s */ + + if (!term_IsVariable(s2) && !term_IsAtom(s2)) { + for (literals = sharing_GetDataList(s2, ShIndex); + !list_Empty(literals); + literals = list_Pop(literals)) { + LITERAL partnerLit = (LITERAL) list_Car(literals); /* u = v[s'] */ + CLAUSE partnerClause = clause_LiteralOwningClause(partnerLit); + TERM partnerAtom = clause_LiteralAtom(partnerLit); + int pli = clause_LiteralGetIndex(partnerLit); + + if (!clause_GetFlag(partnerClause, CLAUSESELECT) && + clause_LiteralGetFlag(partnerLit, STRICTMAXIMAL) && + clause_LiteralIsPositive(partnerLit) && /* succedent literal */ + clause_LiteralIsEquality(partnerLit) && + clause_NumOfSuccLits(partnerClause) > 1 && /* > 1 pos. literals */ + clause_HasSolvedConstraint(partnerClause)) { + TERM partnerLeft = term_FirstArgument(partnerAtom); + TERM partnerRight = term_SecondArgument(partnerAtom); + BOOL inPartnerRight = term_HasPointerSubterm(partnerRight, s2); + + if (!clause_LiteralIsOrientedEquality(partnerLit) || inPartnerRight){ + /* Don't do this if u=v is oriented and s2 is not a subterm of v */ + TERM newPLeft, newPRight; + SUBST tau; + SYMBOL partnerMaxVar; + ord_RESULT ordResult; + + partnerMaxVar = clause_MaxVar(partnerClause); + clause_RenameVarsBiggerThan(Clause, partnerMaxVar); + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(), s, cont_RightContext(), s2); + subst_ExtractUnifierCom(cont_LeftContext(), &tau); + cont_Reset(); + + newPLeft = subst_Apply(tau, term_Copy(partnerLeft)); + newPRight = subst_Apply(tau, term_Copy(partnerRight)); + if (clause_LiteralIsOrientedEquality(partnerLit)) + ordResult = ord_GreaterThan(); + else + ordResult = ord_Compare(newPLeft, newPRight, Flags, Precedence); + + if (inPartnerRight && ord_IsGreaterThan(ordResult)) { + /* Take a look at right side */ + result = list_Nconc(inf_Lit2MParamod(Clause,partnerClause,i,pli, + s, t,s2,partnerRight,newPLeft, + tau, Flags, Precedence), + result); + } + if (ord_IsSmallerThan(ordResult) && + (!inPartnerRight || term_HasPointerSubterm(partnerLeft, s2))) { + /* If s2 is not in partnerRight, it MUST be in partnerLeft, + else really do the test */ + /* Take a look at left side */ + result = list_Nconc(inf_Lit2MParamod(Clause,partnerClause,i,pli, + s,t,s2,partnerLeft,newPRight, + tau,Flags, Precedence), + result); + } + + term_Delete(newPLeft); + term_Delete(newPRight); + subst_Delete(tau); + } + } + } /* for all Literals containing s2 */ + } /* if s2 isn't a variable */ + } /* for all unifiers s2 */ + + return result; +} + + +static LIST inf_MParamodLitToGiven(CLAUSE Clause, int j, BOOL Turn, + SHARED_INDEX ShIndex, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause with a strict maximal equality literal at + position <j>, a boolean value, a shared index a + flag store and a precedence. + If <Turn> is TRUE, the left and right term of the + equality are exchanged. + RETURNS: A list of clauses derivable from the given clause + by merging paramodulation with this literal as second + literal of the rule. +***************************************************************/ +{ + LIST result, unifiers, superterms, literals; + LITERAL actLit; + TERM u, v; + int bottom; + + if (clause_NumOfSuccLits(Clause) < 2) + return list_Nil(); /* There must be at least two positive literals */ + + actLit = clause_GetLiteral(Clause, j); + u = term_FirstArgument(clause_LiteralSignedAtom(actLit)); + v = term_SecondArgument(clause_LiteralSignedAtom(actLit)); + if (Turn) { + /* Exchange s and t */ + TERM help = u; + u = v; + v = help; + } + result = list_Nil(); + bottom = stack_Bottom(); + + sharing_PushReverseOnStack(v); /* Without variables! */ + + while (!stack_Empty(bottom)) { + TERM s2 = (TERM) stack_PopResult(); + + for (unifiers = st_GetUnifier(cont_LeftContext(),sharing_Index(ShIndex), + cont_RightContext(), s2); + !list_Empty(unifiers); + unifiers = list_Pop(unifiers)) { + TERM s = (TERM) list_Car(unifiers); + + for (superterms = term_SupertermList(s); + !list_Empty(superterms); + superterms = list_Cdr(superterms)) { + TERM partnerAtom = (TERM) list_Car(superterms); + + if (fol_IsEquality(partnerAtom)) { + for (literals = sharing_NAtomDataList(partnerAtom); + !list_Empty(literals); + literals = list_Cdr(literals)) { + LITERAL partnerLit = (LITERAL) list_Car(literals); + CLAUSE partnerClause = clause_LiteralOwningClause(partnerLit); + int i = clause_LiteralGetIndex(partnerLit); + + if (!clause_GetFlag(partnerClause,CLAUSESELECT) && + clause_LiteralGetFlag(partnerLit,STRICTMAXIMAL) && + clause_LiteralIsPositive(partnerLit) && + (s == term_FirstArgument(partnerAtom) || + !clause_LiteralIsOrientedEquality(partnerLit)) && + clause_HasSolvedConstraint(partnerClause) && + clause_Number(partnerClause) != clause_Number(Clause)) { + /* We don't allow self inferences (both clauses having the */ + /* same number) here, because they're already made in function */ + /* inf_LitMParamod. */ + SYMBOL partnerMaxVar; + SUBST tau; + TERM u_tau, v_tau; + BOOL checkPassed; + + partnerMaxVar = clause_MaxVar(partnerClause); + clause_RenameVarsBiggerThan(Clause, partnerMaxVar); + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(), s, cont_RightContext(), s2); + subst_ExtractUnifierCom(cont_LeftContext(), &tau); + cont_Reset(); + + u_tau = v_tau = (TERM) NULL; + checkPassed = TRUE; + + /* u_tau must be greater than v_tau */ + if (!clause_LiteralIsOrientedEquality(actLit)) { + u_tau = subst_Apply(tau, term_Copy(u)); + v_tau = subst_Apply(tau, term_Copy(v)); + if (ord_Compare(u_tau, v_tau, Flags, Precedence) != ord_GreaterThan()) + checkPassed = FALSE; + } + + if (checkPassed) { + /* u_tau > v_tau */ + TERM t; + + if (s == term_FirstArgument(partnerAtom)) + t = term_SecondArgument(partnerAtom); + else + t = term_FirstArgument(partnerAtom); + if (u_tau == (TERM)NULL) { + u_tau = subst_Apply(tau, term_Copy(u)); + v_tau = subst_Apply(tau, term_Copy(v)); + } + + result = list_Nconc(inf_Lit2MParamod(partnerClause,Clause,i,j, + s,t,s2,v,u_tau, tau,Flags, + Precedence), + result); + } + + /* Now cleanup */ + if (u_tau != (TERM)NULL) { + term_Delete(u_tau); + term_Delete(v_tau); + } + subst_Delete(tau); + clause_Normalize(Clause); + } + } + } /* partnerAtom is equality */ + } + } + } + + return result; +} + + +LIST inf_MergingParamodulation(CLAUSE GivenClause, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a shared index, a flag store and a + precedence. + RETURNS: A list of clauses derivable from the given clause + by merging paramodulation. + MEMORY: Memory is allocated for the list and the clauses. +***************************************************************/ +{ + LIST result; + CLAUSE copy; + int last, i; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_MergingParamodulation: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (clause_GetFlag(GivenClause, CLAUSESELECT) || + clause_HasEmptySuccedent(GivenClause) || + !clause_HasSolvedConstraint(GivenClause)) + return list_Nil(); + + result = list_Nil(); + copy = clause_Copy(GivenClause); + last = clause_LastSuccedentLitIndex(copy); + + for (i = clause_FirstSuccedentLitIndex(copy); i <= last; i++) { + LITERAL actLit = clause_GetLiteral(copy, i); + TERM atom = clause_LiteralSignedAtom(actLit); + + if (clause_LiteralGetFlag(actLit, STRICTMAXIMAL) && + fol_IsEquality(atom)) { + + result = list_Nconc(inf_LitMParamod(copy,i,FALSE,ShIndex, + Flags, Precedence), + result); + /* Assume GivenClause is the second clause of the rule */ + result = list_Nconc(inf_MParamodLitToGiven(copy,i,FALSE,ShIndex, + Flags, Precedence), + result); + + if (!clause_LiteralIsOrientedEquality(actLit)) { + /* First check rule with left and right side exchanged */ + result = list_Nconc(inf_LitMParamod(copy, i, TRUE, ShIndex, + Flags, Precedence), + result); + /* Now assume GivenClause is the second clause of the rule */ + /* Check with sides exchanged */ + result = list_Nconc(inf_MParamodLitToGiven(copy,i,TRUE,ShIndex, + Flags, Precedence), + result); + } + } + } /* for */ + clause_Delete(copy); + + return result; +} + + +static CLAUSE inf_ApplyGenRes(LITERAL PosLit, LITERAL NegLit, SUBST SubstTermS, + SUBST SubstPartnerTermS, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause to use for Resolution, the index of a + positive non-equality literal, a unifiable literal, + the substitutions for the terms to unify, a flag + store and a precedence. + RETURNS: A clause derivable from the literals owning + clause by Resolution wrt. the Index. + MEMORY: Memory for the new clause is allocated. +***************************************************************/ +{ + CLAUSE NewClause, GivenClause, PartnerClause; + int i,j,lc,la,ls,pi,pls,pla,plc,help,ConNeg,AntNeg; /* p=Partner,l=last */ + + PartnerClause = clause_LiteralOwningClause(NegLit); + GivenClause = clause_LiteralOwningClause(PosLit); + + pls = clause_LastSuccedentLitIndex(PartnerClause); + pla = clause_LastAntecedentLitIndex(PartnerClause); + plc = clause_LastConstraintLitIndex(PartnerClause); + + pi = clause_LiteralGetIndex(NegLit); + + ls = clause_LastSuccedentLitIndex(GivenClause); + la = clause_LastAntecedentLitIndex(GivenClause); + lc = clause_LastConstraintLitIndex(GivenClause); + + i = clause_LiteralGetIndex(PosLit); + + if (pi <= plc) { + ConNeg = 1; + AntNeg = 0; + } + else { + ConNeg = 0; + AntNeg = 1; + } + + NewClause = clause_CreateBody((clause_Length(GivenClause) -1) + + clause_Length(PartnerClause) -1); + + clause_SetNumOfConsLits(NewClause, + (clause_NumOfConsLits(GivenClause) + + (clause_NumOfConsLits(PartnerClause)-ConNeg))); + + clause_SetNumOfAnteLits(NewClause, + (clause_NumOfAnteLits(GivenClause) + + (clause_NumOfAnteLits(PartnerClause)-AntNeg))); + + clause_SetNumOfSuccLits(NewClause, + ((clause_NumOfSuccLits(GivenClause) -1)+ + clause_NumOfSuccLits(PartnerClause))); + + + /* First set the literals from the GivenClause : */ + for (j = clause_FirstLitIndex(); j <= lc; j++) { + clause_SetLiteral(NewClause, j, + clause_LiteralCreate(subst_Apply(SubstTermS, + term_Copy(clause_GetLiteralTerm(GivenClause, j))),NewClause)); + } + + /* help = number of literals to leave empty */ + help = clause_NumOfConsLits(PartnerClause)-ConNeg; + + for ( ; j <= la; j++) { + clause_SetLiteral(NewClause, (j + help), + clause_LiteralCreate(subst_Apply(SubstTermS, + term_Copy(clause_GetLiteralTerm(GivenClause, j))),NewClause)); + } + + /* help = number of literals to leave empty */ + help += clause_NumOfAnteLits(PartnerClause)-AntNeg; + + + + for ( ; j <= ls; j++) { + if (j != i) { + /* The ActLit isn't copied! */ + clause_SetLiteral(NewClause, (j + help), + clause_LiteralCreate(subst_Apply(SubstTermS, + term_Copy(clause_GetLiteralTerm(GivenClause, j))),NewClause)); + + } else { + /*the index has to be decreased to avoid an empty literal! */ + help--; + } + } + + /* Now we consider the PartnerClause : */ + + /* help = number of already set constraint (GivenClause-) literals */ + help = clause_NumOfConsLits(GivenClause); + + for (j = clause_FirstLitIndex(); j <= plc; j++) { + if (j != pi) { + clause_SetLiteral(NewClause, (j + help), + clause_LiteralCreate(subst_Apply(SubstPartnerTermS, + term_Copy(clause_GetLiteralTerm(PartnerClause, j))),NewClause)); + } else { + help--; + } + } + + /* help = number of already set constraint and antecedent Given-literals */ + help += clause_NumOfAnteLits(GivenClause); + + for ( ; j <= pla; j++) { + + if (j != pi) { + /* The NegLit isn't copied! */ + clause_SetLiteral(NewClause, (j + help), + clause_LiteralCreate(subst_Apply(SubstPartnerTermS, + term_Copy(clause_GetLiteralTerm(PartnerClause, j))),NewClause)); + + } else { + /* The index has to be shifted as above. */ + help--; + } + } + + /* help = number of already set (GivenClause-) literals */ + help += clause_NumOfSuccLits(GivenClause) - 1; + + for ( ; j <= pls; j++) { + clause_SetLiteral(NewClause, (j + help), + clause_LiteralCreate(subst_Apply(SubstPartnerTermS, + term_Copy(clause_GetLiteralTerm(PartnerClause, j))),NewClause)); + } /* end of NewClause creation (last for loop). */ + + + clause_SetDataFromParents(NewClause,PartnerClause,pi,GivenClause,i, + Flags, Precedence); + clause_SetFromGeneralResolution(NewClause); + + return(NewClause); +} + + +LIST inf_GeneralResolution(CLAUSE GivenClause, SHARED_INDEX ShIndex, + BOOL Ordered, BOOL Equations, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause and an Index, usually the WorkedOffIndex, + two boolean flags, a flag store and a precedence. + RETURNS: A list of clauses derivable from the GivenClause by + GeneralResolution wrt. the Index. + If <Ordered>=TRUE, this function generates ordered + resolution inferences (the literals must be selected or + (strict) maximal), otherwise it generates standard + resolution inferences. + If <Equations>=TRUE, equations are allowed for inferences, + else no inferences with equations are generated. The + default is <Equations>=FALSE.. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + CLAUSE GivenCopy; + LIST Result; + LITERAL ActLit; + TERM Atom; + int i,n; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GeneralResolution: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (!clause_HasSolvedConstraint(GivenClause)) + return list_Nil(); + + Result = list_Nil(); + GivenCopy = clause_Copy(GivenClause); + + if (clause_GetFlag(GivenCopy,CLAUSESELECT)) + n = clause_LastAntecedentLitIndex(GivenCopy); + else + n = clause_LastSuccedentLitIndex(GivenCopy); + + for (i = clause_FirstAntecedentLitIndex(GivenCopy); i <= n; i++) { + + ActLit = clause_GetLiteral(GivenCopy, i); + Atom = clause_LiteralAtom(ActLit); + + if ((Equations || !fol_IsEquality(Atom)) && + (clause_LiteralGetFlag(ActLit,LITSELECT) || + (!clause_GetFlag(GivenCopy,CLAUSESELECT) && + (!Ordered || clause_LiteralIsMaximal(ActLit)))) && + (!Ordered || clause_LiteralIsFromAntecedent(ActLit) || + clause_LiteralGetFlag(ActLit,STRICTMAXIMAL))) { + /* Positive literals must be strict maximal for ORe, */ + /* negative literals must be either selected or maximal. */ + LIST TermList; + BOOL Swapped; + + Swapped = FALSE; + + /* The 'endless' loop may run twice for equations, once for other atoms */ + while (TRUE) { + TermList = st_GetUnifier(cont_LeftContext(), sharing_Index(ShIndex), + cont_RightContext(), Atom); + + for ( ; !list_Empty(TermList); TermList = list_Pop(TermList)) { + LIST LitList; + TERM PartnerAtom; + + PartnerAtom = list_First(TermList); + + if (!term_IsVariable(PartnerAtom)) { + LITERAL PartnerLit; + int j; + CLAUSE PartnerClause; + + for (LitList = sharing_NAtomDataList(PartnerAtom); + !list_Empty(LitList); LitList = list_Cdr(LitList)) { + PartnerLit = list_Car(LitList); + j = clause_LiteralGetIndex(PartnerLit); + PartnerClause = clause_LiteralOwningClause(PartnerLit); + + if (clause_LiteralsAreComplementary(PartnerLit,ActLit) && + clause_HasSolvedConstraint(PartnerClause) && + /* Negative literals must be from the antecedent */ + (clause_LiteralIsPositive(PartnerLit) || + clause_LiteralIsFromAntecedent(PartnerLit)) && + /* Check whether literal is selected or maximal */ + (clause_LiteralGetFlag(PartnerLit,LITSELECT) || + (!clause_GetFlag(PartnerClause,CLAUSESELECT) && + (!Ordered || clause_LiteralIsMaximal(PartnerLit)))) && + /* Positive literals must be strict maximal for ORe */ + (!Ordered || clause_LiteralIsNegative(PartnerLit) || + clause_LiteralGetFlag(PartnerLit,STRICTMAXIMAL)) && + /* Avoid duplicate self-inferences */ + (clause_LiteralIsPositive(PartnerLit) || + clause_Number(GivenClause) != clause_Number(PartnerClause))) { + SUBST Subst, PartnerSubst; + SYMBOL MaxVar; + + MaxVar = clause_MaxVar(PartnerClause); + clause_RenameVarsBiggerThan(GivenCopy, MaxVar); + + cont_Check(); + if (!unify_UnifyNoOC(cont_LeftContext(), Atom, cont_RightContext(), + PartnerAtom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GeneralResolution: Unification failed."); + misc_FinishErrorReport(); + } + subst_ExtractUnifier(cont_LeftContext(), &Subst, + cont_RightContext(), &PartnerSubst); + cont_Reset(); + + if (!Ordered || + inf_LiteralsMax(GivenCopy, i, Subst, PartnerClause, j, + PartnerSubst, Flags, Precedence)) { + if (clause_LiteralIsNegative(PartnerLit)) + Result = list_Cons(inf_ApplyGenRes(ActLit,PartnerLit,Subst, + PartnerSubst, + Flags, Precedence), + Result); + else + Result = list_Cons(inf_ApplyGenRes(PartnerLit, ActLit, + PartnerSubst,Subst, + Flags, Precedence), + Result); + } + subst_Delete(Subst); + subst_Delete(PartnerSubst); + } + } /* end of for (LitList = sharing_NAtomDataList ...). */ + } /* end of if (!term_IsVariable(PartnerAtom)). */ + } /* end of for (TermList = st_GetUnifier...). */ + if (!Swapped && fol_IsEquality(Atom)) { + term_EqualitySwap(Atom); /* Atom is from copied clause */ + Swapped = TRUE; + } else + break; + } /* end of 'endless' loop */ + } /* end of if (clause_LiteralIsMaximal(ActLit)). */ + } /* end of for 'all antecedent and succedent literals'. */ + + clause_Delete(GivenCopy); + + return Result; +} + + +LIST inf_UnitResolution(CLAUSE GivenClause, SHARED_INDEX ShIndex, + BOOL Equations, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause and an Index, usually the WorkedOffIndex, + a boolean flag, a flag store and a precedence. + RETURNS: A list of clauses derivable from the Givenclause by + Unit Resolution wrt. the Index. + This function does the same inferences as standard resolution, + except that at least one of the clauses must be a unit clause. + The involved literals don't have to be maximal. + If <Equations>=TRUE, equations are allowed for inferences, + else no inferences with equations are made. The + default is <Equations>=FALSE.. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + CLAUSE GivenCopy; + LIST Result; + LITERAL ActLit; + TERM Atom; + BOOL GivenIsUnit; + int i,n; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_UnitResolution: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (!clause_HasSolvedConstraint(GivenClause)) + return list_Nil(); + + Result = list_Nil(); + + GivenCopy = clause_Copy(GivenClause); + GivenIsUnit = (clause_Length(GivenCopy) == 1); + + if (clause_GetFlag(GivenCopy,CLAUSESELECT)) + n = clause_LastAntecedentLitIndex(GivenCopy); + else + n = clause_LastSuccedentLitIndex(GivenCopy); + + for (i=clause_FirstAntecedentLitIndex(GivenCopy); i <= n; i++) { + + ActLit = clause_GetLiteral(GivenCopy, i); + Atom = clause_LiteralAtom(ActLit); + + if ((Equations || !fol_IsEquality(Atom)) && + (clause_LiteralGetFlag(ActLit,LITSELECT) || + !clause_GetFlag(GivenCopy,CLAUSESELECT))) { + LIST TermList; + BOOL Swapped; + + Swapped = FALSE; + + /* The 'endless' loop runs twice for equations, once for other atoms */ + while (TRUE) { + TermList = st_GetUnifier(cont_LeftContext(), sharing_Index(ShIndex), + cont_RightContext(), Atom); + + for ( ; !list_Empty(TermList); TermList = list_Pop(TermList)) { + LIST LitList; + TERM PartnerAtom; + + PartnerAtom = list_First(TermList); + + if (!term_IsVariable(PartnerAtom)) { + LITERAL PartnerLit; + CLAUSE PartnerClause; + + for (LitList = sharing_NAtomDataList(PartnerAtom); + !list_Empty(LitList); LitList = list_Cdr(LitList)) { + PartnerLit = list_Car(LitList); + PartnerClause = clause_LiteralOwningClause(PartnerLit); + + if ((GivenIsUnit || clause_Length(PartnerClause) == 1) && + clause_LiteralsAreComplementary(PartnerLit,ActLit) && + clause_HasSolvedConstraint(PartnerClause) && + /* Negative literals must be from the antecedent */ + (clause_LiteralIsPositive(PartnerLit) || + clause_LiteralIsFromAntecedent(PartnerLit)) && + /* Either the literal is selected or no literal is selected */ + (clause_LiteralGetFlag(PartnerLit,LITSELECT) || + !clause_GetFlag(PartnerClause,CLAUSESELECT))) { + /* Self-inferences aren't possible, since then the clause must */ + /* be a unit and a single literal can't be both positive and */ + /* negative. */ + SUBST Subst, PartnerSubst; + SYMBOL MaxVar; + + MaxVar = clause_MaxVar(PartnerClause); + clause_RenameVarsBiggerThan(GivenCopy, MaxVar); + + cont_Check(); + if (!unify_UnifyNoOC(cont_LeftContext(), Atom, + cont_RightContext(), PartnerAtom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_UnitResolution: Unification failed."); + misc_FinishErrorReport(); + } + subst_ExtractUnifier(cont_LeftContext(), &Subst, + cont_RightContext(), &PartnerSubst); + cont_Reset(); + + if (clause_LiteralIsNegative(PartnerLit)) + Result = list_Cons(inf_ApplyGenRes(ActLit, PartnerLit, Subst, + PartnerSubst, + Flags, Precedence), + Result); + else + Result = list_Cons(inf_ApplyGenRes(PartnerLit, ActLit, + PartnerSubst,Subst, + Flags, Precedence), + Result); + subst_Delete(Subst); + subst_Delete(PartnerSubst); + } + } /* end of for (LitList = sharing_NAtomDataList ...). */ + } /* end of if (!term_IsVariable(PartnerAtom)). */ + } /* end of for (TermList = st_GetUnifier...). */ + if (!Swapped && fol_IsEquality(Atom)) { + term_EqualitySwap(Atom); /* Atom is from copied clause */ + Swapped = TRUE; + } else + break; + } /* end of 'endless' loop */ + } /* end of if (clause_LiteralIsMaximal(ActLit)). */ + } /* end of for 'all antecedent and succedent literals'. */ + + clause_Delete(GivenCopy); + + return Result; +} + +LIST inf_BoundedDepthUnitResolution(CLAUSE GivenClause, SHARED_INDEX ShIndex, + BOOL ConClause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause and an Index, usually the WorkedOffIndex, + a flag indicating whether the partner clause must be + a conjecture clause, a flag store and a precedence. + RETURNS: A list of clauses derivable from the Givenclause by + bounded depth unit resolution wrt. the Index. + This acts similar to inf_UnitResolution, except that + it limits the depth of resolvents to the maximum + depth of its parent clauses. + MEMORY: A list of clauses is produced, where memory for the + list and the clauses is allocated. +***************************************************************/ + /* GivenClause is always a CONCLAUSE */ +{ + CLAUSE GivenCopy; + LIST Result; + LITERAL ActLit; + TERM Atom; + int i,n,depth; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_BoundedDepthUnitResolution: Illegal input."); + misc_FinishErrorReport(); + } + cont_Check(); +#endif + + Result = list_Nil(); + GivenCopy = clause_Copy(GivenClause); + n = clause_LastLitIndex(GivenCopy); + depth = clause_ComputeTermDepth(GivenCopy); + + for (i = clause_FirstLitIndex(); i <= n; i++) { + LIST TermList; + BOOL Swapped; + + ActLit = clause_GetLiteral(GivenCopy, i); + Atom = clause_LiteralAtom(ActLit); + Swapped = FALSE; + + /* The 'endless' loop runs twice for equations, once for other atoms */ + while (TRUE) { + TermList = st_GetUnifier(cont_LeftContext(), sharing_Index(ShIndex), + cont_RightContext(), Atom); + + for ( ; !list_Empty(TermList); TermList = list_Pop(TermList)) { + LIST LitList; + TERM PartnerAtom; + + PartnerAtom = list_First(TermList); + + if (!term_IsVariable(PartnerAtom)) { + LITERAL PartnerLit; + CLAUSE PartnerClause; + + for (LitList = sharing_NAtomDataList(PartnerAtom); + !list_Empty(LitList); LitList = list_Cdr(LitList)) { + PartnerLit = list_Car(LitList); + PartnerClause = clause_LiteralOwningClause(PartnerLit); + + if (clause_LiteralsAreComplementary(PartnerLit,ActLit) && + (clause_Length(GivenCopy)==1 || clause_Length(PartnerClause)==1) && + (clause_GetFlag(GivenCopy,CONCLAUSE) || + clause_GetFlag(PartnerClause,CONCLAUSE)) && + (!ConClause || clause_GetFlag(PartnerClause,CONCLAUSE))) { + SUBST Subst, PartnerSubst; + SYMBOL MaxVar; + int maxdepth; + CLAUSE Resolvent; + + maxdepth = misc_Max(depth, clause_ComputeTermDepth(PartnerClause)); + MaxVar = clause_MaxVar(PartnerClause); + clause_RenameVarsBiggerThan(GivenCopy, MaxVar); + + cont_Check(); + if (!unify_UnifyNoOC(cont_LeftContext(), Atom, + cont_RightContext(), PartnerAtom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_BoundedDepthUnitResolution: Unification failed."); + misc_FinishErrorReport(); + } + subst_ExtractUnifier(cont_LeftContext(), &Subst, + cont_RightContext(), &PartnerSubst); + cont_Reset(); + + if (clause_LiteralIsNegative(PartnerLit)) + Resolvent = inf_ApplyGenRes(ActLit, PartnerLit, Subst, + PartnerSubst, Flags, Precedence); + else + Resolvent = inf_ApplyGenRes(PartnerLit, ActLit, PartnerSubst, + Subst, Flags, Precedence); + + if (clause_ComputeTermDepth(Resolvent) > maxdepth) + clause_Delete(Resolvent); + else { + Result = list_Cons(Resolvent,Result); + } + subst_Delete(Subst); + subst_Delete(PartnerSubst); + } + } + } + } + if (!Swapped && fol_IsEquality(Atom)) { + term_EqualitySwap(Atom); /* Given Clause is a copy */ + Swapped = TRUE; + } else + break; + } /* end of 'endless' loop */ + } + + clause_Delete(GivenCopy); + + return(Result); +} + +static CLAUSE inf_ApplyGeneralFactoring(CLAUSE Clause, NAT i, NAT j, + SUBST Subst, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause an index in the clause, a substitution a + flag store and a precedence. + RETURNS: A new clause obtained from <Clause> by applying <Subst> + and deleting literal <j> keeping literal <i> +***************************************************************/ +{ + CLAUSE NewClause; + + NewClause = clause_Copy(Clause); + clause_ClearFlags(NewClause); + clause_SubstApply(Subst, NewClause); + + clause_DeleteLiteral(NewClause, i, Flags, Precedence); + + list_Delete(clause_ParentClauses(NewClause)); + list_Delete(clause_ParentLiterals(NewClause)); + clause_SetParentLiterals(NewClause,list_Nil()); + clause_SetParentClauses(NewClause,list_Nil()); + + clause_SetDataFromFather(NewClause, Clause, j, Flags, Precedence); + clause_SetFromGeneralFactoring(NewClause); + + clause_AddParentClause(NewClause, clause_Number(Clause)); + clause_AddParentLiteral(NewClause, i); + + clause_NewNumber(NewClause); + + return NewClause; +} + + +LIST inf_GeneralFactoring(CLAUSE GivenClause, BOOL Ordered, BOOL Left, + BOOL Equations, FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, three boolean flags, a flag store and a + precedence. + If <Ordered>=TRUE, this function generates ordered + factoring inferences, otherwise standard factoring + inferences. + If <Left> is FALSE, this function only makes factoring + right inferences, otherwise it also makes factoring left + inferences. + If <Equations>=TRUE, equations are allowed for inferences, + else no inferences with equations are generated. The + default is <Equations>=TRUE. + RETURNS: A list of clauses derivable from <GivenClause> by GF. +***************************************************************/ +{ + LIST Result; + LITERAL ActLit; + int i,j,last; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GeneralFactoring: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (!clause_HasSolvedConstraint(GivenClause)) + return list_Nil(); + + Result = list_Nil(); + + /* Always try Factoring Right inferences */ + last = clause_LastSuccedentLitIndex(GivenClause); + if (!clause_GetFlag(GivenClause,CLAUSESELECT)) { + for (i = clause_FirstSuccedentLitIndex(GivenClause); i <= last; i++) { + ActLit = clause_GetLiteral(GivenClause, i); + if ((!Ordered || clause_LiteralIsMaximal(ActLit)) && + (Equations || !clause_LiteralIsEquality(ActLit))) { + TERM Atom, PartnerAtom; + LITERAL PartnerLit; + Atom = clause_LiteralAtom(ActLit); + for (j = clause_FirstSuccedentLitIndex(GivenClause); j <= last; j++) { + if (i != j) { + PartnerLit = clause_GetLiteral(GivenClause, j); + PartnerAtom = clause_LiteralAtom(PartnerLit); + if ((j>i ||(Ordered && !clause_LiteralIsMaximal(PartnerLit))) && + term_EqualTopSymbols(Atom, PartnerAtom)) { + /* This condition avoids duplicate inferences */ + cont_Check(); + if (unify_UnifyCom(cont_LeftContext(), Atom, PartnerAtom)) { + SUBST mgu; + subst_ExtractUnifierCom(cont_LeftContext(), &mgu); + if (!Ordered || inf_LitMax(GivenClause,i,j,mgu,FALSE, + Flags, Precedence)) + Result = list_Cons(inf_ApplyGeneralFactoring(GivenClause,i,j, + mgu,Flags, + Precedence), + Result); + subst_Delete(mgu); + } + cont_Reset(); + if (fol_IsEquality(Atom) && /* PartnerAtom is equality, too */ + unify_UnifyCom(cont_LeftContext(), + term_SecondArgument(Atom), + term_FirstArgument(PartnerAtom)) && + unify_UnifyCom(cont_LeftContext(), + term_FirstArgument(Atom), + term_SecondArgument(PartnerAtom))) { + SUBST mgu; + subst_ExtractUnifierCom(cont_LeftContext(), &mgu); + if (!Ordered || inf_LitMax(GivenClause,i,j,mgu,FALSE, + Flags, Precedence)) + Result = list_Cons(inf_ApplyGeneralFactoring(GivenClause,i,j, + mgu,Flags, + Precedence), + Result); + subst_Delete(mgu); + } + cont_Reset(); + } + } + } + } + } + } + /* Try Factoring Left inferences only if <Left>==TRUE */ + if (Left) { + last = clause_LastAntecedentLitIndex(GivenClause); + for (i = clause_FirstAntecedentLitIndex(GivenClause); i <= last; i++) { + ActLit = clause_GetLiteral(GivenClause, i); + if ((Equations || !clause_LiteralIsEquality(ActLit)) && + (clause_LiteralGetFlag(ActLit,LITSELECT) || + (!clause_GetFlag(GivenClause,CLAUSESELECT) && + (!Ordered || clause_LiteralIsMaximal(ActLit))))) { + TERM Atom, PartnerAtom; + LITERAL PartnerLit; + Atom = clause_LiteralAtom(ActLit); + for (j = clause_FirstAntecedentLitIndex(GivenClause);j <= last; j++) { + if (i != j) { + PartnerLit = clause_GetLiteral(GivenClause, j); + PartnerAtom = clause_LiteralAtom(PartnerLit); + /* In order to avoid duplicate inferences, we do the following */ + /* somewhat "tricky" test. What we want is something like */ + /* "if (j>i || j wasn't considered within the outer loop) {...} */ + /* This lengthy condition can be transformed into the following */ + /* condition, because only one negative literal is selected. */ + /* This implies that the literal at index j can't be selected. */ + if ((j>i || clause_LiteralGetFlag(ActLit,LITSELECT) || + (Ordered && !clause_LiteralIsMaximal(PartnerLit))) && + term_EqualTopSymbols(Atom, PartnerAtom)) { + PartnerAtom = clause_LiteralAtom(PartnerLit); + cont_Check(); + if (unify_UnifyCom(cont_LeftContext(), Atom, PartnerAtom)) { + SUBST mgu; + subst_ExtractUnifierCom(cont_LeftContext(), &mgu); + if (!Ordered || clause_LiteralGetFlag(ActLit,LITSELECT) || + inf_LitMax(GivenClause,i,j,mgu,FALSE,Flags, Precedence)) + Result = list_Cons(inf_ApplyGeneralFactoring(GivenClause,i,j, + mgu,Flags, + Precedence), + Result); + subst_Delete(mgu); + } + cont_Reset(); + if (fol_IsEquality(Atom) && /* PartnerAtom is equality, too */ + unify_UnifyCom(cont_LeftContext(), + term_SecondArgument(Atom), + term_FirstArgument(PartnerAtom)) && + unify_UnifyCom(cont_LeftContext(), + term_FirstArgument(Atom), + term_SecondArgument(PartnerAtom))) { + SUBST mgu; + subst_ExtractUnifierCom(cont_LeftContext(), &mgu); + if (!Ordered || clause_LiteralGetFlag(ActLit,LITSELECT) || + inf_LitMax(GivenClause,i,j,mgu,FALSE,Flags, Precedence)) + Result = list_Cons(inf_ApplyGeneralFactoring(GivenClause,i,j, + mgu,Flags, + Precedence), + Result); + subst_Delete(mgu); + } + cont_Reset(); + } + } + } + } + } + } + cont_Check(); + + return Result; +} + + +/***************************************************************/ +/* START of code for new Superposition Left rule */ +/***************************************************************/ + + +static LIST inf_GenLitSPLeft(CLAUSE Clause, TERM Left, TERM Right, int i, + SHARED_INDEX ShIndex,BOOL OrdPara, BOOL MaxPara, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause (unshared) with a positive equality literal + at position <i> where <Left> and <Right> are the + arguments of just that literal, two boolean flags, + a flag store and a precedence. + For Ordered Paramodulation and Superposition <Right> + mustn't be greater wrt. the ordering than <Left>. + For Superposition the literal must be strictly maximal. + RETURNS: A list of clauses derivable with the literals owning + clause by Superposition Left wrt. the Index. + MEMORY: The list of clauses is extended, where memory for the + list and the clauses is allocated. +***************************************************************/ +{ + LIST Result, Terms; + +#ifdef CHECK + if (clause_GetFlag(Clause, CLAUSESELECT) || + (OrdPara && + clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause,i)) && + Left == term_SecondArgument(clause_GetLiteralAtom(Clause,i))) || + (MaxPara && + !clause_LiteralGetFlag(clause_GetLiteral(Clause,i), STRICTMAXIMAL))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenLitSPLeft: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Result = list_Nil(); + Terms = st_GetUnifier(cont_LeftContext(), sharing_Index(ShIndex), + cont_RightContext(), Left); + + for ( ; !list_Empty(Terms); Terms = list_Pop(Terms)) { + LIST Lits; + TERM Term; + + Term = (TERM)list_First(Terms); + + if (!term_IsVariable(Term) && !symbol_IsPredicate(term_TopSymbol(Term))) { + + Lits = sharing_GetDataList(Term, ShIndex); + + for ( ; !list_Empty(Lits); Lits = list_Pop(Lits)){ + + LITERAL PartnerLit; + TERM PartnerAtom; + CLAUSE PartnerClause; + int pli; + + PartnerLit = (LITERAL)list_Car(Lits); /* Antecedent Literal ! */ + PartnerAtom = clause_LiteralAtom(PartnerLit); + pli = clause_LiteralGetIndex(PartnerLit); + PartnerClause = clause_LiteralOwningClause(PartnerLit); + + if ((clause_LiteralGetFlag(PartnerLit,LITSELECT) || + (!clause_GetFlag(PartnerClause,CLAUSESELECT) && + (!MaxPara || clause_LiteralIsMaximal(PartnerLit)))) && + clause_LiteralIsNegative(PartnerLit) && + !clause_GetFlag(PartnerClause,NOPARAINTO) && + clause_HasSolvedConstraint(PartnerClause)) { + /* If <PartnerClause> has a solved constraint and <PartnerLit> */ + /* is negative then <PartnerLit> is from the antecedent. */ + + SUBST Subst, PartnerSubst; + TERM NewLeft,NewRight; + SYMBOL PartnerMaxVar; + TERM SupAtom; + + SupAtom = (TERM)NULL; + PartnerMaxVar = clause_MaxVar(PartnerClause); + NewLeft = Left; + clause_RenameVarsBiggerThan(Clause, PartnerMaxVar); + + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(), Left, cont_RightContext(), Term); + subst_ExtractUnifier(cont_LeftContext(), &Subst, + cont_RightContext(), &PartnerSubst); + cont_Reset(); + + if (!MaxPara || + inf_LiteralsMax(Clause, i, Subst, PartnerClause, pli, + PartnerSubst, Flags, Precedence)) { + NewRight = subst_Apply(Subst, term_Copy(Right)); + if (OrdPara && + !clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause,i))) + NewLeft = subst_Apply(Subst, term_Copy(Left)); + if (!OrdPara || + NewLeft == Left || + ord_Compare(NewLeft,NewRight,Flags, Precedence) != ord_SmallerThan()) { + if (!MaxPara || clause_LiteralIsPredicate(PartnerLit)) { + SupAtom = inf_AllTermsRplac(PartnerAtom,Term,NewRight, + PartnerSubst); + } else { + /* Superposition and <PartnerLit> is equality */ + if (clause_LiteralIsOrientedEquality(PartnerLit)) + SupAtom = inf_AllTermsLeftRplac(PartnerAtom,Term,NewRight, + PartnerSubst); + else { + TERM NewPartnerLeft,NewPartnerRight; + NewPartnerLeft = subst_Apply(PartnerSubst, + term_Copy(term_FirstArgument(PartnerAtom))); + NewPartnerRight = subst_Apply(PartnerSubst, + term_Copy(term_SecondArgument(PartnerAtom))); + switch (ord_Compare(NewPartnerLeft,NewPartnerRight, + Flags, Precedence)) { + case ord_SMALLER_THAN: + SupAtom = inf_AllTermsRightRplac(PartnerAtom,Term, + NewRight,PartnerSubst); + break; + case ord_GREATER_THAN: + SupAtom = inf_AllTermsLeftRplac(PartnerAtom,Term, + NewRight,PartnerSubst); + break; + default: + SupAtom = inf_AllTermsRplac(PartnerAtom,Term, + NewRight,PartnerSubst); + } + term_Delete(NewPartnerLeft); + term_Delete(NewPartnerRight); + } + } + + if (SupAtom != NULL) + Result = list_Cons(inf_ApplyGenSuperposition(Clause, i, Subst, + PartnerClause, pli, + PartnerSubst, + SupAtom, FALSE, + OrdPara, MaxPara, + Flags, Precedence), + Result); + } + if (NewLeft != Left) + term_Delete(NewLeft); + term_Delete(NewRight); + } + subst_Delete(Subst); + subst_Delete(PartnerSubst); + } + } + } + } + return Result; +} + + +static LIST inf_GenSPLeftEqToGiven(CLAUSE Clause, int i, BOOL Left, + SHARED_INDEX ShIndex, BOOL OrdPara, + BOOL MaxPara, BOOL Unit, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: An unshared clause, the index of an antecedent + literal that is an equality literal, a boolean + value, a shared index, three boolean flags + controlling inference preconditions, a flag store + and a precedence. + If Left==TRUE then the left argument of the literal is used + otherwise the right argument. + OrdPara and MaxPara control inference conditions. + If <Unit>==TRUE the clause with the maximal, positive + equality must be a unit clause. + RETURNS: A list of clauses derivable from generalized + superposition Left on the + GivenCopy wrt. the Index. See GenSuperpositionLeft + for effects of OrdPara and MaxPara + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result, TermList, ParentList; + int Bottom; + LITERAL Lit; + TERM Atom, Term, PartnerTerm, PartnerEq; + + Result = list_Nil(); + Lit = clause_GetLiteral(Clause,i); /* Is an antecedent Literal ! */ + Atom = clause_LiteralAtom(Lit); + +#ifdef CHECK + if (clause_GetFlag(Clause, NOPARAINTO) || + !clause_LiteralIsEquality(Lit) || + !clause_LiteralIsFromAntecedent(Lit) || + (MaxPara && clause_LiteralIsOrientedEquality(Lit) && !Left) || + (!clause_LiteralGetFlag(clause_GetLiteral(Clause,i),LITSELECT) && + (clause_GetFlag(Clause, CLAUSESELECT) || + (MaxPara && !clause_LiteralIsMaximal(clause_GetLiteral(Clause,i)))))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSPLeftEqToGiven: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Bottom = stack_Bottom(); + if (Left) + sharing_PushOnStack(term_FirstArgument(Atom)); + else + sharing_PushOnStack(term_SecondArgument(Atom)); + + while (!stack_Empty(Bottom)) { + Term = (TERM)stack_PopResult(); + if (!term_IsVariable(Term)) { + /* Superposition into variables is not necessary */ + TermList = st_GetUnifier(cont_LeftContext(), sharing_Index(ShIndex), + cont_RightContext(), Term); + for ( ;!list_Empty(TermList); TermList = list_Pop(TermList)) { + PartnerTerm = (TERM)list_Car(TermList); + for (ParentList = term_SupertermList(PartnerTerm); + !list_Empty(ParentList); ParentList = list_Cdr(ParentList)) { + PartnerEq = (TERM)list_Car(ParentList); + if (fol_IsEquality(PartnerEq)) { + CLAUSE PartnerClause; + LITERAL PartnerLit; + LIST Scl; + int j; + for (Scl = sharing_NAtomDataList(PartnerEq); + !list_Empty(Scl); Scl = list_Cdr(Scl)) { + PartnerLit = (LITERAL)list_Car(Scl); + j = clause_LiteralGetIndex(PartnerLit); + PartnerClause = clause_LiteralOwningClause(PartnerLit); + + if (!clause_GetFlag(PartnerClause,CLAUSESELECT) && + (!MaxPara || + clause_LiteralGetFlag(PartnerLit,STRICTMAXIMAL)) && + (!OrdPara || + PartnerTerm == term_FirstArgument(PartnerEq) || + !clause_LiteralIsOrientedEquality(PartnerLit)) && + clause_LiteralIsPositive(PartnerLit) && + clause_Number(PartnerClause) != clause_Number(Clause) && + (!Unit || clause_Length(PartnerClause) == 1) && + clause_HasSolvedConstraint(PartnerClause)) { + SYMBOL MaxVar; + SUBST Subst, PartnerSubst; + + MaxVar = clause_MaxVar(PartnerClause); + clause_RenameVarsBiggerThan(Clause,MaxVar); + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(), Term, + cont_RightContext(),PartnerTerm); + subst_ExtractUnifier(cont_LeftContext(), &Subst, + cont_RightContext(),&PartnerSubst); + cont_Reset(); + if (!MaxPara || + inf_LiteralsMax(Clause, i, Subst, PartnerClause, j, + PartnerSubst, Flags, Precedence)) { + TERM PartnerLeft,PartnerRight; + BOOL Check, PartnerCheck; + PartnerLeft = PartnerRight = NULL; + PartnerCheck = Check = TRUE; + if (OrdPara && + !clause_LiteralIsOrientedEquality(PartnerLit)) { + /* Check post condition for partner literal */ + if (PartnerTerm == term_FirstArgument(PartnerEq)) + PartnerRight = term_SecondArgument(PartnerEq); + else + PartnerRight = term_FirstArgument(PartnerEq); + PartnerLeft = subst_Apply(PartnerSubst, + term_Copy(PartnerTerm)); + PartnerRight = subst_Apply(PartnerSubst, + term_Copy(PartnerRight)); + PartnerCheck = (ord_Compare(PartnerLeft,PartnerRight, + Flags, Precedence) + != ord_SmallerThan()); + } + if (PartnerCheck && + MaxPara && !clause_LiteralIsOrientedEquality(Lit)) { + /* Check post condition for literal in given clause */ + TERM NewLeft, NewRight; + if (Left) { + NewLeft = term_FirstArgument(Atom); + NewRight = term_SecondArgument(Atom); + } else { + NewLeft = term_SecondArgument(Atom); + NewRight = term_FirstArgument(Atom); + } + NewLeft = subst_Apply(Subst, term_Copy(NewLeft)); + NewRight = subst_Apply(Subst, term_Copy(NewRight)); + Check = (ord_Compare(NewLeft, NewRight, Flags, Precedence) + != ord_SmallerThan()); + term_Delete(NewLeft); + term_Delete(NewRight); + } + if (Check && PartnerCheck) { + /* Make inference only if both tests were successful */ + TERM SupAtom; + SupAtom = NULL; + if (PartnerRight == NULL) { + if (PartnerTerm==term_FirstArgument(PartnerEq)) + PartnerRight = term_SecondArgument(PartnerEq); + else + PartnerRight = term_FirstArgument(PartnerEq); + PartnerRight = subst_Apply(PartnerSubst, + term_Copy(PartnerRight)); + } + if (Left) + SupAtom = inf_AllTermsLeftRplac(Atom, Term, + PartnerRight, Subst); + else + SupAtom = inf_AllTermsRightRplac(Atom, Term, + PartnerRight, Subst); +#ifdef CHECK + if (SupAtom == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSPLeftEqToGiven:"); + misc_ErrorReport(" replacement wasn't possible."); + misc_FinishErrorReport(); + } +#endif + Result = + list_Cons(inf_ApplyGenSuperposition(PartnerClause, j, + PartnerSubst,Clause, + i,Subst,SupAtom, + FALSE,OrdPara, + MaxPara,Flags, + Precedence), + Result); + } + if (PartnerLeft != term_Null()) + term_Delete(PartnerLeft); + if (PartnerRight != term_Null()) + term_Delete(PartnerRight); + } + subst_Delete(Subst); + subst_Delete(PartnerSubst); + } + } + } + } + } + } + } + return Result; +} + + +static LIST inf_GenSPLeftLitToGiven(CLAUSE Clause, int i, TERM Atom, + SHARED_INDEX ShIndex, BOOL OrdPara, + BOOL MaxPara, BOOL Unit, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: An unshared clause, the index of an antecedent + literal that is not an equality literal and its + atom, a shared index, three boolean flags + controlling inference preconditions (see also + inf_GenSuperpositionLeft), a flag store and a + precedence. + RETURNS: A list of clauses derivable from superposition left on the + GivenCopy wrt. the Index. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result, TermList, ParentList; + int Bottom; + LITERAL Lit; + TERM Term, PartnerTerm, PartnerEq; + + Result = list_Nil(); + Lit = clause_GetLiteral(Clause,i); + +#ifdef CHECK + if (clause_LiteralIsEquality(Lit) || !clause_LiteralIsFromAntecedent(Lit)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSPLeftLitToGiven: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Bottom = stack_Bottom(); + sharing_PushListOnStack(term_ArgumentList(Atom)); + + while (!stack_Empty(Bottom)) { + Term = (TERM)stack_PopResult(); + if (!term_IsVariable(Term)) { + /* Superposition into variables is not necessary */ + TermList = st_GetUnifier(cont_LeftContext(), + sharing_Index(ShIndex), + cont_RightContext(), + Term); + for ( ; !list_Empty(TermList); TermList=list_Pop(TermList)) { + PartnerTerm = (TERM)list_Car(TermList); + for (ParentList = term_SupertermList(PartnerTerm); + !list_Empty(ParentList); ParentList = list_Cdr(ParentList)) { + PartnerEq = (TERM)list_Car(ParentList); + if (fol_IsEquality(PartnerEq)) { + CLAUSE PartnerClause; + LITERAL PartnerLit; + TERM PartnerAtom; + LIST Scl; + int j; + for (Scl = sharing_NAtomDataList(PartnerEq); + !list_Empty(Scl); Scl = list_Cdr(Scl)) { + PartnerLit = (LITERAL)list_Car(Scl); + j = clause_LiteralGetIndex(PartnerLit); + PartnerClause = clause_LiteralOwningClause(PartnerLit); + PartnerAtom = clause_LiteralAtom(PartnerLit); + if (!clause_GetFlag(PartnerClause,CLAUSESELECT) && + (!MaxPara || + clause_LiteralGetFlag(PartnerLit,STRICTMAXIMAL)) && + (!OrdPara || + PartnerTerm == term_FirstArgument(PartnerAtom) || + !clause_LiteralIsOrientedEquality(PartnerLit)) && + clause_LiteralIsPositive(PartnerLit) && + clause_Number(PartnerClause) != clause_Number(Clause) && + (!Unit || clause_Length(PartnerClause) == 1) && + clause_HasSolvedConstraint(PartnerClause)) { + SYMBOL MaxVar; + TERM PartnerLeft,PartnerRight; + SUBST Subst, PartnerSubst; + TERM SupAtom; + + SupAtom = (TERM)NULL; + MaxVar = clause_MaxVar(PartnerClause); + clause_RenameVarsBiggerThan(Clause,MaxVar); + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(),Term,cont_RightContext(),PartnerTerm); + subst_ExtractUnifier(cont_LeftContext(),&Subst,cont_RightContext(),&PartnerSubst); + cont_Reset(); + if (!MaxPara || + inf_LiteralsMax(Clause, i, Subst, PartnerClause, j, + PartnerSubst, Flags, Precedence)) { + PartnerLeft = subst_Apply(PartnerSubst, + term_Copy(PartnerTerm)); + if (PartnerTerm == term_FirstArgument(PartnerAtom)) + PartnerRight = subst_Apply(PartnerSubst, + term_Copy(term_SecondArgument(PartnerAtom))); + else + PartnerRight = subst_Apply(PartnerSubst, + term_Copy(term_FirstArgument(PartnerAtom))); + + if (!OrdPara || + clause_LiteralIsOrientedEquality(PartnerLit) || + ord_Compare(PartnerLeft,PartnerRight,Flags, Precedence) + != ord_SmallerThan()) { + SupAtom = inf_AllTermsRplac(Atom,Term,PartnerRight,Subst); +#ifdef CHECK + if (SupAtom == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSPRightLitToGiven:"); + misc_ErrorReport(" replacement wasn't possible."); + misc_FinishErrorReport(); + } +#endif + Result = + list_Cons(inf_ApplyGenSuperposition(PartnerClause, j, + PartnerSubst, Clause, + i, Subst, SupAtom, + FALSE, OrdPara, + MaxPara, Flags, + Precedence), + Result); + + } + term_Delete(PartnerLeft); + term_Delete(PartnerRight); + } + subst_Delete(Subst); + subst_Delete(PartnerSubst); + } + } + } + } + } + } + } + return Result; +} + + +static LIST inf_GenSPLeftToGiven(CLAUSE Clause, int i, SHARED_INDEX ShIndex, + BOOL OrdPara, BOOL MaxPara, BOOL Unit, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: An unshared clause, the index of an antecedent + literal, an index of shared clauses, three boolean + flags for controlling inference preconditions (see + inf_GenSuperpositionLeft), a flag store and a + precedence. + RETURNS: A list of clauses derivable from Superposition Left + on the GivenCopy wrt. the Index. + MEMORY: A list of clauses is produced, where memory for the + list and the clauses is allocated. +***************************************************************/ +{ + TERM Atom; + LIST Result; + +#ifdef CHECK + if (clause_GetFlag(Clause, NOPARAINTO) || + (!clause_LiteralGetFlag(clause_GetLiteral(Clause,i),LITSELECT) && + (clause_GetFlag(Clause, CLAUSESELECT) || + (MaxPara && !clause_LiteralIsMaximal(clause_GetLiteral(Clause,i)))))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSPLeftToGiven: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Result = list_Nil(); + Atom = clause_LiteralAtom(clause_GetLiteral(Clause,i)); + + if (fol_IsEquality(Atom)) { + Result = list_Nconc(inf_GenSPLeftEqToGiven(Clause,i, TRUE,ShIndex, OrdPara, + MaxPara, Unit, Flags,Precedence), + Result); + if (!MaxPara || + !clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause,i))) + /* For SPm and OPm always try other direction, for SpR try it */ + /* only if the literal is not oriented. */ + Result = list_Nconc(inf_GenSPLeftEqToGiven(Clause,i,FALSE,ShIndex,OrdPara, + MaxPara,Unit,Flags,Precedence), + Result); + } else + Result = list_Nconc(inf_GenSPLeftLitToGiven(Clause,i,Atom,ShIndex,OrdPara, + MaxPara,Unit,Flags,Precedence), + Result); + + return Result; +} + + +LIST inf_GenSuperpositionLeft(CLAUSE GivenClause, SHARED_INDEX ShIndex, + BOOL OrdPara, BOOL MaxPara, BOOL Unit, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause and an Index, usually the WorkedOffIndex, + two boolean flags for controlling inference + preconditions, a flag store and a precedence. + RETURNS: A list of clauses derivable from the Givenclause by + one of the following inference rules wrt. the Index: + + OrdPara=TRUE, MaxPara=TRUE + -> Superposition Left + + OrdPara=TRUE, MaxPara=FALSE + -> ordered Paramodulation + + OrdPara=FALSE, MaxPara=FALSE + -> simple Paramodulation + + OrdPara=FALSE, MaxPara=TRUE + -> not defined + + If <Unit>==TRUE the clause with the maximal equality + additionally must be a unit clause. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result; + TERM Atom; + CLAUSE Copy; + int i, n; + LITERAL ActLit; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSuperpositionLeft: Illegal input."); + misc_FinishErrorReport(); + } + if (!OrdPara && MaxPara) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GenSuperpositionLeft: Illegal inference rule selection,"); + misc_ErrorReport("\n OrdPara=FALSE & MaxPara=TRUE."); + misc_FinishErrorReport(); + } +#endif + + Result = list_Nil(); + + if (!clause_HasSolvedConstraint(GivenClause)) + return Result; + + Copy = clause_Copy(GivenClause); + n = clause_LastSuccedentLitIndex(Copy); + + if (!clause_GetFlag(Copy, CLAUSESELECT) && + (!Unit || clause_Length(Copy) == 1)) { + for (i = clause_FirstSuccedentLitIndex(Copy); i <= n; i++) { + ActLit = clause_GetLiteral(Copy, i); + Atom = clause_LiteralSignedAtom(ActLit); + + if (fol_IsEquality(Atom) && + (!MaxPara || + clause_LiteralGetFlag(ActLit,STRICTMAXIMAL))) { + + Result = + list_Nconc(inf_GenLitSPLeft(Copy, term_FirstArgument(Atom), + term_SecondArgument(Atom), i, ShIndex, + OrdPara, MaxPara, Flags, Precedence), + Result); + if (!OrdPara || !clause_LiteralIsOrientedEquality(ActLit)) + /* For SPm always try the other direction, for OPm and SpL */ + /* only try it if the literal is not oriented. */ + Result = + list_Nconc(inf_GenLitSPLeft(Copy, term_SecondArgument(Atom), + term_FirstArgument(Atom), i, ShIndex, + OrdPara, MaxPara, Flags, Precedence), + Result); + } + } + } + + n = clause_LastAntecedentLitIndex(Copy); + if (!clause_GetFlag(Copy,NOPARAINTO)) { + for (i = clause_FirstAntecedentLitIndex(Copy); i <= n; i++) { + ActLit = clause_GetLiteral(Copy, i); + + if (clause_LiteralGetFlag(ActLit, LITSELECT) || + (!clause_GetFlag(Copy, CLAUSESELECT) && + (!MaxPara || clause_LiteralIsMaximal(ActLit)))) + Result = list_Nconc(inf_GenSPLeftToGiven(Copy, i, ShIndex, OrdPara, + MaxPara,Unit,Flags,Precedence), + Result); + } + } + clause_Delete(Copy); + + return(Result); +} + + + +LIST inf_ApplyDefinition(PROOFSEARCH Search, CLAUSE Clause, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A proof search object, a clause, a flag store and a + precedence. + RETURNS: A list of clauses derivable from the given clause by + applying the (potential) definitions in <Search>. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result, Defs; + DEF Def; + + Result = list_Nil(); + for (Defs=prfs_Definitions(Search); !list_Empty(Defs); Defs=list_Cdr(Defs)) { + Def = (DEF)list_Car(Defs); + Result = list_Nconc(def_ApplyDefToClauseOnce(Def, Clause, Flags, Precedence), + Result); + } + return Result; +} + + +/************************************************************** + block with hyperresolution code starts here +***************************************************************/ + +typedef struct { + LITERAL NucleusLit; + LITERAL ElectronLit; + SUBST ElectronSubst; +} INF_MAPNODE, *INF_MAPITEM; + + +static void inf_CopyHyperElectron(CLAUSE Clause, SUBST Subst2, SUBST Subst1, + int PLitInd, LIST* Constraint, + LIST* Succedent) +/************************************************************** + INPUT: An electron clause, a substitution, an index of a + succedent literal in this clause (the matched one), + and two lists by reference. + RETURNS: Nothing. + EFFECTS: The constraint and succedent literals are copied into + the corresponding lists except for the literal with + the given index. The composition <Subst2> ° <Subst1> + is applied to all copied literals. + The antecedent of the electron clause is empty, so + there's no need for a third list by reference. +***************************************************************/ +{ + TERM Atom; + int n, lc, j; + +#ifdef CHECK + if (clause_NumOfAnteLits(Clause) != 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_CopyHyperElectron: Electron contains antecedent literals."); + misc_FinishErrorReport(); + } +#endif + + n = clause_LastSuccedentLitIndex(Clause); + lc = clause_LastConstraintLitIndex(Clause); + + for (j = clause_FirstConstraintLitIndex(Clause); j <= n; j++) { + if (j != PLitInd) { + Atom = subst_Apply(Subst1, term_Copy(clause_GetLiteralAtom(Clause, j))); + Atom = subst_Apply(Subst2, Atom); + if (j <= lc) + *Constraint = list_Cons(Atom, *Constraint); + else /* Literal must be from succedent */ + *Succedent = list_Cons(Atom, *Succedent); + } + } +} + + +static CLAUSE inf_BuildHyperResolvent(CLAUSE Nucleus, SUBST Subst, + LIST FoundMap, BOOL StrictlyMaximal, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause <Nucleus> with solved sort constraint, + the substitution <Subst> for <Nucleus>, a mapping + <FoundMap> of literals of already found partner + clauses, a boolean flag indicating whether this is + a ordered or a standard hyper resolution inference + a flag store and a precedence. + RETURNS: The newly created hyper resolvent. +***************************************************************/ +{ + CLAUSE NewClause; + LIST Constraint, Succedent, Parents, ParentNum, ParentLits, Scan; + int i, bound, Depth; + LITERAL Lit; + SUBST ESubst; + INF_MAPITEM MapItem; + + Parents = list_List(Nucleus); /* parent clauses */ + ParentNum = list_Nil(); /* parent clause numbers */ + ParentLits = list_Nil(); /* literal indices */ + Constraint = Succedent = list_Nil(); /* literals of the new clause */ + + /* Get constraint literals from nucleus */ + bound = clause_LastConstraintLitIndex(Nucleus); + for (i = clause_FirstConstraintLitIndex(Nucleus); i <= bound; i++) + Constraint = + list_Cons(subst_Apply(Subst,term_Copy(clause_GetLiteralAtom(Nucleus,i))), + Constraint); + /* Get succedent literals from nucleus */ + bound = clause_LastSuccedentLitIndex(Nucleus); + for (i = clause_FirstSuccedentLitIndex(Nucleus); i <= bound; i++) + Succedent = + list_Cons(subst_Apply(Subst,term_Copy(clause_GetLiteralAtom(Nucleus,i))), + Succedent); + + /* Now get the remaining data for the resolvent */ + Depth = clause_Depth(Nucleus); + bound = clause_LastAntecedentLitIndex(Nucleus); + for (i = clause_FirstAntecedentLitIndex(Nucleus); i <= bound; i++) { + /* Search <FoundMap> for the nucleus literal with index <i> */ + Lit = clause_GetLiteral(Nucleus, i); + for (Scan = FoundMap, MapItem = NULL; !list_Empty(Scan); + Scan = list_Cdr(Scan)) { + MapItem = list_Car(Scan); + if (MapItem->NucleusLit == Lit) + break; + } + + if (MapItem == NULL || MapItem->NucleusLit != Lit) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_BuildHyperResolvent: Map entry not found."); + misc_FinishErrorReport(); + } + + Lit = MapItem->ElectronLit; + NewClause = clause_LiteralOwningClause(Lit); + ESubst = MapItem->ElectronSubst; + + Depth = misc_Max(Depth, clause_Depth(NewClause)); + Parents = list_Cons(NewClause, Parents); + ParentNum = list_Cons((POINTER) clause_Number(Nucleus), ParentNum); + ParentLits = list_Cons((POINTER) i, ParentLits); + ParentNum = list_Cons((POINTER) clause_Number(NewClause), ParentNum); + ParentLits = list_Cons((POINTER) clause_LiteralGetIndex(Lit), ParentLits); + + /* Get the remaining constraint and succedent literals from electron */ + inf_CopyHyperElectron(NewClause,Subst,ESubst,clause_LiteralGetIndex(Lit), + &Constraint, &Succedent); + } + + /* create new clause and set clause data */ + NewClause = clause_Create(Constraint, list_Nil(), Succedent, Flags,Precedence); + + if (StrictlyMaximal) + clause_SetFromOrderedHyperResolution(NewClause); + else + clause_SetFromSimpleHyperResolution(NewClause); + + clause_SetDepth(NewClause, Depth + 1); + + clause_SetSplitDataFromList(NewClause, Parents); + + clause_SetParentClauses(NewClause, list_NReverse(ParentNum)); + clause_SetParentLiterals(NewClause, list_NReverse(ParentLits)); + + /* clean up */ + list_Delete(Parents); + list_Delete(Constraint); + list_Delete(Succedent); + + return NewClause; +} + + +static LIST inf_GetHyperResolutionPartnerLits(TERM Atom, SHARED_INDEX Index, + BOOL StrictlyMaximal) +/************************************************************** + INPUT: An atom, a clause index, and a boolean flag. + RETURNS: A list of literals from purely positive clauses + from the index where either <StrictlyMaximal> is + false or the literals are strictly maximal in their + respective clauses. +***************************************************************/ +{ + LIST Result, TermList, LitScan; + LITERAL NextLit; + CLAUSE Clause; + +#ifdef CHECK + if (!term_IsAtom(Atom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GetHyperResolutionPartnerLits: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Result = list_Nil(); + TermList = st_GetUnifier(cont_LeftContext(), sharing_Index(Index), + cont_RightContext(), Atom); + + for (; !list_Empty(TermList); TermList = list_Pop(TermList)) { + if (!term_IsVariable(list_Car(TermList))) { + for (LitScan = sharing_NAtomDataList(list_Car(TermList)); + !list_Empty(LitScan); + LitScan = list_Cdr(LitScan)) { + NextLit = list_Car(LitScan); + Clause = clause_LiteralOwningClause(NextLit); + if (clause_LiteralIsFromSuccedent(NextLit) && + (!StrictlyMaximal || clause_LiteralGetFlag(NextLit, STRICTMAXIMAL)) && + clause_HasSolvedConstraint(Clause) && + clause_HasEmptyAntecedent(Clause)) + Result = list_Cons(NextLit, Result); + } + } + } + return Result; +} + +static LIST inf_HyperResolvents(CLAUSE Clause, SUBST Subst, LIST Restlits, + int GlobalMaxVar, LIST FoundMap, + BOOL StrictlyMaximal, SHARED_INDEX Index, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A nucleus <Clause> where the sort constraint is + solved, + a substitution, that has to be applied to the + nucleus, + a list <Restlits> of antecedent literals for which + a partner clause is searched, + a list <FoundMap> of map items (n,e,s), where + n is an antecedent literal from the nucleus, + e is a positive literal from an electron clause, + that is unifiable with n and s is a substitution + that has to be applied to the electron clause, + a flag store and + a precedence. + A main invariant of our algorithm is that all involved + clauses are pairwise variable disjoint. For that reason + we need, when building the resolvent, only apply the electron + specific substitution and the composed substitution <Subst> + to the electron clauses, and only <Subst> to the nucleus clause. + RETURNS: The list of hyper-resolvents. +***************************************************************/ +{ + LITERAL Lit, PLit; + + if (list_Empty(Restlits)) { + /* This case stops the recursion */ + LIST Scan; + INF_MAPITEM MapItem; + + /* A posteriori test for the electron literals */ + if (StrictlyMaximal) { /* only for ordered hyper resolution */ + for (Scan = FoundMap; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + MapItem = list_Car(Scan); + Lit = MapItem->ElectronLit; + if (!inf_LitMaxWith2Subst(clause_LiteralOwningClause(Lit), + clause_LiteralGetIndex(Lit), -1, Subst, + MapItem->ElectronSubst,TRUE,Flags,Precedence)) + return list_Nil(); + } + } + /* Build the resolvent */ + return list_List(inf_BuildHyperResolvent(Clause, Subst, FoundMap, + StrictlyMaximal,Flags,Precedence)); + } + else { + CLAUSE PartnerCopy; + LIST Result, NextLits; + TERM AtomCopy; + SUBST NewSubst, RightSubst, HelpSubst; + SYMBOL NewMaxVar; + int PLitInd; + BOOL Swapped; + INF_MAPNODE MapNode; + + Result = list_Nil(); + Restlits = clause_MoveBestLiteralToFront(list_Copy(Restlits), Subst, + GlobalMaxVar, + clause_HyperLiteralIsBetter); + Lit = list_Car(Restlits); + Restlits = list_Pop(Restlits); + AtomCopy = subst_Apply(Subst, term_Copy(clause_LiteralAtom(Lit))); + + Swapped = FALSE; + + /* The 'endless' loop may run twice for equations, once for other atoms */ + while (TRUE) { + NextLits = inf_GetHyperResolutionPartnerLits(AtomCopy,Index, + StrictlyMaximal); + + for ( ; !list_Empty(NextLits); NextLits = list_Pop(NextLits)) { + + PLit = list_Car(NextLits); + PLitInd = clause_LiteralGetIndex(PLit); + PartnerCopy = clause_Copy(clause_LiteralOwningClause(PLit)); + + clause_RenameVarsBiggerThan(PartnerCopy, GlobalMaxVar); + PLit = clause_GetLiteral(PartnerCopy, PLitInd); + + NewMaxVar = term_MaxVar(clause_LiteralAtom(PLit)); + NewMaxVar = symbol_GreaterVariable(GlobalMaxVar, NewMaxVar) ? + GlobalMaxVar : NewMaxVar; + + cont_Check(); + if (!unify_UnifyNoOC(cont_LeftContext(), AtomCopy, cont_RightContext(), + clause_LiteralAtom(PLit))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_HyperResolvents: Unification failed."); + misc_FinishErrorReport(); + } + subst_ExtractUnifier(cont_LeftContext(), &NewSubst, + cont_RightContext(), &RightSubst); + cont_Reset(); + + HelpSubst = NewSubst; + NewSubst = subst_Compose(NewSubst, subst_Copy(Subst)); + subst_Delete(HelpSubst); + + MapNode.NucleusLit = Lit; + MapNode.ElectronLit = PLit; + MapNode.ElectronSubst = RightSubst; + FoundMap = list_Cons(&MapNode, FoundMap); + + Result = list_Nconc(inf_HyperResolvents(Clause, NewSubst, Restlits, + NewMaxVar, FoundMap, + StrictlyMaximal, Index, Flags, + Precedence), + Result); + + subst_Delete(NewSubst); + subst_Delete(RightSubst); + clause_Delete(PartnerCopy); + FoundMap = list_Pop(FoundMap); + } + if (!Swapped && fol_IsEquality(AtomCopy)) { + term_EqualitySwap(AtomCopy); + Swapped = TRUE; + } else + break; + } /* end of 'endless' loop */ + + list_Delete(Restlits); + term_Delete(AtomCopy); + + return Result; + } +} + + +static LIST inf_GetAntecedentLiterals(CLAUSE Clause) +/************************************************************** + INPUT: A clause + RETURNS: The list of all antecedent literals of the clause. +***************************************************************/ +{ + int lc, i; + LIST Result; + + Result = list_Nil(); + lc = clause_LastAntecedentLitIndex(Clause); + for (i = clause_FirstAntecedentLitIndex(Clause); i <= lc ; i++) { + Result = list_Cons(clause_GetLiteral(Clause, i), Result); + } + return Result; +} + + +static LIST inf_ForwardHyperResolution(CLAUSE GivenClause, SHARED_INDEX Index, + BOOL StrictlyMaximal, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause with an solved sort constraint, an 'Index' + of clauses, a boolean flag, a flag store and a + precedence. + RETURNS: A list of clauses inferred from <GivenClause> by + hyper resolution wrt. the index. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result, RestLits; +; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_ForwardHyperResolution: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (clause_HasEmptyAntecedent(GivenClause)) + return list_Nil(); + + Result = list_Nil(); + + /* Build up list of all antecedent literals. */ + RestLits = inf_GetAntecedentLiterals(GivenClause); + + Result = list_Nconc(inf_HyperResolvents(GivenClause, subst_Nil(), + RestLits,clause_MaxVar(GivenClause), + list_Nil(),StrictlyMaximal,Index, + Flags, Precedence), + Result); + list_Delete(RestLits); + + return Result; +} + + +static LIST inf_BackwardHyperResolution(CLAUSE Electron, SHARED_INDEX Index, + BOOL StrictlyMaximal, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause with an solved sort constraint, + an 'Index' of clauses, a boolean flag, a flag store, + and a precedence. + RETURNS: A list of clauses inferred by hyper resolution + wrt. the index with <Electron> as an electron. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + CLAUSE ElectronCopy; + LIST Result; + int i, ls; + + if (!clause_HasEmptyAntecedent(Electron) || + clause_HasEmptySuccedent(Electron)) + return list_Nil(); + + Result = list_Nil(); + + ElectronCopy = clause_Copy(Electron); + + /* Search succedent literal in <Electron> */ + ls = clause_LastSuccedentLitIndex(ElectronCopy); + for (i = clause_FirstSuccedentLitIndex(Electron); i <= ls; i++) { + LITERAL ElecLit; + TERM ElecAtom; + + ElecLit = clause_GetLiteral(ElectronCopy, i); + ElecAtom = clause_LiteralAtom(ElecLit); + + if (!StrictlyMaximal || clause_LiteralGetFlag(ElecLit, STRICTMAXIMAL)) { + LIST CandAtoms; + BOOL Swapped; + + Swapped = FALSE; + + /* The 'endless' loop may run twice for equations, once for other atoms */ + while (TRUE) { + /* Get unifiable antecedent literals in nucleus */ + CandAtoms = st_GetUnifier(cont_LeftContext(), sharing_Index(Index), + cont_RightContext(), ElecAtom); + + for ( ; !list_Empty(CandAtoms); CandAtoms = list_Pop(CandAtoms)) { + if (!term_IsVariable(list_Car(CandAtoms))) { + LIST CandLits; + + CandLits = sharing_NAtomDataList(list_Car(CandAtoms)); + + for (; !list_Empty(CandLits); CandLits = list_Cdr(CandLits)) { + LITERAL NucLit; + TERM NucAtom; + CLAUSE Nucleus; + + NucLit = list_Car(CandLits); + NucAtom = clause_LiteralAtom(NucLit); + Nucleus = clause_LiteralOwningClause(NucLit); + + if (clause_LiteralIsFromAntecedent(NucLit) && + clause_HasSolvedConstraint(Nucleus)) { + LIST FoundMap, RestLits; + SUBST LeftSubst, RightSubst; + SYMBOL GlobalMaxVar, MaxVar; + INF_MAPNODE MapNode; + + GlobalMaxVar = clause_MaxVar(Nucleus); + clause_RenameVarsBiggerThan(ElectronCopy, GlobalMaxVar); + MaxVar = clause_SearchMaxVar(ElectronCopy); + GlobalMaxVar = symbol_GreaterVariable(GlobalMaxVar, MaxVar) ? + GlobalMaxVar : MaxVar; + /* Now ElecLit is renamed, too */ + + RestLits = inf_GetAntecedentLiterals(Nucleus); + RestLits = list_PointerDeleteElement(RestLits, NucLit); + + /* Get unifier */ + cont_Check(); + if (!unify_UnifyNoOC(cont_LeftContext(), NucAtom, + cont_RightContext(), ElecAtom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_BackwardHyperResolution: Unification failed."); + misc_FinishErrorReport(); + } + subst_ExtractUnifier(cont_LeftContext(), &LeftSubst, + cont_RightContext(), &RightSubst); + cont_Reset(); + + MapNode.NucleusLit = NucLit; + MapNode.ElectronLit = ElecLit; + MapNode.ElectronSubst = RightSubst; + FoundMap = list_List(&MapNode); + + Result = list_Nconc(inf_HyperResolvents(Nucleus, LeftSubst, + RestLits, GlobalMaxVar, + FoundMap,StrictlyMaximal, + Index, Flags,Precedence), + Result); + + /* clean up */ + subst_Delete(LeftSubst); + subst_Delete(RightSubst); + list_Delete(RestLits); + list_Free(FoundMap); + } /* if a nucleus has been found */ + } /* for all nucleus candidate literals */ + } /* if term is atom */ + } /* for all nucleus candidate atoms */ + if (!Swapped && fol_IsEquality(ElecAtom)) { + term_EqualitySwap(ElecAtom); /* Atom is from copied clause */ + Swapped = TRUE; + } else + break; + } /* end of 'endless' loop */ + } /* for all lits usable in electron for hyper resolution */ + } /* for all lits in succedent */ + clause_Delete(ElectronCopy); + + return Result; +} + + +LIST inf_GeneralHyperResolution(CLAUSE GivenClause, SHARED_INDEX Index, + BOOL Ordered, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, an 'Index' of clauses, a boolean flag, + a flag store and a precedence. + RETURNS: A list of clauses inferred by + (ordered) hyper resolution wrt. the index. + If <Ordered>=TRUE then ordered hyper resolution + inferences are made, else standard hyper resolution + inferences. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result; + + Result = list_Nil(); + if (clause_HasSolvedConstraint(GivenClause)) { + Result = inf_ForwardHyperResolution(GivenClause, Index, Ordered, + Flags, Precedence); + Result = list_Nconc(inf_BackwardHyperResolution(GivenClause, Index, Ordered, + Flags, Precedence), + Result); + } + return Result; +} + + +LIST inf_DerivableClauses(PROOFSEARCH Search, CLAUSE GivenClause) +/************************************************************** + INPUT: A clause and an Index, usually the WorkedOffIndex. + RETURNS: A list of clauses derivable from 'GivenClause' wrt index. + EFFECT: Allocates memory for the clauselistnodes and new clauses. +***************************************************************/ +{ + LIST ListOfDerivedClauses; + SHARED_INDEX ShIndex; + SORTTHEORY Dynamic; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_DerivableClauses: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + ListOfDerivedClauses = list_Nil(); + ShIndex = prfs_WorkedOffSharingIndex(Search); + Dynamic = prfs_DynamicSortTheory(Search); + + if (Dynamic && !clause_HasSolvedConstraint(GivenClause)) { + + if (clause_HasTermSortConstraintLits(GivenClause)) { + if (flag_GetFlagValue(Flags, flag_ISOR)) + ListOfDerivedClauses = + list_Nconc(inf_ForwardSortResolution(GivenClause, + sort_TheoryIndex(Dynamic), + Dynamic, FALSE, Flags,Precedence), + ListOfDerivedClauses); + } + else + if (flag_GetFlagValue(Flags, flag_IEMS)) + ListOfDerivedClauses = + list_Nconc(inf_ForwardEmptySort(GivenClause, + sort_TheoryIndex(Dynamic), Dynamic, + FALSE, Flags, Precedence), + ListOfDerivedClauses); + } else { /* Given with solved Constraint! */ + + if (Dynamic && flag_GetFlagValue(Flags, flag_IEMS)) + ListOfDerivedClauses = + list_Nconc(inf_BackwardEmptySort(GivenClause, sharing_Index(ShIndex), + Dynamic, FALSE, Flags, Precedence), + ListOfDerivedClauses); + + if (Dynamic && flag_GetFlagValue(Flags, flag_ISOR)) + ListOfDerivedClauses = + list_Nconc(inf_BackwardSortResolution(GivenClause, + sharing_Index(ShIndex), Dynamic, + FALSE, Flags, Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_IEQR)) + ListOfDerivedClauses = + list_Nconc(inf_EqualityResolution(GivenClause, TRUE, Flags, Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_IERR)) + ListOfDerivedClauses = + list_Nconc(inf_EqualityResolution(GivenClause, FALSE, Flags, Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_IMPM)) + ListOfDerivedClauses = + list_Nconc(inf_MergingParamodulation(GivenClause, ShIndex, Flags, + Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_IEQF)) + ListOfDerivedClauses = + list_Nconc(inf_EqualityFactoring(GivenClause,Flags, Precedence), + ListOfDerivedClauses); + + switch (flag_GetFlagValue(Flags, flag_IOFC)) { + case flag_FACTORINGOFF: + break; /* Do nothing */ + case flag_FACTORINGONLYRIGHT: + ListOfDerivedClauses = + list_Nconc(inf_GeneralFactoring(GivenClause, TRUE, FALSE,TRUE, Flags, + Precedence), + ListOfDerivedClauses); + break; + case flag_FACTORINGRIGHTANDLEFT: + ListOfDerivedClauses = + list_Nconc(inf_GeneralFactoring(GivenClause, TRUE, TRUE, TRUE, Flags, + Precedence), + ListOfDerivedClauses); + break; + default: + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Flag \"IOFC\" has invalid value.\n"); + misc_FinishUserErrorReport(); + } + + if (flag_GetFlagValue(Flags, flag_ISFC)) + ListOfDerivedClauses = + list_Nconc(inf_GeneralFactoring(GivenClause, FALSE, TRUE, TRUE, Flags, + Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_ISPR)) + ListOfDerivedClauses = + list_Nconc(inf_SuperpositionRight(GivenClause,ShIndex,Flags,Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_ISPM)) + ListOfDerivedClauses = + list_Nconc(inf_Paramodulation(GivenClause, ShIndex, Flags, Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_IOPM)) + ListOfDerivedClauses = + list_Nconc(inf_OrderedParamodulation(GivenClause, ShIndex, Flags, + Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_ISPL)) + ListOfDerivedClauses = + list_Nconc(inf_SuperpositionLeft(GivenClause, ShIndex, Flags,Precedence), + ListOfDerivedClauses); + + switch (flag_GetFlagValue(Flags, flag_IORE)) { + case flag_ORDEREDRESOLUTIONOFF: + break; /* Do nothing */ + case flag_ORDEREDRESOLUTIONNOEQUATIONS: /* no equations */ + ListOfDerivedClauses = + list_Nconc(inf_GeneralResolution(GivenClause,ShIndex,TRUE,FALSE,Flags, + Precedence), + ListOfDerivedClauses); + break; + + case flag_ORDEREDRESOLUTIONWITHEQUATIONS: /* allow equations */ + ListOfDerivedClauses = + list_Nconc(inf_GeneralResolution(GivenClause,ShIndex,TRUE,TRUE, Flags, + Precedence), + ListOfDerivedClauses); + break; + default: + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Flag \"IORE\" has invalid value.\n"); + misc_FinishUserErrorReport(); + } + + + switch (flag_GetFlagValue(Flags, flag_ISRE)) { + case flag_STANDARDRESOLUTIONOFF: + break; /* Do nothing */ + case flag_STANDARDRESOLUTIONNOEQUATIONS: /* no equations */ + ListOfDerivedClauses = + list_Nconc(inf_GeneralResolution(GivenClause,ShIndex,FALSE,FALSE,Flags, + Precedence), + ListOfDerivedClauses); + break; + case flag_STANDARDRESOLUTIONWITHEQUATIONS: /* allow equations */ + ListOfDerivedClauses = + list_Nconc(inf_GeneralResolution(GivenClause,ShIndex,FALSE,TRUE,Flags, + Precedence), + ListOfDerivedClauses); + break; + default: + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error: Flag \"ISRE\" has invalid value.\n"); + misc_FinishUserErrorReport(); + } + + if (flag_GetFlagValue(Flags, flag_IUNR)) + ListOfDerivedClauses = + list_Nconc(inf_UnitResolution(GivenClause, ShIndex, FALSE, + Flags, Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_IBUR)) + ListOfDerivedClauses = + list_Nconc(inf_BoundedDepthUnitResolution(GivenClause,ShIndex,FALSE, + Flags, Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_ISHY)) + ListOfDerivedClauses = + list_Nconc(inf_GeneralHyperResolution(GivenClause,ShIndex,FALSE,Flags, + Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_IOHY)) + ListOfDerivedClauses = + list_Nconc(inf_GeneralHyperResolution(GivenClause,ShIndex,TRUE,Flags, + Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_IURR)) + ListOfDerivedClauses = + list_Nconc(inf_URResolution(GivenClause, ShIndex, Flags, Precedence), + ListOfDerivedClauses); + + if (flag_GetFlagValue(Flags, flag_IDEF)) + ListOfDerivedClauses = + list_Nconc(inf_ApplyDefinition(Search, GivenClause, Flags, Precedence), + ListOfDerivedClauses); + } + + return ListOfDerivedClauses; +} diff --git a/test/spass/rules-inf.h b/test/spass/rules-inf.h new file mode 100644 index 0000000000000000000000000000000000000000..d900bc5d6d06237a7c4d4db59fbd50f16aeea0de --- /dev/null +++ b/test/spass/rules-inf.h @@ -0,0 +1,165 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INFERENCE RULES * */ +/* * * */ +/* * $Module: INFRULES * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _INFRULES_ +#define _INFRULES_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "search.h" +#include "rules-split.h" +#include "rules-sort.h" +#include "rules-ur.h" +#include "subst.h" +#include "unify.h" +#include "st.h" +#include "defs.h" + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +LIST inf_DerivableClauses(PROOFSEARCH, CLAUSE); + +LIST inf_EqualityResolution(CLAUSE, BOOL, FLAGSTORE, PRECEDENCE); +LIST inf_EqualityFactoring(CLAUSE, FLAGSTORE, PRECEDENCE); + +LIST inf_MergingParamodulation(CLAUSE, SHARED_INDEX, FLAGSTORE, PRECEDENCE); + +LIST inf_GenSuperpositionLeft(CLAUSE,SHARED_INDEX,BOOL,BOOL,BOOL,FLAGSTORE, PRECEDENCE); +LIST inf_GenSuperpositionRight(CLAUSE,SHARED_INDEX,BOOL,BOOL,BOOL,FLAGSTORE, PRECEDENCE); + +LIST inf_BoundedDepthUnitResolution(CLAUSE, SHARED_INDEX, BOOL, FLAGSTORE, PRECEDENCE); +LIST inf_UnitResolution(CLAUSE, SHARED_INDEX, BOOL, FLAGSTORE, PRECEDENCE); +LIST inf_GeneralResolution(CLAUSE, SHARED_INDEX, BOOL, BOOL, FLAGSTORE, PRECEDENCE); + +BOOL inf_HyperLiteralIsBetter(LITERAL, NAT, LITERAL, NAT); +LIST inf_GeneralHyperResolution(CLAUSE, SHARED_INDEX, BOOL, FLAGSTORE, PRECEDENCE); + +LIST inf_GeneralFactoring(CLAUSE, BOOL, BOOL, BOOL, FLAGSTORE, PRECEDENCE); + +LIST inf_ApplyDefinition(PROOFSEARCH, CLAUSE, FLAGSTORE, PRECEDENCE); + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +static __inline__ LIST inf_Paramodulation(CLAUSE GivenClause, + SHARED_INDEX ShIndex, + FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, an Index, usually the WorkedOffIndex, a + flag store and a precedence. + RETURNS: A list of clauses derivable from the GivenClause by + paramodulation wrt. the Index. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + return list_Nconc(inf_GenSuperpositionLeft(GivenClause, ShIndex, FALSE, + FALSE, FALSE, Flags, Precedence), + inf_GenSuperpositionRight(GivenClause, ShIndex, FALSE, + FALSE, FALSE, Flags, Precedence)); +} + +static __inline__ LIST inf_OrderedParamodulation(CLAUSE GivenClause, + SHARED_INDEX ShIndex, + FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, an Index, usually the WorkedOffIndex, a + flag store and a precedence. + RETURNS: A list of clauses derivable from the Givenclause by + ordered paramodulation wrt. the Index. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + return list_Nconc(inf_GenSuperpositionLeft(GivenClause, ShIndex, TRUE, + FALSE, FALSE, Flags, Precedence), + inf_GenSuperpositionRight(GivenClause, ShIndex, TRUE, + FALSE, FALSE, Flags, Precedence)); +} + +static __inline__ LIST inf_SuperpositionLeft(CLAUSE GivenClause, + SHARED_INDEX ShIndex, + FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, an Index, usually the WorkedOffIndex, a + flag store, and a precedence. + RETURNS: A list of clauses derivable from the Givenclause by + superposition left wrt. the Index. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + return inf_GenSuperpositionLeft(GivenClause,ShIndex,TRUE,TRUE,FALSE,Flags, Precedence); +} + +static __inline__ LIST inf_SuperpositionRight(CLAUSE GivenClause, + SHARED_INDEX ShIndex, + FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, an Index, usually the WorkedOffIndex, a + flag store and a precedence. + RETURNS: A list of clauses derivable from the Givenclause by + superposition right wrt. the Index. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + return inf_GenSuperpositionRight(GivenClause,ShIndex,TRUE,TRUE,FALSE,Flags, Precedence); +} + + +#endif + diff --git a/test/spass/rules-red.c b/test/spass/rules-red.c new file mode 100644 index 0000000000000000000000000000000000000000..609b3cf9c18ed3ca144e4c4d223bd3d883792f48 --- /dev/null +++ b/test/spass/rules-red.c @@ -0,0 +1,4508 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * REDUCTION RULES * */ +/* * * */ +/* * $Module: REDRULES * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "rules-red.h" + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * Globals * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* Needed for term stamping in red_RewriteRedUnitClause */ +static NAT red_STAMPID; + +const NAT red_USABLE = 1; +const NAT red_WORKEDOFF = 2; +const NAT red_ALL = 3; + + +/**************************************************************/ +/* FUNTION PROTOTYPES */ +/**************************************************************/ + +static BOOL red_SortSimplification(SORTTHEORY, CLAUSE, NAT, BOOL, FLAGSTORE, + PRECEDENCE, CLAUSE*); +static BOOL red_SelectedStaticReductions(PROOFSEARCH, CLAUSE*, CLAUSE*, LIST*, + NAT); + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * Functions * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + + +static void red_HandleRedundantIndexedClauses(PROOFSEARCH Search, LIST Blocked, + CLAUSE RedClause) +/********************************************************* + INPUT: A proof search object, a list <Blocked> of clauses from + the proof search object and a clause that causes the + already indexed clauses in <Blocked> to be redundant. + RETURNS: Nothing. +**********************************************************/ +{ + FLAGSTORE Flags; + CLAUSE Clause; + LIST Scan; + + Flags = prfs_Store(Search); + for (Scan = Blocked; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Clause = (CLAUSE)list_Car(Scan); + if (prfs_SplitLevelCondition(clause_SplitLevel(RedClause),clause_SplitLevel(Clause), + prfs_LastBacktrackLevel(Search))) + split_DeleteClauseAtLevel(Search, Clause, clause_SplitLevel(RedClause)); + else { + if (clause_GetFlag(Clause, WORKEDOFF)) { + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) + prfs_MoveWorkedOffDocProof(Search, Clause); + else + prfs_DeleteWorkedOff(Search, Clause); + } + else + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) + prfs_MoveUsableDocProof(Search, Clause); + else + prfs_DeleteUsable(Search, Clause); + } + } +} + +static void red_HandleRedundantDerivedClauses(PROOFSEARCH Search, LIST Blocked, + CLAUSE RedClause) +/********************************************************* + INPUT: A proof search object, a list <Blocked> of clauses from + the proof search object and a clause that causes the + derived clauses in <Blocked> to be redundant. + RETURNS: Nothing. +**********************************************************/ +{ + CLAUSE Clause; + LIST Scan; + + for (Scan = Blocked; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Clause = (CLAUSE)list_Car(Scan); + if (prfs_SplitLevelCondition(clause_SplitLevel(RedClause),clause_SplitLevel(Clause), + prfs_LastBacktrackLevel(Search))) { + split_KeepClauseAtLevel(Search, Clause, clause_SplitLevel(RedClause)); + } + else { + if (flag_GetFlagValue(prfs_Store(Search), flag_DOCPROOF)) + prfs_InsertDocProofClause(Search, Clause); + else + clause_Delete(Clause); + } + } +} + + +void red_Init(void) +/********************************************************* + INPUT: None. + RETURNS: Nothing. + EFFECT: Initializes the Reduction module, in particular + its stampid to stamp terms. +**********************************************************/ +{ + red_STAMPID = term_GetStampID(); +} + + +static void red_DocumentObviousReductions(CLAUSE Clause, LIST Indexes) +/********************************************************* + INPUT: A clause and a list of literal indexes removed by + obvious reductions. + RETURNS: None + MEMORY: The <Indexes> list is consumed. +**********************************************************/ +{ + list_Delete(clause_ParentClauses(Clause)); + list_Delete(clause_ParentLiterals(Clause)); + clause_SetParentClauses(Clause, list_Nil()); + clause_SetParentLiterals(Clause, Indexes); + + clause_AddParentClause(Clause,clause_Number(Clause)); /* Has to be done before increasing it! */ + + clause_SetNumber(Clause, clause_IncreaseCounter()); + clause_SetFromObviousReductions(Clause); +} + + +static BOOL red_ObviousReductions(CLAUSE Clause, BOOL Document, + FLAGSTORE Flags, PRECEDENCE Precedence, + CLAUSE *Changed) +/********************************************************** + INPUT: A clause, a boolean flag for proof + documentation, a flag store and a precedence. + RETURNS: TRUE iff obvious reductions are possible. + If <Document> is false the clause is + destructively changed, + else a reduced copy of the clause is returned + in <*Changed>. + EFFECT: Multiple occurrences of the same literal as + well as trivial equations are removed. +********************************************************/ +{ + int i, j, end; + LIST Indexes; + TERM Atom, PartnerAtom; + +#ifdef CHECK + clause_Check(Clause, Flags, Precedence); +#endif + + Indexes = list_Nil(); + end = clause_LastAntecedentLitIndex(Clause); + + for (i = clause_FirstConstraintLitIndex(Clause); i <= end; i++) { + Atom = clause_LiteralAtom(clause_GetLiteral(Clause,i)); + if (fol_IsEquality(Atom) && + !clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause, i)) && + term_Equal(term_FirstArgument(Atom),term_SecondArgument(Atom))) { + Indexes = list_Cons((POINTER)i,Indexes); + } + else + for (j = i+1; j <= end; j++) { + PartnerAtom = clause_LiteralAtom(clause_GetLiteral(Clause,j)); + if (term_Equal(PartnerAtom, Atom) || + (fol_IsEquality(Atom) && + fol_IsEquality(PartnerAtom) && + term_Equal(term_FirstArgument(Atom),term_SecondArgument(PartnerAtom)) && + term_Equal(term_FirstArgument(PartnerAtom),term_SecondArgument(Atom)))) { + Indexes = list_Cons((POINTER)i,Indexes); + j = end; + } + } + } + + end = clause_LastSuccedentLitIndex(Clause); + + for (i = clause_FirstSuccedentLitIndex(Clause); i <= end; i++) { + Atom = clause_LiteralAtom(clause_GetLiteral(Clause,i)); + for (j = i+1; j <= end; j++) { + PartnerAtom = clause_LiteralAtom(clause_GetLiteral(Clause,j)); + if (term_Equal(PartnerAtom,Atom) || + (fol_IsEquality(Atom) && + fol_IsEquality(PartnerAtom) && + term_Equal(term_FirstArgument(Atom),term_SecondArgument(PartnerAtom)) && + term_Equal(term_FirstArgument(PartnerAtom),term_SecondArgument(Atom)))) { + Indexes = list_Cons((POINTER)i,Indexes); + j = end; + } + } + } + + if (clause_Length(Clause) == 1 && + clause_NumOfAnteLits(Clause) == 1 && + !list_PointerMember(Indexes,(POINTER)clause_FirstAntecedentLitIndex(Clause)) && + fol_IsEquality(clause_GetLiteralAtom(Clause,clause_FirstAntecedentLitIndex(Clause)))) { + cont_StartBinding(); + if (unify_UnifyCom(cont_LeftContext(), + term_FirstArgument(clause_LiteralAtom(clause_GetLiteral(Clause,clause_FirstAntecedentLitIndex(Clause)))), + term_SecondArgument(clause_LiteralAtom(clause_GetLiteral(Clause,clause_FirstAntecedentLitIndex(Clause)))))) + Indexes = list_Cons((POINTER)clause_FirstAntecedentLitIndex(Clause),Indexes); + cont_BackTrack(); + } + + if (!list_Empty(Indexes)) { + if (flag_GetFlagValue(Flags, flag_POBV)) { + fputs("\nObvious: ", stdout); + clause_Print(Clause); + fputs(" ==> ", stdout); + } + if (Document) { + CLAUSE Copy; + Copy = clause_Copy(Clause); + clause_DeleteLiterals(Copy,Indexes, Flags, Precedence); + red_DocumentObviousReductions(Copy,Indexes); /* Indexes is consumed */ + if (flag_GetFlagValue(Flags, flag_POBV)) + clause_Print(Copy); + *Changed = Copy; + } + else { + clause_DeleteLiterals(Clause,Indexes, Flags, Precedence); + list_Delete(Indexes); + if (flag_GetFlagValue(Flags, flag_POBV)) + clause_Print(Clause); + } + return TRUE; + } + + return FALSE; +} + + +static void red_DocumentCondensing(CLAUSE Clause, LIST Indexes) +/********************************************************* + INPUT: A clause and a list of literal indexes removed by condensing. + RETURNS: Nothing. + MEMORY: The <Indexes> list is consumed. +**********************************************************/ +{ + list_Delete(clause_ParentClauses(Clause)); + list_Delete(clause_ParentLiterals(Clause)); + clause_SetParentClauses(Clause, list_Nil()); + clause_SetParentLiterals(Clause, Indexes); + + clause_AddParentClause(Clause,clause_Number(Clause)); /* Has to be done before increasing it! */ + + clause_SetNumber(Clause, clause_IncreaseCounter()); + clause_SetFromCondensing(Clause); +} + +static BOOL red_Condensing(CLAUSE Clause, BOOL Document, FLAGSTORE Flags, + PRECEDENCE Precedence, CLAUSE *Changed) +/********************************************************** + INPUT: A non-empty unshared clause, a boolean flag + concerning proof documentation, a flag store and + a precedence. + RETURNS: TRUE iff condensing is applicable to <Clause>. + If <Document> is false the clause is + destructively changed else a condensed copy of + the clause is returned in <*Changed>. +***********************************************************/ +{ + LIST Indexes; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence) || + (*Changed != (CLAUSE)NULL)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_Condensing : "); + misc_ErrorReport("Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(Clause, Flags, Precedence); +#endif + + Indexes = cond_CondFast(Clause); + + if (!list_Empty(Indexes)) { + if (flag_GetFlagValue(Flags, flag_PCON)) { + fputs("\nCondensing: ", stdout); + clause_Print(Clause); + fputs(" ==> ", stdout); + } + if (Document) { + CLAUSE Copy; + Copy = clause_Copy(Clause); + clause_DeleteLiterals(Copy, Indexes, Flags, Precedence); + red_DocumentCondensing(Copy, Indexes); + if (flag_GetFlagValue(Flags, flag_PCON)) + clause_Print(Copy); + *Changed = Copy; + } + else { + clause_DeleteLiterals(Clause, Indexes, Flags, Precedence); + list_Delete(Indexes); + if (flag_GetFlagValue(Flags, flag_PCON)) + clause_Print(Clause); + } + return TRUE; + } + return FALSE; +} + + +static void red_DocumentAssignmentEquationDeletion(CLAUSE Clause, LIST Indexes, + NAT NonTrivClauseNumber) +/********************************************************* + INPUT: A clause and a list of literal indexes pointing to + redundant equations and the clause number of a clause + implying a non-trivial domain. + RETURNS: Nothing. + MEMORY: The <Indexes> list is consumed. +**********************************************************/ +{ + list_Delete(clause_ParentClauses(Clause)); + list_Delete(clause_ParentLiterals(Clause)); + clause_SetParentClauses(Clause, list_Nil()); + clause_SetParentLiterals(Clause, Indexes); + + clause_AddParentClause(Clause,clause_Number(Clause)); /* Has to be done before increasing it! */ + + clause_SetNumber(Clause, clause_IncreaseCounter()); + clause_SetFromAssignmentEquationDeletion(Clause); + + if (NonTrivClauseNumber != 0) { /* Such a clause exists */ + clause_AddParentClause(Clause, NonTrivClauseNumber); + clause_AddParentLiteral(Clause, 0); /* The non triv clause has exactly one negative literal */ + } +} + + +static BOOL red_AssignmentEquationDeletion(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence, CLAUSE *Changed, + NAT NonTrivClauseNumber, + BOOL NonTrivDomain) +/********************************************************** + INPUT: A non-empty unshared clause, a flag store, a + precedence, the clause number of a clause + implying a non-trivial domain and a boolean + flag indicating whether the current domain has + more than one element. + RETURNS: TRUE iff equations are removed. + If the <DocProof> flag is false the clause is + destructively changed else a copy of the clause + where redundant equations are removed is + returned in <*Changed>. +***********************************************************/ +{ + LIST Indexes; /* List of indexes of redundant equations*/ + NAT i; + TERM LeftArg, RightArg; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence) || + (*Changed != (CLAUSE)NULL) || + (NonTrivDomain && NonTrivClauseNumber == 0) || + (!NonTrivDomain && NonTrivClauseNumber > 0)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_AssignmentEquationDeletion: "); + misc_ErrorReport("Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(Clause, Flags, Precedence); +#endif + + Indexes = list_Nil(); + + if (clause_ContainsNegativeEquations(Clause)) { + for (i = clause_FirstAntecedentLitIndex(Clause); i <= clause_LastAntecedentLitIndex(Clause); i++) { + if (clause_LiteralIsEquality(clause_GetLiteral(Clause,i))) { + LeftArg = term_FirstArgument(clause_GetLiteralAtom(Clause,i)); + RightArg = term_SecondArgument(clause_GetLiteralAtom(Clause,i)); + if ((term_IsVariable(LeftArg) && + clause_NumberOfSymbolOccurrences(Clause, term_TopSymbol(LeftArg)) == 1) || + (term_IsVariable(RightArg) && + clause_NumberOfSymbolOccurrences(Clause, term_TopSymbol(RightArg)) == 1)) + Indexes = list_Cons((POINTER)i, Indexes); + } + } + } + else + if (NonTrivDomain && clause_ContainsPositiveEquations(Clause)) { + for (i = clause_FirstSuccedentLitIndex(Clause); i <= clause_LastSuccedentLitIndex(Clause); i++) { + if (clause_LiteralIsEquality(clause_GetLiteral(Clause,i))) { + LeftArg = term_FirstArgument(clause_GetLiteralAtom(Clause,i)); + RightArg = term_SecondArgument(clause_GetLiteralAtom(Clause,i)); + if ((term_IsVariable(LeftArg) && + clause_NumberOfSymbolOccurrences(Clause, term_TopSymbol(LeftArg)) == 1) || + (term_IsVariable(RightArg) && + clause_NumberOfSymbolOccurrences(Clause, term_TopSymbol(RightArg)) == 1)) + Indexes = list_Cons((POINTER)i, Indexes); + } + } + } + + if (!list_Empty(Indexes)) { + if (flag_GetFlagValue(Flags, flag_PAED)) { + fputs("\nAED: ", stdout); + clause_Print(Clause); + fputs(" ==> ", stdout); + } + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) { + CLAUSE Copy; + Copy = clause_Copy(Clause); + clause_DeleteLiterals(Copy, Indexes, Flags, Precedence); + red_DocumentAssignmentEquationDeletion(Copy, Indexes, NonTrivClauseNumber); + if (flag_GetFlagValue(Flags, flag_PAED)) + clause_Print(Copy); + *Changed = Copy; + } + else { + clause_DeleteLiterals(Clause, Indexes, Flags, Precedence); + list_Delete(Indexes); + if (flag_GetFlagValue(Flags, flag_PAED)) + clause_Print(Clause); + } + return TRUE; + } + + return FALSE; +} + + +static BOOL red_Tautology(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/********************************************************** + INPUT: A non-empty clause, a flag store and a + precedence. + RETURNS: The boolean value TRUE if 'Clause' is a + tautology. +***********************************************************/ +{ + TERM Atom; + int i,j, la,n; + BOOL Result; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_Tautology :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(Clause, Flags, Precedence); +#endif + + la = clause_LastAntecedentLitIndex(Clause); + n = clause_Length(Clause); + Result = FALSE; + + for (j = clause_FirstSuccedentLitIndex(Clause); j < n && !Result; j++) { + + Atom = clause_LiteralAtom(clause_GetLiteral(Clause, j)); + + if (fol_IsEquality(Atom) && + !clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause, j)) && + term_Equal(term_FirstArgument(Atom),term_SecondArgument(Atom))) + Result = TRUE; + + for (i = clause_FirstLitIndex(); i <= la && !Result; i++) + if (term_Equal(Atom, clause_LiteralAtom(clause_GetLiteral(Clause, i)))) + Result = TRUE; + } + + + if (!Result && + flag_GetFlagValue(Flags, flag_RTAUT) == flag_RTAUTSEMANTIC && + clause_NumOfAnteLits(Clause) != 0 && + clause_NumOfSuccLits(Clause) != 0) { + Result = cc_Tautology(Clause); + } + + if (Result && flag_GetFlagValue(Flags, flag_PTAUT)) { + fputs("\nTautology: ", stdout); + clause_Print(Clause); + } + return Result; +} + +static LITERAL red_GetMRResLit(LITERAL ActLit, SHARED_INDEX ShIndex) +/************************************************************** + INPUT: A literal and an Index. + RETURNS: The most valid clause with a complementary literal, + (CLAUSE)NULL, if no such clause exists. +***************************************************************/ +{ + LITERAL NextLit; + int i; + CLAUSE ActClause; + TERM CandTerm; + LIST LitScan; + + NextLit = (LITERAL)NULL; + ActClause = clause_LiteralOwningClause(ActLit); + i = clause_LiteralGetIndex(ActLit); + CandTerm = st_ExistGen(cont_LeftContext(), + sharing_Index(ShIndex), + clause_LiteralAtom(ActLit)); + + while (CandTerm) { /* First check units */ + if (!term_IsVariable(CandTerm)) { /* Has to be an Atom! */ + LitScan = sharing_NAtomDataList(CandTerm); /* CAUTION !!! the List is not a copy */ + while (!list_Empty(LitScan)) { + NextLit = list_Car(LitScan); + if (clause_LiteralsAreComplementary(ActLit,NextLit)) + if (clause_Length(clause_LiteralOwningClause(NextLit)) == 1 || + subs_SubsumesBasic(clause_LiteralOwningClause(NextLit),ActClause, + clause_LiteralGetIndex(NextLit),i)) { + st_CancelExistRetrieval(); + return NextLit; + } + LitScan = list_Cdr(LitScan); + } + } + CandTerm = st_NextCandidate(); + } + return (LITERAL)NULL; +} + +static void red_DocumentMatchingReplacementResolution(CLAUSE Clause, LIST LitInds, + LIST ClauseNums, LIST PLitInds) +/********************************************************* + INPUT: A clause, the involved literals indices in <Clause>, + the literal indices of the reduction literals + and the clauses number. + RETURNS: Nothing. + MEMORY: All input lists are consumed. +**********************************************************/ +{ + LIST Scan,Help; + + Help = list_Nil(); + + for (Scan=LitInds; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Help = list_Cons((POINTER)clause_Number(Clause), Help); + /* Has to be done before increasing the clause number! */ + } + list_Delete(clause_ParentClauses(Clause)); + list_Delete(clause_ParentLiterals(Clause)); + clause_SetParentClauses(Clause, list_Nconc(Help,ClauseNums)); + clause_SetParentLiterals(Clause, list_Nconc(LitInds,PLitInds)); + + clause_SetNumber(Clause, clause_IncreaseCounter()); + clause_SetFromMatchingReplacementResolution(Clause); +} + +static BOOL red_MatchingReplacementResolution(CLAUSE Clause, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence, + CLAUSE *Changed, int Level) +/************************************************************** + INPUT: A clause, an Index, a flag store, a precedence and a + split level indicating the need of a copy if + <Clause> is reduced by a clause of higher split + level than <Level>. + RETURNS: TRUE if reduction wrt the indexed clauses was + possible. + If the <DocProof> flag is true or the clauses used + for reductions have a higher split level then a + changed copy is returned in <*Changed>. + Otherwise <Clause> is destructively changed. +***************************************************************/ +{ + CLAUSE PClause,Copy; + LITERAL ActLit,PLit; + int i, j, length; + LIST ReducedBy,ReducedLits,PLits,Scan1,Scan2; + BOOL Document; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence) || + (*Changed != (CLAUSE)NULL)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_MatchingReplacementResolution:"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(Clause, Flags, Precedence); +#endif + + Copy = Clause; + length = clause_Length(Clause); + ReducedBy = list_Nil(); + ReducedLits = list_Nil(); + PLits = list_Nil(); + i = clause_FirstLitIndex(); + j = 0; + Document = flag_GetFlagValue(Flags, flag_DOCPROOF); + + while (i < length) { + ActLit = clause_GetLiteral(Copy, i); + + if (!fol_IsEquality(clause_LiteralAtom(ActLit)) || /* Reduce with negative equations. */ + clause_LiteralIsPositive(ActLit)) { + PLit = red_GetMRResLit(ActLit, ShIndex); + if (clause_LiteralExists(PLit)) { + if (list_Empty(PLits) && flag_GetFlagValue(Flags, flag_PMRR)) { + fputs("\nFMatchingReplacementResolution: ", stdout); + clause_Print(Copy); + } + PClause = clause_LiteralOwningClause(PLit); + ReducedBy = list_Cons((POINTER)clause_Number(PClause), ReducedBy); + PLits = list_Cons((POINTER)clause_LiteralGetIndex(PLit),PLits); + ReducedLits = list_Cons((POINTER)(i+j), ReducedLits); + if (Copy == Clause && + (Document || prfs_SplitLevelCondition(clause_SplitLevel(PClause),clause_SplitLevel(Copy),Level))) + Copy = clause_Copy(Clause); + clause_UpdateSplitDataFromPartner(Copy, PClause); + clause_DeleteLiteral(Copy,i, Flags, Precedence); + length--; + j++; + } + else + i++; + } + else + i++; + } + + if (!list_Empty(ReducedBy)) { + if (Document) { + ReducedBy = list_NReverse(ReducedBy); + ReducedLits = list_NReverse(ReducedLits); + PLits = list_NReverse(PLits); + red_DocumentMatchingReplacementResolution(Copy, ReducedLits, ReducedBy, PLits); /* Lists are consumed */ + if (flag_GetFlagValue(Flags, flag_PMRR)) { + fputs(" ==> [ ", stdout); + for(Scan1=ReducedBy,Scan2=ReducedLits;!list_Empty(Scan1); + Scan1=list_Cdr(Scan1),Scan2=list_Cdr(Scan2)) + printf("%d.%d ",(NAT)list_Car(Scan1),(NAT)list_Car(Scan2)); + fputs("] ", stdout); + clause_Print(Copy); + } + } + else { + if (flag_GetFlagValue(Flags, flag_PMRR)) { + fputs(" ==> [ ", stdout); + for(Scan1=ReducedBy,Scan2=ReducedLits;!list_Empty(Scan1); + Scan1=list_Cdr(Scan1),Scan2=list_Cdr(Scan2)) + printf("%d.%d ",(NAT)list_Car(Scan1),(NAT)list_Car(Scan2)); + fputs("] ", stdout); + clause_Print(Copy); + } + list_Delete(ReducedBy); + list_Delete(ReducedLits); + list_Delete(PLits); + } + if (Copy != Clause) + *Changed = Copy; + return TRUE; + } + return FALSE; +} + +static void red_DocumentUnitConflict(CLAUSE Clause, LIST LitInds, + LIST ClauseNums, LIST PLitInds) +/********************************************************* + INPUT: A clause, the involved literals indices and the clauses number. + RETURNS: Nothing. + MEMORY: All input lists are consumed. +**********************************************************/ +{ + list_Delete(clause_ParentClauses(Clause)); + list_Delete(clause_ParentLiterals(Clause)); + clause_SetParentClauses(Clause, list_Nconc(list_List((POINTER)clause_Number(Clause)),ClauseNums)); + clause_SetParentLiterals(Clause, list_Nconc(LitInds,PLitInds)); + + clause_SetNumber(Clause, clause_IncreaseCounter()); + clause_SetFromUnitConflict(Clause); +} + + +static BOOL red_UnitConflict(CLAUSE Clause, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence, + CLAUSE *Changed, int Level) +/************************************************************** + INPUT: A clause, an Index, a flag store and a splitlevel + indicating the need of a copy if <Clause> is reduced + by a clause of higher split level than <Level>. + RETURNS: TRUE if a unit conflict with <Clause> and the + clauses in <ShIndex> happened. + If the <DocProof> flag is true or the clauses used for + reductions have a higher split level then a changed + copy is returned in <*Changed>. + Otherwise <Clause> is destructively changed. +***************************************************************/ +{ + CLAUSE PClause,Copy; + LITERAL ActLit,PLit; + LIST Scan; + TERM CandTerm; + BOOL Document; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence) || (*Changed != (CLAUSE)NULL)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_ForwardUnitConflict :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(Clause, Flags, Precedence); +#endif + + if (clause_Length(Clause) == 1) { + Copy = Clause; + Document = flag_GetFlagValue(Flags, flag_DOCPROOF); + ActLit = clause_GetLiteral(Copy, clause_FirstLitIndex()); + PLit = (LITERAL)NULL; + CandTerm = st_ExistUnifier(cont_LeftContext(), sharing_Index(ShIndex), cont_RightContext(), + clause_LiteralAtom(ActLit)); + while (PLit == (LITERAL)NULL && CandTerm) { + if (!term_IsVariable(CandTerm)) { + Scan = sharing_NAtomDataList(CandTerm); /* CAUTION !!! the List is not a copy */ + while (!list_Empty(Scan)) { + PLit = list_Car(Scan); + if (clause_LiteralsAreComplementary(ActLit,PLit) && + clause_Length(clause_LiteralOwningClause(PLit)) == 1) { + st_CancelExistRetrieval(); + Scan = list_Nil(); + } + else { + PLit = (LITERAL)NULL; + Scan = list_Cdr(Scan); + } + } + } + if (PLit == (LITERAL)NULL) + CandTerm = st_NextCandidate(); + } + + if (PLit == (LITERAL)NULL && fol_IsEquality(clause_LiteralAtom(ActLit))) { + TERM Atom; + Atom = term_Create(fol_Equality(),list_Reverse(term_ArgumentList(clause_LiteralAtom(ActLit)))); + CandTerm = st_ExistUnifier(cont_LeftContext(), sharing_Index(ShIndex), cont_RightContext(), Atom); + while (PLit == (LITERAL)NULL && CandTerm) { + if (!term_IsVariable(CandTerm)) { + Scan = sharing_NAtomDataList(CandTerm); /* CAUTION !!! the List is not a copy */ + while (!list_Empty(Scan)) { + PLit = list_Car(Scan); + if (clause_LiteralsAreComplementary(ActLit,PLit) && + clause_Length(clause_LiteralOwningClause(PLit)) == 1) { + st_CancelExistRetrieval(); + Scan = list_Nil(); + } + else { + PLit = (LITERAL)NULL; + Scan = list_Cdr(Scan); + } + } + } + if (PLit == (LITERAL)NULL) + CandTerm = st_NextCandidate(); + } + list_Delete(term_ArgumentList(Atom)); + term_Free(Atom); + } + + if (clause_LiteralExists(PLit)) { + if (flag_GetFlagValue(Flags, flag_PUNC)) { + fputs("\nUnitConflict: ", stdout); + clause_Print(Copy); + } + PClause = clause_LiteralOwningClause(PLit); + if (Copy == Clause && + (Document || prfs_SplitLevelCondition(clause_SplitLevel(PClause),clause_SplitLevel(Copy),Level))) + Copy = clause_Copy(Clause); + clause_UpdateSplitDataFromPartner(Copy, PClause); + clause_DeleteLiteral(Copy,clause_FirstLitIndex(), Flags, Precedence); + if (Document) + red_DocumentUnitConflict(Copy, list_List((POINTER)clause_FirstLitIndex()), + list_List((POINTER)clause_Number(PClause)), + list_List((POINTER)clause_FirstLitIndex())); + if (flag_GetFlagValue(Flags, flag_PUNC)) { + printf(" ==> [ %d.%d ]", clause_Number(PClause), clause_FirstLitIndex()); + clause_Print(Copy); + } + if (Copy != Clause) + *Changed = Copy; + return TRUE; + } + } + return FALSE; +} + + +static CLAUSE red_ForwardSubsumer(CLAUSE RedCl, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence) +/********************************************************** + INPUT: A pointer to a non-empty clause, an index of + clauses, a flag store and a precedence. + RETURNS: A clause that subsumes <RedCl>, or NULL if no such + clause exists. +***********************************************************/ +{ + TERM Atom,AtomGen; + CLAUSE CandCl; + LITERAL CandLit; + LIST LitScan; + int i, lc, fa, la, fs, ls; + +#ifdef CHECK + if (!clause_IsClause(RedCl, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_ForwardSubsumer:"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedCl, Flags, Precedence); +#endif + + lc = clause_LastConstraintLitIndex(RedCl); + fa = clause_FirstAntecedentLitIndex(RedCl); + la = clause_LastAntecedentLitIndex(RedCl); + fs = clause_FirstSuccedentLitIndex(RedCl); + ls = clause_LastSuccedentLitIndex(RedCl); + + for (i = 0; i <= ls; i++) { + Atom = clause_GetLiteralAtom(RedCl, i); + AtomGen = st_ExistGen(cont_LeftContext(), sharing_Index(ShIndex), Atom); + + while (AtomGen) { + if (!term_IsVariable(AtomGen)) { + for (LitScan = sharing_NAtomDataList(AtomGen); + !list_Empty(LitScan); + LitScan = list_Cdr(LitScan)) { + CandLit = list_Car(LitScan); + CandCl = clause_LiteralOwningClause(CandLit); + + if (CandCl != RedCl && + clause_GetLiteral(CandCl,clause_FirstLitIndex()) == CandLit && + /* Literals must be from same part of the clause */ + ((i<=lc && clause_LiteralIsFromConstraint(CandLit)) || + (i>=fa && i<=la && clause_LiteralIsFromAntecedent(CandLit)) || + (i>=fs && clause_LiteralIsFromSuccedent(CandLit))) && + subs_SubsumesBasic(CandCl, RedCl, clause_FirstLitIndex(), i)) { + st_CancelExistRetrieval(); + return (CandCl); + } + } + } + AtomGen = st_NextCandidate(); + } + + if (fol_IsEquality(Atom) && + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(RedCl,i))) { + Atom = term_Create(fol_Equality(),list_Reverse(term_ArgumentList(Atom))); + AtomGen = st_ExistGen(cont_LeftContext(), sharing_Index(ShIndex), Atom); + while (AtomGen) { + if (!term_IsVariable(AtomGen)) { + for (LitScan = sharing_NAtomDataList(AtomGen); + !list_Empty(LitScan); + LitScan = list_Cdr(LitScan)) { + CandLit = list_Car(LitScan); + CandCl = clause_LiteralOwningClause(CandLit); + if (CandCl != RedCl && + clause_GetLiteral(CandCl,clause_FirstLitIndex()) == CandLit && + /* Literals must be from same part of the clause */ + ((i<=lc && clause_LiteralIsFromConstraint(CandLit)) || + (i>=fa && i<=la && clause_LiteralIsFromAntecedent(CandLit)) || + (i>=fs && clause_LiteralIsFromSuccedent(CandLit))) && + subs_SubsumesBasic(CandCl, RedCl, clause_FirstLitIndex(), i)) { + st_CancelExistRetrieval(); + list_Delete(term_ArgumentList(Atom)); + term_Free(Atom); + return (CandCl); + } + } + } + AtomGen = st_NextCandidate(); + } + list_Delete(term_ArgumentList(Atom)); + term_Free(Atom); + } + } + + return((CLAUSE)NULL); +} + + +static CLAUSE red_ForwardSubsumption(CLAUSE RedClause, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence) +/********************************************************** + INPUT: A clause, an index of clauses, a flag store and + a precedence. + RETURNS: The clause <RedClause> is subsumed by in <ShIndex>. +***********************************************************/ +{ + CLAUSE Subsumer; + +#ifdef CHECK + if (!clause_IsClause(RedClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_ForwardSubsumption:"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedClause, Flags, Precedence); +#endif + + Subsumer = red_ForwardSubsumer(RedClause, ShIndex, Flags, Precedence); + + if (flag_GetFlagValue(Flags, flag_PSUB) && Subsumer) { + fputs("\nFSubsumption: ", stdout); + clause_Print(RedClause); + printf(" by %d %d ",clause_Number(Subsumer),clause_SplitLevel(Subsumer)); + } + + return Subsumer; +} + + +static void red_DocumentRewriting(CLAUSE Clause, int i, CLAUSE Rule, int ri) +/********************************************************* + INPUT: Two clauses and the literal indices involved in the rewrite step. + RETURNS: Nothing. + EFFECT: Documentation in <Clause> is set. +**********************************************************/ +{ + list_Delete(clause_ParentClauses(Clause)); + list_Delete(clause_ParentLiterals(Clause)); + clause_SetParentClauses(Clause, + list_List((POINTER)clause_Number(Clause))); + /* Has to be done before increasing the number! */ + + clause_SetParentLiterals(Clause, list_List((POINTER)i)); + clause_NewNumber(Clause); + clause_SetFromRewriting(Clause); + + clause_AddParentClause(Clause,clause_Number(Rule)); + clause_AddParentLiteral(Clause,ri); +} + + +static void red_DocumentFurtherRewriting(CLAUSE Clause, int i, CLAUSE Rule, int ri) +/********************************************************* + INPUT: Two clauses and the literal indices involved in the rewrite step. + RETURNS: Nothing. + EFFECT: Documentation in <Clause> is set. +**********************************************************/ +{ + clause_AddParentClause(Clause, + (int) list_Car(list_Cdr(clause_ParentClauses(Clause)))); + clause_AddParentLiteral(Clause, i); + clause_AddParentClause(Clause, clause_Number(Rule)); + clause_AddParentLiteral(Clause, ri); +} + + +static BOOL red_RewriteRedUnitClause(CLAUSE RedClause, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence, + CLAUSE *Changed, int Level) +/************************************************************** + INPUT: A unit (!) clause, an Index, a flag store, a + precedence and a split level indicating the need of + a copy if <Clause> is reduced by a clause of higher + split level than <Level>. + RETURNS: TRUE iff rewriting was possible. + If the <DocProof> flag is true or the split level of + the rewrite rule is higher a copy of RedClause that + is rewritten wrt. the indexed clauses is returned in + <*Changed>. + Otherwise the clause is destructively rewritten. +***************************************************************/ +{ + TERM RedAtom, RedTermS; + int B_Stack; + BOOL Rewritten, Result, Oriented, Renamed, Document; + TERM TermS,PartnerEq; + LIST EqList,EqScan,LitScan; + CLAUSE Copy; + +#ifdef CHECK + if (!clause_IsClause(RedClause, Flags, Precedence) || + *Changed != (CLAUSE)NULL || + clause_Length(RedClause) != 1) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_RewriteRedUnitClause :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedClause, Flags, Precedence); +#endif + + Result = FALSE; + Renamed = FALSE; + Copy = RedClause; + RedAtom = clause_GetLiteralAtom(Copy, clause_FirstLitIndex()); + Rewritten = TRUE; + Document = flag_GetFlagValue(Flags, flag_DOCPROOF); + + /* Don't apply this rule on constraint or propositional literals */ + if (clause_FirstLitIndex() <= clause_LastConstraintLitIndex(RedClause) || + list_Empty(term_ArgumentList(RedAtom))) + return Result; + + if (term_StampOverflow(red_STAMPID)) + term_ResetTermStamp(clause_LiteralSignedAtom(clause_GetLiteral(RedClause, clause_FirstLitIndex()))); + term_StartStamp(); + + while (Rewritten) { + Rewritten = FALSE; + B_Stack = stack_Bottom(); + sharing_PushListOnStackNoStamps(term_ArgumentList(RedAtom)); + + while (!stack_Empty(B_Stack)) { + RedTermS = (TERM)stack_PopResult(); + TermS = st_ExistGen(cont_LeftContext(), sharing_Index(ShIndex), RedTermS); + while (TermS && !Rewritten) { + EqList = term_SupertermList(TermS); + for (EqScan = EqList; !list_Empty(EqScan) && !Rewritten; + EqScan = list_Cdr(EqScan)) { + PartnerEq = list_Car(EqScan); + if (fol_IsEquality(PartnerEq)) { + CLAUSE RewriteClause; + LITERAL RewriteLit; + TERM Right; + + if (TermS == term_FirstArgument(PartnerEq)) + Right = term_SecondArgument(PartnerEq); + else + Right = term_FirstArgument(PartnerEq); + + for (LitScan = sharing_NAtomDataList(PartnerEq); + !list_Empty(LitScan) && !Rewritten; + LitScan = list_Cdr(LitScan)) { + RewriteLit = list_Car(LitScan); + RewriteClause = clause_LiteralOwningClause(RewriteLit); + if (clause_LiteralIsPositive(RewriteLit) && + clause_Length(RewriteClause) == 1) { + Oriented = (clause_LiteralIsOrientedEquality(RewriteLit) && + TermS == term_FirstArgument(PartnerEq)); + if (!Oriented && !clause_LiteralIsOrientedEquality(RewriteLit)) { + Renamed = TRUE; /* If oriented, no renaming needed! */ + term_StartMaxRenaming(clause_MaxVar(RewriteClause)); + term_Rename(RedAtom); /* Renaming destructive, no extra match needed !! */ + Oriented = ord_ContGreater(cont_LeftContext(), TermS, + cont_LeftContext(), Right, + Flags, Precedence); + + /*if (Oriented) { + fputs("\n\n\tRedAtom: ",stdout);term_PrintPrefix(RedAtom); + fputs("\n\tSubTerm: ",stdout);term_PrintPrefix(RedTermS); + fputs("\n\tGenTerm: ",stdout);term_PrintPrefix(TermS); + fputs("\n\tGenRight: ",stdout);term_PrintPrefix(Right); + putchar('\n');cont_PrintCurrentTrail();putchar('\n'); + }*/ + } + if (Oriented) { + TERM TermT; + + if (RedClause == Copy && + (Document || + prfs_SplitLevelCondition(clause_SplitLevel(RewriteClause), + clause_SplitLevel(RedClause),Level))) { + Copy = clause_Copy(RedClause); + RedAtom = clause_GetLiteralAtom(Copy, clause_FirstLitIndex()); + } + + if (!Result) + if (flag_GetFlagValue(Flags, flag_PREW)) { + fputs("\nFRewriting: ", stdout); + clause_Print(Copy); + fputs(" ==>[ ", stdout); + } + + if (Document) { + if (!Result) + red_DocumentRewriting(Copy, clause_FirstLitIndex(), + RewriteClause, clause_FirstLitIndex()); + else + red_DocumentFurtherRewriting(Copy, clause_FirstLitIndex(), + RewriteClause, clause_FirstLitIndex()); + } + Result = TRUE; + TermT = cont_ApplyBindingsModuloMatching(cont_LeftContext(), term_Copy(Right), TRUE); + if (cont_BindingsAreRenamingModuloMatching(cont_RightContext())) + term_SetTermSubtermStamp(TermT); + term_ReplaceSubtermBy(RedAtom, RedTermS, TermT); + Rewritten = TRUE; + clause_UpdateSplitDataFromPartner(Copy, RewriteClause); + term_Delete(TermT); + stack_SetBottom(B_Stack); + + if (flag_GetFlagValue(Flags, flag_PREW)) + printf("%d.%d ",clause_Number(RewriteClause), clause_FirstLitIndex()); + clause_UpdateWeight(Copy, Flags); + } + } + } + } + } + if (!Rewritten) + TermS = st_NextCandidate(); + } + st_CancelExistRetrieval(); + if (!Rewritten) + term_SetTermStamp(RedTermS); + } + } + term_StopStamp(); + + if (Result) { + clause_OrientAndReInit(Copy, Flags, Precedence); + if (Copy != RedClause) + clause_OrientAndReInit(RedClause, Flags, Precedence); + if (flag_GetFlagValue(Flags, flag_PREW)) { + fputs("] ", stdout); + clause_Print(Copy); + } + if (Copy != RedClause) + *Changed = Copy; + } + else + if (Renamed) + clause_OrientAndReInit(Copy, Flags, Precedence); + + +#ifdef CHECK + clause_Check(Copy, Flags, Precedence); + clause_Check(RedClause, Flags, Precedence); +#endif + + return Result; +} + + +static BOOL red_RewriteRedClause(CLAUSE RedClause, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence, + CLAUSE *Changed, int Level) +/************************************************************** + INPUT: A clause, an Index, a flag store, a precedence and + a split level indicating the need of a copy if + <Clause> is reduced by a clause of higher split + level than <Level>. + RETURNS: NULL, if no rewriting was possible. + If the <DocProof> flag is true or the split level of + the rewrite rule is higher a copy of RedClause + that is rewritten wrt. the indexed clauses. + Otherwise the clause is destructively rewritten and + returned. +***************************************************************/ +{ + TERM RedAtom, RedTermS; + int B_Stack; + int ci, length; + BOOL Rewritten, Result, Document; + TERM TermS,PartnerEq; + LIST EqScan,LitScan; + CLAUSE Copy; + +#ifdef CHECK + if (!clause_IsClause(RedClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_RewriteRedClause :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedClause, Flags, Precedence); +#endif + + length = clause_Length(RedClause); + Document = flag_GetFlagValue(Flags, flag_DOCPROOF); + + if (length == 1) + return red_RewriteRedUnitClause(RedClause, ShIndex, Flags, Precedence, + Changed, Level); + + Result = FALSE; + Copy = RedClause; + + /* Don't apply this rule on constraint literals! */ + for (ci = clause_FirstAntecedentLitIndex(RedClause); ci < length; ci++) { + Rewritten = TRUE; + if (!list_Empty(term_ArgumentList(clause_GetLiteralAtom(Copy, ci)))) { + while (Rewritten) { + Rewritten = FALSE; + RedAtom = clause_GetLiteralAtom(Copy, ci); + + B_Stack = stack_Bottom(); + /* push subterms on stack except variables */ + sharing_PushListReverseOnStack(term_ArgumentList(RedAtom)); + + while (!stack_Empty(B_Stack)) { + RedTermS = (TERM)stack_PopResult(); + TermS = st_ExistGen(cont_LeftContext(), sharing_Index(ShIndex), RedTermS); + + while (TermS && !Rewritten) { + /* A variable can't be greater than any other term, */ + /* so don't consider any variables here */ + if (!term_IsVariable(TermS)) { + EqScan = term_SupertermList(TermS); + + for ( ; !list_Empty(EqScan) && !Rewritten; + EqScan = list_Cdr(EqScan)) { + PartnerEq = list_Car(EqScan); + if (fol_IsEquality(PartnerEq) && + (term_FirstArgument(PartnerEq) == TermS)) { + CLAUSE RewriteClause; + LITERAL RewriteLit; + int ri; + + for (LitScan = sharing_NAtomDataList(PartnerEq); + !list_Empty(LitScan) && !Rewritten; + LitScan = list_Cdr(LitScan)) { + RewriteLit = list_Car(LitScan); + RewriteClause = clause_LiteralOwningClause(RewriteLit); + ri = clause_LiteralGetIndex(RewriteLit); + + if (clause_LiteralIsPositive(RewriteLit) && + clause_LiteralIsOrientedEquality(RewriteLit) && + subs_SubsumesBasic(RewriteClause, Copy, ri, ci)) { + TERM TermT; + + if (RedClause == Copy && + (Document || + prfs_SplitLevelCondition(clause_SplitLevel(RewriteClause), + clause_SplitLevel(RedClause),Level))) { + Copy = clause_Copy(RedClause); + RedAtom = clause_GetLiteralAtom(Copy, ci); + } + + if (!Result) { + if (flag_GetFlagValue(Flags, flag_PREW)) { + fputs("\nFRewriting: ", stdout); + clause_Print(Copy); + fputs(" ==>[ ", stdout); + } + } + + if (Document) { + if (!Result) + red_DocumentRewriting(Copy, ci, RewriteClause, ri); + else + red_DocumentFurtherRewriting(Copy,ci,RewriteClause,ri); + } + Result = TRUE; + /* Since <TermS> is the bigger term of an oriented */ + /* equation and all variables in <TermS> are bound, */ + /* all variables in the smaller term are bound, too. */ + /* So the strict version of cont_Apply... will work. */ + TermT = cont_ApplyBindingsModuloMatching(cont_LeftContext(), + term_Copy(term_SecondArgument(PartnerEq)), + TRUE); + + /* No variable renaming is necessary before creation */ + /* of bindings and replacement of subterms because all */ + /* variables of <TermT> are from <RedClause>/<Copy>. */ + term_ReplaceSubtermBy(RedAtom, RedTermS, TermT); + Rewritten = TRUE; + clause_UpdateSplitDataFromPartner(Copy,RewriteClause); + term_Delete(TermT); + stack_SetBottom(B_Stack); + + if (flag_GetFlagValue(Flags, flag_PREW)) + printf("%d.%d ",clause_Number(RewriteClause), ri); + clause_UpdateWeight(Copy, Flags); + } + } + } + } + } + if (!Rewritten) + TermS = st_NextCandidate(); + } + st_CancelExistRetrieval(); + } + } + } + } + if (Result) { + clause_OrientAndReInit(Copy, Flags, Precedence); + if (flag_GetFlagValue(Flags, flag_PREW)) { + fputs("] ", stdout); + clause_Print(Copy); + } + if (Copy != RedClause) { + clause_OrientAndReInit(RedClause, Flags, Precedence); + *Changed = Copy; + } + } + +#ifdef CHECK + clause_Check(Copy, Flags, Precedence); + clause_Check(RedClause, Flags, Precedence); +#endif + + return Result; +} + + +/**************************************************************/ +/* FORWARD CONTEXTUAL REWRITING */ +/**************************************************************/ + +static BOOL red_LeftTermOfEquationIsStrictlyMaximalTerm(CLAUSE Clause, + LITERAL Equation, + FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a literal of the clause, that is an + oriented equation, a flag store and a precedence. + RETURNS: TRUE, iff the bigger (i.e. left) term of the equation + is the strictly maximal term of the clause. + A term s is strictly maximal in a clause, iff for every atom + u=v (A=tt) of the clause s > u and s > v (s > A). +***************************************************************/ +{ + int i, except, last; + TERM LeftTerm, Atom; + LITERAL ActLit; + +#ifdef CHECK + if (!clause_LiteralIsOrientedEquality(Equation)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_LeftTermOfEquationIsStrictlyMaximalTerm: "); + misc_ErrorReport("literal is not oriented"); + misc_FinishErrorReport(); + } +#endif + + LeftTerm = term_FirstArgument(clause_LiteralSignedAtom(Equation)); + except = clause_LiteralGetIndex(Equation); + + /* Compare <LeftTerm> with all terms in the clause */ + last = clause_LastLitIndex(Clause); + for (i = clause_FirstLitIndex() ; i <= last; i++) { + if (i != except) { + ActLit = clause_GetLiteral(Clause, i); + Atom = clause_LiteralAtom(ActLit); + if (fol_IsEquality(Atom)) { + /* Atom is an equation */ + if (ord_Compare(LeftTerm, term_FirstArgument(Atom), Flags, Precedence) + != ord_GREATER_THAN || + (!clause_LiteralIsOrientedEquality(ActLit) && + ord_Compare(LeftTerm, term_SecondArgument(Atom), Flags, Precedence) + != ord_GREATER_THAN)) + /* Compare only with left (i.e. greater) subterm if the atom is */ + /* an oriented equation. */ + return FALSE; + } else { + /* Atom is not an equation */ + if (ord_Compare(LeftTerm, Atom, Flags, Precedence) != ord_GREATER_THAN) + return FALSE; + } + } + } + return TRUE; +} + + +static void red_CRwCalculateAdditionalParents(CLAUSE Reduced, + LIST RedundantClauses, + CLAUSE Subsumer, + int OriginalClauseNumber) +/************************************************************** + INPUT: A clause that was just reduced by forward reduction, + a list of intermediate clauses that were derived from + the original clause, a clause that subsumes <Reduced> + (NULL, if <Reduced> is not subsumed), and the clause + number of <Reduced> before it was reduced. + RETURNS: Nothing. + EFFECT: This function collects the information about parent + clauses and parent literals that is necessary for + proof documentation for Contextual Rewriting + and sets the parent information of <Reduced> accordingly. + The clause <Reduced> was derived in several steps + C1 -> C2 -> ... Cn -> <Reduced> from some clause C1. + <RedundantClauses> contains all those clauses C1, ..., Cn. + This function first collects the parent information from + the clauses C1, C2, ..., Cn, <Reduced>. All those clauses + were needed to derive <Reduced>, but for proof documentation + of the rewriting step we have to delete the numbers of + all clauses C1,...,Cn,Reduced. + + As a simplification this function doesn't set the + correct parent literals. It simply assumes that every + reduction step was done by literal 0. + This isn't a problem since only the correct parent + clause numbers are really needed for proof documentation. +***************************************************************/ +{ + LIST Parents, Scan; + int ActNum; + + /* First collect all parent clause numbers from the redundant clauses. */ + /* Also add number of <Subsumer> if it exists. */ + Parents = clause_ParentClauses(Reduced); + clause_SetParentClauses(Reduced, list_Nil()); + for (Scan = RedundantClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) + Parents = list_Append(clause_ParentClauses(list_Car(Scan)), Parents); + if (Subsumer != NULL) + Parents = list_Cons((POINTER)clause_Number(Subsumer), Parents); + + /* Now delete <OriginalClauseNumber> and the numbers of all clauses */ + /* that were derived from it. */ + Parents = list_PointerDeleteElement(Parents, (POINTER) OriginalClauseNumber); + for (Scan = RedundantClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + ActNum = clause_Number(list_Car(Scan)); + Parents = list_PointerDeleteElement(Parents, (POINTER) ActNum); + } + + /* Finally set data of result clause <Reduced>. */ + Parents = list_PointerDeleteDuplicates(Parents); + clause_SetParentClauses(Reduced, Parents); + /* Build list of literal numbers: in this simple version we just build */ + /* a list with the same length as the parent clauses containing only the */ + /* literal indices 0. */ + Parents = list_Copy(Parents); + for (Scan = Parents; !list_Empty(Scan); Scan = list_Cdr(Scan)) + list_Rplaca(Scan, (POINTER)0); + list_Delete(clause_ParentLiterals(Reduced)); + clause_SetParentLiterals(Reduced, Parents); +} + + +static BOOL red_LiteralIsDefinition(LITERAL Literal) +/************************************************************** + INPUT: A literal. + RETURNS: TRUE, iff the literal is a definition, i.e. an equation x=t, + where x is a variable and x doesn't occur in t. + The function needs time O(1), it is independent of the size + of the literal. + CAUTION: The orientation of the literal must be correct. +***************************************************************/ +{ + TERM Atom; + + Atom = clause_LiteralAtom(Literal); + if (fol_IsEquality(Atom) && + !clause_LiteralIsOrientedEquality(Literal) && + (term_IsVariable(term_FirstArgument(Atom)) || + term_IsVariable(term_SecondArgument(Atom))) && + !term_VariableEqual(term_FirstArgument(Atom), + term_SecondArgument(Atom))) + return TRUE; + else + return FALSE; +} + + +static BOOL red_PropagateDefinitions(CLAUSE Clause, TERM LeadingTerm, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a term, a flag store and a precedence. + RETURNS: TRUE, iff any definitions in <Clause> where propagated, + false otherwise. + + Here, a definitions means a negative literal x=t, where + x is a variable and x doesn't occur in t. + Definitions are only propagated if all terms in the + resulting clause would be smaller than <LeadingTerm>. + The flag store and the precedence are only needed for + term comparisons with respect to the reduction ordering. + CAUTION: <Clause> is changed destructively! +***************************************************************/ +{ + LITERAL Lit; + TERM Term, Atom; + SYMBOL Var; + int i, last, j, lj; + BOOL success, applied; + LIST litsToRemove; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_PropagateDefinitions: clause is corrupted."); + misc_FinishErrorReport(); + } +#endif + + applied = FALSE; + litsToRemove = list_Nil(); /* collect indices of redundant literals */ + last = clause_LastAntecedentLitIndex(Clause); + + for (i = clause_FirstAntecedentLitIndex(Clause); i <= last; i++) { + Lit = clause_GetLiteral(Clause, i); + + if (red_LiteralIsDefinition(Lit)) { + /* <Lit> is an equation x=t where the variable x doesn't occur in t. */ + + Term = term_FirstArgument(clause_LiteralAtom(Lit)); + if (term_IsVariable(Term)) { + Var = term_TopSymbol(Term); + Term = term_SecondArgument(clause_LiteralAtom(Lit)); + } else { + Var = term_TopSymbol(term_SecondArgument(clause_LiteralAtom(Lit))); + } + + /* Establish variable binding x -> t in context */ +#ifdef CHECK + cont_SaveState(); +#endif + cont_StartBinding(); + cont_CreateBinding(cont_LeftContext(), Var, cont_InstanceContext(), Term); + + /* Check that for each literal u=v (A=tt) the conditions */ + /* u{x->t} < LeadingTerm and v{x->t} < LeadingTerm (A < LeadingTerm) */ + /* hold. */ + success = TRUE; + Lit = NULL; + lj = clause_LastLitIndex(Clause); + + for (j = clause_FirstLitIndex(); j <= lj && success; j++) { + if (j != i) { + success = FALSE; + Lit = clause_GetLiteral(Clause, j); + Atom = clause_LiteralAtom(Lit); + if (fol_IsEquality(Atom)) { + /* Atom is an equation */ + if (ord_ContGreater(cont_InstanceContext(), LeadingTerm, + cont_LeftContext(), term_FirstArgument(Atom), + Flags, Precedence) && + (clause_LiteralIsOrientedEquality(Lit) || + ord_ContGreater(cont_InstanceContext(), LeadingTerm, + cont_LeftContext(), term_SecondArgument(Atom), + Flags, Precedence))) + /* Compare only with left (i.e. greater) subterm if the atom is */ + /* an oriented equation. */ + success = TRUE; + } else { + /* Atom is not an equation */ + if (ord_ContGreater(cont_InstanceContext(), LeadingTerm, + cont_LeftContext(), Atom, Flags, Precedence)) + success = TRUE; + } + } + } + + cont_BackTrack(); + +#ifdef CHECK + cont_CheckState(); +#endif + + if (success) { + /* Replace variable <Var> in <Clause> by <Term> */ + clause_ReplaceVariable(Clause, Var, Term); + /* The clause literals aren't reoriented here. For the detection of */ + /* definitions it suffices to know the non-oriented literals in the */ + /* original clause. */ + litsToRemove = list_Cons((POINTER)i, litsToRemove); + applied = TRUE; + } + } + } + + if (applied) { + /* Now remove the definition literals. */ + clause_DeleteLiterals(Clause, litsToRemove, Flags, Precedence); + list_Delete(litsToRemove); + + /* Equations have to be reoriented. */ + clause_OrientEqualities(Clause, Flags, Precedence); + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_PropagateDefinitions: clause is corrupted "); + misc_ErrorReport("after propagation of definitions"); + misc_FinishErrorReport(); + } +#endif + } + + return applied; +} + + +static CLAUSE red_CRwLitTautologyCheck(PROOFSEARCH Search, CLAUSE RedClause, + int Except, CLAUSE RuleClause, int i, + TERM LeadingTerm, NAT Mode) +/************************************************************** + INPUT: A proof search object, two clauses, two literal indices + (one per clause), a mode defining the clause index used + for intermediate reductions. + RETURNS: NULL, if the tautology check for literal <i> in <RuleClause> + failed. + + If the test succeeds an auxiliary clause is returned that + contains part of the splitting information for the current + rewriting step. If the 'DocProof' flag is set, the necessary + parent information is set, too. + MEMORY: Remember to delete the returned clause! +***************************************************************/ +{ + FLAGSTORE Flags; + PRECEDENCE Precedence; + CLAUSE aux, NewClause; + LITERAL Lit; + TERM Atom; + BOOL DocProof, Negative, Redundant; + LIST NegLits, PosLits, RedundantList; + int OrigNum; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + DocProof = flag_GetFlagValue(Flags, flag_DOCPROOF); + + Lit = clause_GetLiteral(RuleClause, i); + Atom = clause_LiteralAtom(Lit); + Negative = clause_LiteralIsNegative(Lit); + +#ifdef CRW_DEBUG + printf("\n ----------\n "); + if (Negative) + printf((i <= clause_LastConstraintLitIndex(RuleClause)) ? "Cons" : "Ante"); + else + printf("Succ"); + printf(" aux = "); +#endif + + if (i <= clause_LastConstraintLitIndex(RuleClause)) { + + /* Apply Sort Simplification for constraint literals only */ + NegLits = list_List(term_Copy(Atom)); + aux = clause_Create(NegLits, list_Nil(), list_Nil(), Flags, Precedence); + clause_SetTemporary(aux); + list_Delete(NegLits); + +#ifdef CRW_DEBUG + clause_Print(aux); +#endif + + NewClause = NULL; + OrigNum = clause_Number(aux); + if (red_SortSimplification(prfs_DynamicSortTheory(Search), aux, NAT_MAX, + DocProof, Flags, Precedence, &NewClause)) { + /* Sort Simplification was possible, so the unit clause was reduced */ + /* to the empty clause. */ + + /* The splitting information is already set in <aux> or <NewClause>. */ + if (DocProof) + /* If 'DocProof' is turned on, a copy was created and assigned */ + /* to <NewClause>. */ + red_CRwCalculateAdditionalParents(NewClause, list_Nil(), NULL, OrigNum); + + if (NewClause != NULL) { + clause_Delete(aux); + return NewClause; + } else + return aux; + } + clause_Delete(aux); + +#ifdef CRW_DEBUG + printf("\n Cons aux2 = "); +#endif + } + + /* Collect literals for tautology test */ + if (Negative) { + if (i <= clause_LastConstraintLitIndex(RuleClause)) + NegLits = clause_CopyConstraint(RedClause); + else + NegLits = clause_CopyAntecedentExcept(RedClause, Except); + PosLits = list_List(term_Copy(Atom)); + } else { + NegLits = list_List(term_Copy(Atom)); + PosLits = clause_CopySuccedentExcept(RedClause, Except); + } + + /* Create clause for tautology test */ + aux = clause_Create(list_Nil(), NegLits, PosLits, Flags, Precedence); + clause_SetTemporary(aux); + list_Delete(NegLits); + list_Delete(PosLits); + +#ifdef CRW_DEBUG + clause_Print(aux); +#endif + + /* Apply special reduction. Propagate definitions x=t if for all literals */ + /* u=v (A=tt) of the resulting clause the conditions holds: */ + /* LeadingTerm > u{x->t} and LeadingTerm > v{x->t} (LeadingTerm > A{x->t}. */ + if (red_PropagateDefinitions(aux, LeadingTerm, Flags, Precedence)) { +#ifdef CRW_DEBUG + printf("\n After propagation of definitions:\n aux = "); + clause_Print(aux); +#endif + } + + /* Invoke forward reduction and tautology test */ + NewClause = NULL; + RedundantList = list_Nil(); + OrigNum = clause_Number(aux); + Redundant = red_SelectedStaticReductions(Search, &aux, &NewClause, + &RedundantList, Mode); + clause_SetTemporary(aux); + /* <aux> was possibly changed by some reductions, so mark it as */ + /* temporary again. */ + + /* Invoke tautology test if <aux> isn't redundant. */ + if (Redundant || (!clause_IsEmptyClause(aux) && cc_Tautology(aux))) { + + if (NewClause != NULL) + /* <aux> is subsumed by <NewClause> */ + clause_UpdateSplitDataFromPartner(aux, NewClause); + + if (DocProof) + red_CRwCalculateAdditionalParents(aux, RedundantList, NewClause, OrigNum); + } else { + /* test failed */ + + clause_Delete(aux); + aux = NULL; + } + +#ifdef CRW_DEBUG + if (aux != NULL) { + if (NewClause != NULL) { + printf("\n Subsumer = "); + clause_Print(NewClause); + } + if (!list_Empty(RedundantList)) { + printf("\n RedundantList: "); + clause_ListPrint(RedundantList); + } + + printf("\n aux reduced = "); + clause_Print(aux); + } + printf("\n ----------"); +#endif + + /* Delete list of redundant clauses */ + clause_DeleteClauseList(RedundantList); + + return aux; +} + + +static BOOL red_CRwTautologyCheck(PROOFSEARCH Search, CLAUSE RedClause, int i, + TERM TermSInstance, CLAUSE RuleClause, + int j, NAT Mode, CLAUSE *Result) +/************************************************************** + INPUT: A proof search object, two clauses, two literal indices + (one per clause), <TermSInstance> is a subterm of + literal <i> in <RedClause>, a mode defining the clause + index used for intermediate reductions, and a pointer + to a clause used as return value. + RETURNS: FALSE, if the clauses failed some tautology test or + the literal <i> in <RedClause> is not greater than literal + <j> in <RedClause> with the substitution <sigma> applied. + In this case <Result> is set to NULL. + + TRUE is returned if the clauses passed all tautology tests + and literal <i> in <RedClause> is greater than literal <j> + in <RuleClause> with the substitution <sigma> applied. + In some cases <Result> is set to some auxiliary clause. + This is done if some clauses from the index were used to + reduce the intermediate clauses before the tautology test. + The auxiliary clause is used to return the necessary splitting + information for the current rewriting step. + If the <DocProof> flag is true, the information about + parent clauses is set in <Result>, too. + MEMORY: Remember to delete the <Result> clause if it is not NULL. +***************************************************************/ +{ + FLAGSTORE Flags, BackupFlags; + PRECEDENCE Precedence; + CLAUSE RuleCopy, aux; + TERM TermS; + int last, h; + BOOL Rewrite; + +#ifdef CHECK + if (!clause_LiteralIsOrientedEquality(clause_GetLiteral(RuleClause, j))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_CRwTautologyCheck:"); + misc_ErrorReport(" literal %d in <RuleClause> %d", j, + clause_Number(RuleClause)); + misc_ErrorReport(" isn't an oriented equation"); + misc_FinishErrorReport(); + } +#endif + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + *Result = NULL; + + /* copy <RuleClause> and rename variables in copy */ + RuleCopy = clause_Copy(RuleClause); + clause_RenameVarsBiggerThan(RuleCopy, clause_MaxVar(RedClause)); + TermS = term_FirstArgument(clause_GetLiteralAtom(RuleCopy, j)); + + /* Remove parent information of copied clause and mark it as temporary */ + list_Delete(clause_ParentClauses(RuleCopy)); + clause_SetParentClauses(RuleCopy, list_Nil()); + list_Delete(clause_ParentLiterals(RuleCopy)); + clause_SetParentLiterals(RuleCopy, list_Nil()); + clause_SetTemporary(RuleCopy); + + /* establish bindings */ + cont_StartBinding(); + if (!unify_MatchBindings(cont_LeftContext(), TermS, TermSInstance)) { +#ifdef CHECK + misc_StartErrorReport(); + misc_ErrorReport("\n In red_CRwTautologyCheck: terms aren't matchable"); + misc_FinishErrorReport(); +#endif + } + + /* Apply bindings to equation s=t, where s > t. Here the strict version */ + /* of cont_Apply... can be applied, because all variables in s and t */ + /* are bound. */ + cont_ApplyBindingsModuloMatching(cont_LeftContext(), + clause_GetLiteralAtom(RuleCopy, j), + TRUE); + + /* Check whether E > (s=t)sigma. It suffices to check only positive */ + /* equations. All other cases imply the condition. */ + if (i >= clause_FirstSuccedentLitIndex(RedClause) && + clause_LiteralIsEquality(clause_GetLiteral(RedClause, i)) && + ord_LiteralCompare(clause_GetLiteralTerm(RedClause, i), + clause_LiteralIsOrientedEquality(clause_GetLiteral(RedClause, i)), + clause_GetLiteralTerm(RuleCopy, j), TRUE, + FALSE, Flags, Precedence) != ord_GREATER_THAN) { + cont_BackTrack(); + clause_Delete(RuleCopy); + return FALSE; + } + + /* if (subs_SubsumesBasic(RuleClause, RedClause, j, i)) { Potential improvement, not completely + cont_BackTrack(); developed .... + return TRUE; + } else */ + { + int OldClauseCounter; + /* Apply bindings to the rest of <RuleCopy> */ + last = clause_LastLitIndex(RuleCopy); + for (h = clause_FirstLitIndex(); h <= last; h++) { + if (h != j) + cont_ApplyBindingsModuloMatching(cont_LeftContext(), + clause_GetLiteralAtom(RuleCopy, h), + FALSE); + } + + /* Backtrack bindings before reduction rules are invoked */ + cont_BackTrack(); + + /* Create new flag store and save current settings. Must be improved **** */ + /* Then turn off flags for printing and contextual rewriting. */ + /* IMPORTANT: the DocProof flag mustn't be changed! */ + BackupFlags = flag_CreateStore(); + flag_TransferAllFlags(Flags, BackupFlags); +#ifndef CRW_DEBUG + flag_ClearPrinting(Flags); +#else + { /* HACK: turn on all printing flags for debugging */ + FLAG_ID f; + + for (f = (FLAG_ID) 0; f < flag_MAXFLAG; f++) { + if (flag_IsPrinting(f)) + flag_SetFlagValue(Flags, f, flag_ON); + } + } +#endif + + /* ATTENTION: to apply CRw recursively, uncomment the following */ + /* line and comment out the following two lines! */ + /* flag_SetFlagValue(Flags, flag_RFCRW, flag_RFCRWON); */ + flag_SetFlagValue(Flags, flag_RBCRW, flag_RBCRWOFF); + flag_SetFlagValue(Flags, flag_RFCRW, flag_RFCRWOFF); + + /* Examine all literals of <RuleCopy> except <j> */ + Rewrite = TRUE; + last = clause_LastLitIndex(RuleCopy); + OldClauseCounter = clause_Counter(); + + for (h = clause_FirstLitIndex(); Rewrite && h <= last; h++) { + if (h != j) { + aux = red_CRwLitTautologyCheck(Search, RedClause, i, RuleCopy, h, + TermSInstance, Mode); + if (aux == NULL) + Rewrite = FALSE; + else { + /* Store splitting data of <aux> in RuleCopy */ + clause_UpdateSplitDataFromPartner(RuleCopy, aux); + /* Collect additonal parent information, if <DocProof> is turned on */ + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) { + clause_SetParentClauses(RuleCopy, + list_Nconc(clause_ParentClauses(aux), + clause_ParentClauses(RuleCopy))); + clause_SetParentLiterals(RuleCopy, + list_Nconc(clause_ParentLiterals(aux), + clause_ParentLiterals(RuleCopy))); + clause_SetParentClauses(aux, list_Nil()); + clause_SetParentLiterals(aux, list_Nil()); + } + clause_Delete(aux); + } + } + } + /* restore clause counter */ + clause_SetCounter(OldClauseCounter); + + /* reset flag store of proof search object and free backup store */ + flag_TransferAllFlags(BackupFlags, Flags); + flag_DeleteStore(BackupFlags); + } + + if (Rewrite) + *Result = RuleCopy; + else + /* cleanup */ + clause_Delete(RuleCopy); + + return Rewrite; +} + + +static void red_DocumentContextualRewriting(CLAUSE Clause, int i, + CLAUSE RuleClause, int ri, + LIST AdditionalPClauses, + LIST AdditionalPLits) +/************************************************************** + INPUT: Two clauses and two literal indices (one per clause), + and two lists of additional parent clause numbers and + parent literals. + RETURNS: Nothing. + EFFECT: <Clause> is rewritten for the first time by + Contextual Rewriting. This function sets the parent + clause and parent literal information in <Clause>. + <Clause> gets a new clause number. + CAUTION: The lists are not copied! +***************************************************************/ +{ +#ifdef CHECK + if (list_Length(AdditionalPClauses) != list_Length(AdditionalPLits)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_DocumentContextualRewriting: lists of parent "); + misc_ErrorReport("clauses\n and literals have different length."); + misc_FinishErrorReport(); + } +#endif + + list_Delete(clause_ParentClauses(Clause)); + list_Delete(clause_ParentLiterals(Clause)); + clause_SetParentClauses(Clause, AdditionalPClauses); + clause_SetParentLiterals(Clause, AdditionalPLits); + /* Add the old number of <Clause> as parent clause, */ + /* before it gets a new clause number. */ + clause_AddParentClause(Clause, clause_Number(Clause)); + clause_AddParentLiteral(Clause, i); + clause_AddParentClause(Clause, clause_Number(RuleClause)); + clause_AddParentLiteral(Clause, ri); + + clause_NewNumber(Clause); + clause_SetFromContextualRewriting(Clause); +} + + +static void red_DocumentFurtherCRw(CLAUSE Clause, int i, CLAUSE RuleClause, + int ri, LIST AdditionalPClauses, + LIST AdditionalPLits) +/************************************************************** + INPUT: Two clauses, two literal indices (one per clause), + and two lists of additional parent clause numbers and + parent literal indices. + RETURNS: Nothing. + EFFECT: <Clause> is a clause, that was rewritten before by + Contextual Rewriting. This function adds the parent + clause and parent literal information from one more + rewriting step to <Clause>. The information is added + to the front of the respective lists. + CAUTION: The lists are not copied! +***************************************************************/ +{ + int PClauseNum; + +#ifdef CHECK + if (list_Length(AdditionalPClauses) != list_Length(AdditionalPLits)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_DocumentFurtherCRw: lists of parent "); + misc_ErrorReport("clauses\n and literals have different length."); + misc_FinishErrorReport(); + } +#endif + + PClauseNum = (int)list_Second(clause_ParentClauses(Clause)); + + clause_SetParentClauses(Clause, list_Nconc(AdditionalPClauses, + clause_ParentClauses(Clause))); + clause_SetParentLiterals(Clause, list_Nconc(AdditionalPLits, + clause_ParentLiterals(Clause))); + + clause_AddParentClause(Clause, PClauseNum); + clause_AddParentLiteral(Clause, i); + clause_AddParentClause(Clause, clause_Number(RuleClause)); + clause_AddParentLiteral(Clause, ri); +} + + +static BOOL red_ContextualRewriting(PROOFSEARCH Search, CLAUSE RedClause, + NAT Mode, int Level, CLAUSE *Changed) +/************************************************************** + INPUT: A proof search object, a clause to reduce, the + reduction mode which defines the clause set used for + reduction, a split level indicating the need of a copy + if <Clause> is reduced by a clause of higher split level + than <Level>, and a pointer to a clause used as return value. + RETURNS: TRUE, if contextual rewriting was possible, FALSE otherwise. + If rewriting was possible and the <DocProof> flag is true + or the split level of the rewrite rule is higher than + <Level>, a copy of <RedClause> that is rewritten wrt. + the indexed clauses is returned in <*Changed>. + Otherwise the clause is destructively rewritten and + returned. + CAUTION: If rewriting wasn't applied, the value of <*Changed> + isn't set explicitely in this function. +***************************************************************/ +{ + TERM RedAtom, RedTermS; + int B_Stack; + int ri, last; + BOOL Rewritten, Result, Document; + TERM TermS, PartnerEq; + LIST Gen, EqScan, LitScan; + CLAUSE Copy; + FLAGSTORE Flags; + PRECEDENCE Precedence; + SHARED_INDEX ShIndex; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + +#ifdef CHECK + if (!clause_IsClause(RedClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_ContextualRewriting: Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedClause, Flags, Precedence); +#endif + + /* Select clause index */ + if (red_WorkedOffMode(Mode)) + ShIndex = prfs_WorkedOffSharingIndex(Search); + else + ShIndex = prfs_UsableSharingIndex(Search); + + last = clause_LastSuccedentLitIndex(RedClause); + Document = flag_GetFlagValue(Flags, flag_DOCPROOF); + + Result = FALSE; + Copy = RedClause; + + /* Don't apply this rule on constraint literals! */ + for (ri = clause_FirstAntecedentLitIndex(RedClause); ri <= last; ri++) { + if (!list_Empty(term_ArgumentList(clause_GetLiteralAtom(Copy, ri)))) { + Rewritten = TRUE; + while (Rewritten) { + Rewritten = FALSE; + RedAtom = clause_GetLiteralAtom(Copy, ri); + + B_Stack = stack_Bottom(); + /* push subterms on stack except variables */ + sharing_PushListReverseOnStack(term_ArgumentList(RedAtom)); + + while (!stack_Empty(B_Stack)) { + RedTermS = (TERM)stack_PopResult(); + Gen = st_GetGen(cont_LeftContext(), sharing_Index(ShIndex), RedTermS); + + for ( ; !list_Empty(Gen) && !Rewritten; Gen = list_Pop(Gen)) { + TermS = list_Car(Gen); + + /* A variable can't be greater than any other term, */ + /* so don't consider any variables here. */ + if (!term_IsVariable(TermS)) { + EqScan = term_SupertermList(TermS); + + for ( ; !list_Empty(EqScan) && !Rewritten; + EqScan = list_Cdr(EqScan)) { + PartnerEq = list_Car(EqScan); + if (fol_IsEquality(PartnerEq) && + (term_FirstArgument(PartnerEq) == TermS)) { + CLAUSE RuleClause, HelpClause; + LITERAL RuleLit; + int i; + + for (LitScan = sharing_NAtomDataList(PartnerEq); + !list_Empty(LitScan) && !Rewritten; + LitScan = list_Cdr(LitScan)) { + RuleLit = list_Car(LitScan); + RuleClause = clause_LiteralOwningClause(RuleLit); + i = clause_LiteralGetIndex(RuleLit); + HelpClause = NULL; + +#ifdef CRW_DEBUG + if (clause_LiteralIsPositive(RuleLit) && + clause_LiteralGetFlag(RuleLit,STRICTMAXIMAL) && + clause_LiteralIsOrientedEquality(RuleLit) && + red_LeftTermOfEquationIsStrictlyMaximalTerm(RuleClause, + RuleLit, + Flags, + Precedence)) { + printf("\n------\nFCRw: %s\n%d ", red_WorkedOffMode(Mode) + ? "WorkedOff" : "Usable", i); + clause_Print(RuleClause); + printf("\n%d ", ri); + clause_Print(RedClause); + } +#endif + + if (clause_LiteralIsPositive(RuleLit) && + clause_LiteralGetFlag(RuleLit,STRICTMAXIMAL) && + clause_LiteralIsOrientedEquality(RuleLit) && + red_LeftTermOfEquationIsStrictlyMaximalTerm(RuleClause, + RuleLit, + Flags, + Precedence) && + red_CRwTautologyCheck(Search, Copy, ri, RedTermS, + RuleClause, i, Mode, + &HelpClause)) { + TERM TermT; + + if (RedClause == Copy && + (Document || + prfs_SplitLevelCondition(clause_SplitLevel(RuleClause), + clause_SplitLevel(RedClause),Level) || + prfs_SplitLevelCondition(clause_SplitLevel(HelpClause), + clause_SplitLevel(RedClause), + Level))) { + Copy = clause_Copy(RedClause); + RedAtom = clause_GetLiteralAtom(Copy, ri); + } + + if (!Result && flag_GetFlagValue(Flags, flag_PCRW)) { + /* Clause is rewitten for the first time and */ + /* printing is turned on. */ + fputs("\nFContRewriting: ", stdout); + clause_Print(Copy); + fputs(" ==>[ ", stdout); + } + + if (Document) { + LIST PClauses, PLits; + + /* Get additional parent information from */ + /* <HelpClause> */ + PClauses = PLits = list_Nil(); + if (HelpClause != NULL) { + PClauses = clause_ParentClauses(HelpClause); + PLits = clause_ParentLiterals(HelpClause); + clause_SetParentClauses(HelpClause, list_Nil()); + clause_SetParentLiterals(HelpClause, list_Nil()); + } else + PClauses = PLits = list_Nil(); + + if (!Result) + red_DocumentContextualRewriting(Copy, ri, + RuleClause, i, + PClauses, PLits); + else + red_DocumentFurtherCRw(Copy, ri, RuleClause, i, + PClauses, PLits); + } + Result = TRUE; + + cont_StartBinding(); + unify_MatchBindings(cont_LeftContext(), TermS, RedTermS); + TermT = cont_ApplyBindingsModuloMatching(cont_LeftContext(), + term_Copy(term_SecondArgument(PartnerEq)), + TRUE); + cont_BackTrack(); + + term_ReplaceSubtermBy(RedAtom, RedTermS, TermT); + Rewritten = TRUE; + /* Set splitting data from parents */ + clause_UpdateSplitDataFromPartner(Copy, RuleClause); + if (HelpClause != NULL) { + /* Store splitting data from intermediate clauses */ + clause_UpdateSplitDataFromPartner(Copy, HelpClause); + clause_Delete(HelpClause); + } + term_Delete(TermT); + stack_SetBottom(B_Stack); + + if (flag_GetFlagValue(Flags, flag_PCRW)) + printf("%d.%d ",clause_Number(RuleClause), i); + clause_UpdateWeight(Copy, Flags); + } + } + } + } + } + } + list_Delete(Gen); + } + } + } + } + if (Result) { + clause_OrientAndReInit(Copy, Flags, Precedence); + if (flag_GetFlagValue(Flags, flag_PCRW)) { + fputs("] ", stdout); + clause_Print(Copy); + } + if (Copy != RedClause) { + clause_OrientAndReInit(RedClause, Flags, Precedence); + *Changed = Copy; + } + } + +#ifdef CHECK + if (Copy != RedClause) + clause_Check(Copy, Flags, Precedence); + clause_Check(RedClause, Flags, Precedence); +#endif + + return Result; +} + + +static LIST red_BackSubsumption(CLAUSE RedCl, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence) +/********************************************************** + INPUT: A pointer to a non-empty clause, an index of + clauses, a flag store and a precedence. + RETURNS: The list of clauses that are subsumed by the + clause RedCl. +***********************************************************/ +{ + TERM Atom,CandTerm; + CLAUSE SubsumedCl; + LITERAL CandLit; + LIST CandLits, Scan, SubsumedList; + int i, j, lc, fa, la, fs, l; + +#ifdef CHECK + if (!clause_IsClause(RedCl, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_BackSubsumption :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedCl, Flags, Precedence); +#endif + + /* Special case: clause is empty */ + if (clause_IsEmptyClause(RedCl)) + return list_Nil(); + + SubsumedList = list_Nil(); + + lc = clause_LastConstraintLitIndex(RedCl); + fa = clause_FirstAntecedentLitIndex(RedCl); + la = clause_LastAntecedentLitIndex(RedCl); + fs = clause_FirstSuccedentLitIndex(RedCl); + l = clause_LastLitIndex(RedCl); + + /* Choose the literal with the greatest weight to start the search */ + i = clause_FirstLitIndex(); + for (j = i + 1; j <= l; j++) { + if (clause_LiteralWeight(clause_GetLiteral(RedCl, j)) > + clause_LiteralWeight(clause_GetLiteral(RedCl, i))) + i = j; + } + + Atom = clause_GetLiteralAtom(RedCl, i); + CandTerm = st_ExistInstance(cont_LeftContext(), sharing_Index(ShIndex), Atom); + + while (CandTerm) { + CandLits = sharing_NAtomDataList(CandTerm); + + for (Scan = CandLits; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + CandLit = list_Car(Scan); + SubsumedCl = clause_LiteralOwningClause(CandLit); + j = clause_LiteralGetIndex(CandLit); + + if (RedCl != SubsumedCl && + /* Literals must be from same part of the clause */ + ((i<=lc && clause_LiteralIsFromConstraint(CandLit)) || + (i>=fa && i<=la && clause_LiteralIsFromAntecedent(CandLit)) || + (i>=fs && clause_LiteralIsFromSuccedent(CandLit))) && + !list_PointerMember(SubsumedList, SubsumedCl) && + subs_SubsumesBasic(RedCl, SubsumedCl, i, j)) + SubsumedList = list_Cons(SubsumedCl, SubsumedList); + } + + CandTerm = st_NextCandidate(); + } + + if (fol_IsEquality(Atom) && + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(RedCl, i))) { + Atom = term_Create(fol_Equality(), + list_Reverse(term_ArgumentList(Atom))); + CandTerm = st_ExistInstance(cont_LeftContext(), sharing_Index(ShIndex), Atom); + + while (CandTerm) { + CandLits = sharing_NAtomDataList(CandTerm); + + for (Scan = CandLits; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + CandLit = list_Car(Scan); + SubsumedCl = clause_LiteralOwningClause(list_Car(Scan)); + /* if (!clause_GetFlag(SubsumedCl, BLOCKED)) { */ + j = clause_LiteralGetIndex(list_Car(Scan)); + + if ((RedCl != SubsumedCl) && + /* Literals must be from same part of the clause */ + ((i<=lc && clause_LiteralIsFromConstraint(CandLit)) || + (i>=fa && i<=la && clause_LiteralIsFromAntecedent(CandLit)) || + (i>=fs && clause_LiteralIsFromSuccedent(CandLit))) && + !list_PointerMember(SubsumedList, SubsumedCl) && + subs_SubsumesBasic(RedCl, SubsumedCl, i, j)) + SubsumedList = list_Cons(SubsumedCl, SubsumedList); + /* } */ + } + + CandTerm = st_NextCandidate(); + } + + list_Delete(term_ArgumentList(Atom)); + term_Free(Atom); + } + + if (flag_GetFlagValue(Flags, flag_PSUB)) { + for (Scan = SubsumedList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + SubsumedCl = list_Car(Scan); + fputs("\nBSubsumption: ", stdout); + clause_Print(SubsumedCl); + printf(" by %d ",clause_Number(RedCl)); + } + } + return SubsumedList; +} + + +static LIST red_GetBackMRResLits(CLAUSE Clause, LITERAL ActLit, SHARED_INDEX ShIndex) +/************************************************************** + INPUT: A clause, one of its literals and an Index. + RETURNS: A list of clauses with a complementary literal instance + that are subsumed if these literals are ignored. + the empty list if no such clause exists. + MEMORY: Allocates the needed listnodes. +***************************************************************/ +{ + CLAUSE PClause; + LITERAL PLit; + LIST LitScan, PClLits; + TERM CandTerm; + int i; + + PClLits = list_Nil(); + i = clause_LiteralGetIndex(ActLit); + + CandTerm = st_ExistInstance(cont_LeftContext(), + sharing_Index(ShIndex), + clause_LiteralAtom(ActLit)); + + while (CandTerm) { + + LitScan = sharing_NAtomDataList(CandTerm); /* CAUTION ! */ + + for ( ; !list_Empty(LitScan); LitScan = list_Cdr(LitScan)) { + + PLit = list_Car(LitScan); + PClause = clause_LiteralOwningClause(PLit); + + if (PClause != Clause && + clause_LiteralsAreComplementary(ActLit,PLit) && + subs_SubsumesBasic(Clause,PClause,i,clause_LiteralGetIndex(PLit))) + PClLits = list_Cons(PLit, PClLits); + } + + CandTerm = st_NextCandidate(); + } + return PClLits; +} + + +static LIST red_BackMatchingReplacementResolution(CLAUSE RedClause, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence, + LIST* Result) +/************************************************************** + INPUT: A clause, a shared index, a flag store, a + precedence, and a pointer to a result list. + RETURNS: The return value itself contains a list of clauses + from <ShIndex> that is reducible by <RedClause> via + clause reduction. + The return value stored in <*Result> contains the + result of this operation. + If the <DocProof> flag is true then the clauses in + <*Result> contain information about the reduction. +***************************************************************/ +{ + LIST Blocked; + CLAUSE Copy; + BOOL Document; + +#ifdef CHECK + if (!clause_IsClause(RedClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_BackMatchingReplacementResolution:"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedClause, Flags, Precedence); +#endif + + Blocked = list_Nil(); + Document = flag_GetFlagValue(Flags, flag_DOCPROOF); + + if (clause_Length(RedClause) == 1) { + LITERAL ActLit, PLit; + LIST LitList, Scan, Iter; + TERM CandTerm; + int RedClNum; + + ActLit = clause_GetLiteral(RedClause, clause_FirstLitIndex()); + + if (!fol_IsEquality(clause_LiteralAtom(ActLit)) || /* Reduce with negative equations too */ + clause_LiteralIsNegative(ActLit)) { + CLAUSE PClause; + LIST PIndL; + + CandTerm = st_ExistInstance(cont_LeftContext(), sharing_Index(ShIndex), clause_LiteralAtom(ActLit)); + RedClNum = clause_Number(RedClause); + LitList = list_Nil(); + + while (CandTerm) { + for (Iter = sharing_NAtomDataList(CandTerm); !list_Empty(Iter); Iter = list_Cdr(Iter)) + if (clause_LiteralsAreComplementary(ActLit,list_Car(Iter))) + LitList = list_Cons(list_Car(Iter),LitList); + CandTerm = st_NextCandidate(); + } + + /* It is important to get all literals first, + because there may be several literals in the same clause which can be reduced by <ActLit> */ + + while (!list_Empty(LitList)) { + PLit = list_Car(LitList); + PIndL = list_List(PLit); + PClause = clause_LiteralOwningClause(PLit); + Blocked = list_Cons(PClause, Blocked); + + if (flag_GetFlagValue(Flags, flag_PMRR)) { + fputs("\nBMatchingReplacementResolution: ", stdout); + clause_Print(PClause); + printf(" ==>[ %d.%d ] ",clause_Number(RedClause),clause_FirstLitIndex()); + } + + Iter = LitList; + for (Scan=list_Cdr(LitList);!list_Empty(Scan);Scan=list_Cdr(Scan)) /* Get brothers of PLit */ + if (PClause == clause_LiteralOwningClause(list_Car(Scan))) { + list_Rplacd(Iter,list_Cdr(Scan)); + list_Rplacd(Scan,PIndL); + PIndL = Scan; + Scan = Iter; + } + else + Iter = Scan; + Iter = LitList; + LitList = list_Cdr(LitList); + list_Free(Iter); + Copy = clause_Copy(PClause); + clause_RemoveFlag(Copy,WORKEDOFF); + clause_UpdateSplitDataFromPartner(Copy, RedClause); + for(Scan=PIndL;!list_Empty(Scan);Scan=list_Cdr(Scan)) /* Change lits to indexes */ + list_Rplaca(Scan,(POINTER)clause_LiteralGetIndex(list_Car(Scan))); + clause_DeleteLiterals(Copy, PIndL, Flags, Precedence); + + if (Document) + /* Lists are consumed */ + red_DocumentMatchingReplacementResolution(Copy, PIndL, list_List((POINTER)RedClNum), + list_List((POINTER)clause_FirstLitIndex())); + + else + list_Delete(PIndL); + + if (flag_GetFlagValue(Flags, flag_PMRR)) + clause_Print(Copy); + *Result = list_Cons(Copy, *Result); + } + } + return Blocked; + } + else { + CLAUSE PClause; + LITERAL ActLit, PLit; + LIST LitScan,LitList; + int i,length,RedClNum,PInd; + + RedClNum = clause_Number(RedClause); + length = clause_Length(RedClause); + + for (i = clause_FirstLitIndex(); i < length; i++) { + ActLit = clause_GetLiteral(RedClause, i); + + if (!fol_IsEquality(clause_LiteralAtom(ActLit))) { + LitList = red_GetBackMRResLits(RedClause, ActLit, ShIndex); + + for (LitScan = LitList;!list_Empty(LitScan);LitScan = list_Cdr(LitScan)) { + PLit = list_Car(LitScan); + PClause = clause_LiteralOwningClause(PLit); + PInd = clause_LiteralGetIndex(PLit); + Copy = clause_Copy(PClause); + if (list_PointerMember(Blocked,PClause)) { + if (!flag_GetFlagValue(Flags, flag_DOCPROOF)) + clause_NewNumber(Copy); + } + else + Blocked = list_Cons(PClause, Blocked); + clause_RemoveFlag(Copy,WORKEDOFF); + clause_UpdateSplitDataFromPartner(Copy, RedClause); + clause_DeleteLiteral(Copy, PInd, Flags, Precedence); + + if (Document) + red_DocumentMatchingReplacementResolution(Copy, list_List((POINTER)PInd), + list_List((POINTER)RedClNum), + list_List((POINTER)i)); + + if (flag_GetFlagValue(Flags, flag_PMRR)) { + fputs("\nBMatchingReplacementResolution: ", stdout); + clause_Print(PClause); + printf(" ==>[ %d.%d ] ",clause_Number(RedClause),i); + clause_Print(Copy); + } + *Result = list_Cons(Copy, *Result); + } + list_Delete(LitList); + } + } + return Blocked; + } +} + + +static void red_ApplyRewriting(CLAUSE RuleCl, int ri, CLAUSE PartnerClause, + int pli, TERM PartnerTermS, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause to use for rewriting, the index of a + positive equality literal where the first equality + argument is greater, a clause, the index of a + literal with subterm <PartnerTermS> that can be + rewritten, a flag store and a precedence. + RETURNS: Nothing. + EFFECT: The atom of literal pli in PartnerClause is + destructively changed !!! + The <DocProof> flag is considered. +***************************************************************/ +{ + LITERAL PartnerLit; + TERM ReplaceTermT, NewAtom; + +#ifdef CHECK + clause_Check(PartnerClause, Flags, Precedence); + clause_Check(RuleCl, Flags, Precedence); +#endif + + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) + red_DocumentRewriting(PartnerClause, pli, RuleCl, ri); + + if (flag_GetFlagValue(Flags, flag_PREW)) { + fputs("\nBRewriting: ", stdout); + clause_Print(PartnerClause); + printf(" ==>[ %d.%d ] ", clause_Number(RuleCl), ri); + } + + PartnerLit = clause_GetLiteral(PartnerClause, pli); + + ReplaceTermT = + cont_ApplyBindingsModuloMatchingReverse(cont_LeftContext(), + term_Copy(term_SecondArgument(clause_GetLiteralTerm(RuleCl, ri)))); + + NewAtom = clause_LiteralSignedAtom(PartnerLit); + term_ReplaceSubtermBy(NewAtom, PartnerTermS, ReplaceTermT); + term_Delete(ReplaceTermT); + + clause_OrientAndReInit(PartnerClause, Flags, Precedence); + clause_UpdateSplitDataFromPartner(PartnerClause, RuleCl); + + if (flag_GetFlagValue(Flags, flag_PREW)) + clause_Print(PartnerClause); +} + + +static LIST red_LiteralRewriting(CLAUSE RedClause, LITERAL ActLit, int ri, + SHARED_INDEX ShIndex, FLAGSTORE Flags, + PRECEDENCE Precedence, LIST* Result) +/************************************************************** + INPUT: A clause, a positive equality literal where the + first equality argument is greater, its index, an + index of clauses, a flag store, a precedence and a + pointer to a list of clauses that were rewritten. + RETURNS: The list of clauses from the index that can be + rewritten by <ActLit> and <RedClause>. + The rewritten clauses are stored in <*Result>. + EFFECT: The <DocProof> flag is considered. +***************************************************************/ +{ + TERM TermS, CandTerm; + LIST Blocked; + +#ifdef CHECK + if (!clause_LiteralIsLiteral(ActLit) || !clause_LiteralIsEquality(ActLit) || + !clause_LiteralIsOrientedEquality(ActLit)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_LiteralRewriting: Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedClause, Flags, Precedence); +#endif + + Blocked = list_Nil(); + TermS = term_FirstArgument(clause_LiteralSignedAtom(ActLit)); /* Vars can't be greater ! */ + + CandTerm = st_ExistInstance(cont_LeftContext(), sharing_Index(ShIndex), TermS); + + while (CandTerm) { + + if (!term_IsVariable(CandTerm) && + !symbol_IsPredicate(term_TopSymbol(CandTerm))) { + LIST LitList; + + LitList = sharing_GetDataList(CandTerm, ShIndex); + + for ( ; !list_Empty(LitList); LitList = list_Pop(LitList)){ + LITERAL PartnerLit; + CLAUSE PartnerClause; + int pli; + + PartnerLit = list_Car(LitList); + pli = clause_LiteralGetIndex(PartnerLit); + PartnerClause = clause_LiteralOwningClause(PartnerLit); + + /* Partner literal must be from antecedent or succedent */ + if (clause_Number(RedClause) != clause_Number(PartnerClause) && + pli >= clause_FirstAntecedentLitIndex(PartnerClause) && + !list_PointerMember(Blocked, PartnerClause) && + subs_SubsumesBasic(RedClause, PartnerClause, ri, pli)) { + CLAUSE Copy; + + Blocked = list_Cons(PartnerClause, Blocked); + Copy = clause_Copy(PartnerClause); + clause_RemoveFlag(Copy, WORKEDOFF); + red_ApplyRewriting(RedClause, ri, Copy, pli, CandTerm, + Flags, Precedence); + *Result = list_Cons(Copy, *Result); + } + } + } + CandTerm = st_NextCandidate(); + } + return Blocked; +} + + +static LIST red_BackRewriting(CLAUSE RedClause, SHARED_INDEX ShIndex, + FLAGSTORE Flags, PRECEDENCE Precedence, + LIST* Result) +/************************************************************** + INPUT: A clause, and Index, a flag store, a precedence and + a pointer to the list of rewritten clauses. + RETURNS: A list of clauses that can be rewritten with + <RedClause> and the result of this operation is + stored in <*Result>. + EFFECT: The <DocProof> flag is considered. +***************************************************************/ +{ + int i,length; + LITERAL ActLit; + LIST Blocked; + +#ifdef CHECK + if (!(clause_IsClause(RedClause, Flags, Precedence))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_BackRewriting :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedClause, Flags, Precedence); +#endif + + Blocked = list_Nil(); + length = clause_Length(RedClause); + + for (i=clause_FirstSuccedentLitIndex(RedClause); i < length; i++) { + ActLit = clause_GetLiteral(RedClause, i); + if (clause_LiteralIsOrientedEquality(ActLit)) { + Blocked = list_Nconc(red_LiteralRewriting(RedClause, ActLit, i, + ShIndex, Flags, Precedence, + Result), + Blocked); + } + +#ifdef CHECK + if (fol_IsEquality(clause_LiteralSignedAtom(ActLit))) { + ord_RESULT HelpRes; + + HelpRes = + ord_Compare(term_FirstArgument(clause_LiteralSignedAtom(ActLit)), + term_SecondArgument(clause_LiteralSignedAtom(ActLit)), + Flags, Precedence); + + if (ord_IsSmallerThan(HelpRes)){ /* For Debugging */ + misc_StartErrorReport(); + misc_ErrorReport("\n In red_BackRewriting:"); + misc_ErrorReport("First Argument smaller than second in RedClause.\n"); + misc_FinishErrorReport(); + } + } /* end of if (fol_IsEquality). */ +#endif + } /* end of for 'all succedent literals'. */ + Blocked = list_PointerDeleteDuplicates(Blocked); + return Blocked; +} + + +/**************************************************************/ +/* BACKWARD CONTEXTUAL REWRITING */ +/**************************************************************/ + +static LIST red_BackCRwOnLiteral(PROOFSEARCH Search, CLAUSE RuleClause, + LITERAL Lit, int i, NAT Mode, LIST* Result) +/************************************************************** + INPUT: A proof search object, a clause that is used to rewrite + other clauses, a positive literal from the clause, + that is a strictly maximal, oriented equation, the index + of the literal, a mode defining which clause index + is used to find rewritable clauses, and a pointer + to a list that is used as return value. + The left term of the equation has to be the strictly + maximal term in the clause, i.e. it is bigger than + any other term. + RETURNS: The list of clauses from the clause index that can be + rewritten by <Lit> and <RuleClause>. + The rewritten clauses are stored in <*Result>. + EFFECT: The <DocProof> flag is considered. +***************************************************************/ +{ + TERM TermS, CandTerm, ReplaceTermT; + LIST Inst, Blocked; + FLAGSTORE Flags; + PRECEDENCE Precedence; + SHARED_INDEX ShIndex; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + if (red_WorkedOffMode(Mode)) + ShIndex = prfs_WorkedOffSharingIndex(Search); + else + ShIndex = prfs_UsableSharingIndex(Search); + +#ifdef CHECK + if (!clause_LiteralIsLiteral(Lit) || !clause_LiteralIsEquality(Lit) || + !clause_LiteralGetFlag(Lit, STRICTMAXIMAL) || + !clause_LiteralIsOrientedEquality(Lit)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_BackCRwOnLiteral: Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RuleClause, Flags, Precedence); +#endif + + Blocked = list_Nil(); + TermS = term_FirstArgument(clause_LiteralSignedAtom(Lit)); + + /* Get all instances of <TermS> at once. This can't be done iteratively */ + /* since other reduction rules are invoked within the following loop. */ + Inst = st_GetInstance(cont_LeftContext(), sharing_Index(ShIndex), TermS); + + for ( ; !list_Empty(Inst); Inst = list_Pop(Inst)) { + CandTerm = list_Car(Inst); + + if (!term_IsVariable(CandTerm) && + !symbol_IsPredicate(term_TopSymbol(CandTerm))) { + LIST LitList; + + LitList = sharing_GetDataList(CandTerm, ShIndex); + + for ( ; !list_Empty(LitList); LitList = list_Pop(LitList)){ + LITERAL RedLit; + CLAUSE RedClause, HelpClause; + int ri; + + RedLit = list_Car(LitList); + ri = clause_LiteralGetIndex(RedLit); + RedClause = clause_LiteralOwningClause(RedLit); + HelpClause = NULL; + +#ifdef CRW_DEBUG + if (clause_Number(RuleClause) != clause_Number(RedClause) && + ri >= clause_FirstAntecedentLitIndex(RedClause) && + !list_PointerMember(Blocked, RedClause)) { + printf("\n------\nBCRw: %s\n%d ", red_WorkedOffMode(Mode) ? + "WorkedOff" : "Usable", i); + clause_Print(RuleClause); + printf("\n%d ", ri); + clause_Print(RedClause); + } +#endif + + /* Partner literal must be from antecedent or succedent */ + if (clause_Number(RuleClause) != clause_Number(RedClause) && + ri >= clause_FirstAntecedentLitIndex(RedClause) && + /* Check that clause wasn't already rewritten by this literal. */ + /* Necessary because then the old version of the clause is still */ + /* in the index, but the rewritten version in not in the index. */ + !list_PointerMember(Blocked, RedClause) && + red_CRwTautologyCheck(Search, RedClause, ri, CandTerm, + RuleClause, i, Mode, &HelpClause)) { + CLAUSE Copy; + + /* The <PartnerClause> has to be copied because it's indexed. */ + Blocked = list_Cons(RedClause, Blocked); + Copy = clause_Copy(RedClause); + clause_RemoveFlag(Copy, WORKEDOFF); + + /* Establish bindings */ + cont_StartBinding(); + if (!unify_MatchBindings(cont_LeftContext(), TermS, CandTerm)) { +#ifdef CHECK + misc_StartErrorReport(); + misc_ErrorReport("\n In red_BackCRwOnLiteral: terms aren't "); + misc_ErrorReport("matchable."); + misc_FinishErrorReport(); +#endif + } + /* The variable check in cont_ApplyBindings... is turned on here */ + /* because all variables is s are bound, and s > t. So all */ + /* variables in t are bound, too. */ + ReplaceTermT = + cont_ApplyBindingsModuloMatching(cont_LeftContext(), + term_Copy(term_SecondArgument(clause_GetLiteralTerm(RuleClause, i))), + TRUE); + cont_BackTrack(); + + /* Modify copied clause */ + term_ReplaceSubtermBy(clause_GetLiteralAtom(Copy, ri), CandTerm, + ReplaceTermT); + term_Delete(ReplaceTermT); + + /* Proof documentation */ + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) { + LIST PClauses, PLits; + + if (HelpClause != NULL) { + /* Get additional parent clauses and literals from the */ + /* tautology check. */ + PClauses = clause_ParentClauses(HelpClause); + PLits = clause_ParentLiterals(HelpClause); + clause_SetParentClauses(HelpClause, list_Nil()); + clause_SetParentLiterals(HelpClause, list_Nil()); + } else + PClauses = PLits = list_Nil(); + + red_DocumentContextualRewriting(Copy, ri, RuleClause, i, + PClauses, PLits); + } + + /* Set splitting data according to all parents */ + clause_UpdateSplitDataFromPartner(Copy, RuleClause); + if (HelpClause != NULL) { + clause_UpdateSplitDataFromPartner(Copy, HelpClause); + clause_Delete(HelpClause); + } + + clause_OrientAndReInit(Copy, Flags, Precedence); + + if (flag_GetFlagValue(Flags, flag_PCRW)) { + fputs("\nBContRewriting: ", stdout); + clause_Print(RedClause); + printf(" ==>[ %d.%d ] ", clause_Number(RuleClause), i); + clause_Print(Copy); + } + + *Result = list_Cons(Copy, *Result); + } + } + } + } + + return Blocked; +} + + +static LIST red_BackContextualRewriting(PROOFSEARCH Search, CLAUSE RuleClause, + NAT Mode, LIST* Result) +/************************************************************** + INPUT: A proof search object, a clause that is used to rewrite + other clauses, a mode flag that indicates which clause + index is used to find rewritable clauses, and a pointer + to a list that is used as return value. + RETURNS: A list of clauses that can be reduced + with Contextual Rewriting with <RuleClause>. + The clauses resulting from the rewriting steps are + stored in <*Result>. + EFFECT: The <DocProof> flag is considered. Every rewritable clause + is copied before rewriting is applied! This has to be done, + because the rewritable clauses are indexed. +***************************************************************/ +{ + BOOL found; + int i, ls; + LITERAL Lit; + LIST Blocked; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + +#ifdef CHECK + if (!clause_IsClause(RuleClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_BackContextualRewriting: Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RuleClause, Flags, Precedence); +#endif + + Blocked = list_Nil(); + ls = clause_LastSuccedentLitIndex(RuleClause); + found = FALSE; + + for (i = clause_FirstSuccedentLitIndex(RuleClause); i <= ls && !found; i++) { + Lit = clause_GetLiteral(RuleClause, i); + if (clause_LiteralIsOrientedEquality(Lit) && + clause_LiteralGetFlag(Lit, STRICTMAXIMAL) && + red_LeftTermOfEquationIsStrictlyMaximalTerm(RuleClause, Lit, Flags, + Precedence)) { + Blocked = list_Nconc(red_BackCRwOnLiteral(Search, RuleClause, Lit, i, + Mode, Result), + Blocked); + /* Stop loop: there's only one strictly maximal term per clause */ + found = TRUE; + } + } + + Blocked = list_PointerDeleteDuplicates(Blocked); + return Blocked; +} + + +static void red_DocumentSortSimplification(CLAUSE Clause, LIST Indexes, + LIST Clauses) +/********************************************************* + INPUT: A clause and the literal indices and clauses + involved in sort simplification. + RETURNS: Nothing. + MEMORY: Consumes the input lists. +**********************************************************/ +{ + LIST Scan,Declarations,Self; + + Declarations = list_Nil(); + Self = list_Nil(); + + list_Delete(clause_ParentClauses(Clause)); + list_Delete(clause_ParentLiterals(Clause)); + + for(Scan=Indexes;!list_Empty(Scan);Scan=list_Cdr(Scan)) + Self = list_Cons((POINTER)clause_Number(Clause),Self); + + for(Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Declarations = list_Cons((POINTER)clause_FirstSuccedentLitIndex(list_Car(Scan)),Declarations); + list_Rplaca(Scan,(POINTER)clause_Number(list_Car(Scan))); + } + + clause_SetParentLiterals(Clause, list_Nconc(Indexes,Declarations)); + clause_SetParentClauses(Clause, list_Nconc(Self,Clauses)); + + clause_SetNumber(Clause, clause_IncreaseCounter()); + clause_SetFromSortSimplification(Clause); +} + + +static BOOL red_SortSimplification(SORTTHEORY Theory, CLAUSE Clause, NAT Level, + BOOL Document, FLAGSTORE Flags, + PRECEDENCE Precedence, CLAUSE *Changed) +/********************************************************** + INPUT: A sort theory, a clause, the last backtrack + level of the current proof search, a boolean + flag concerning proof documentation, a flag + store and a precedence. + RETURNS: TRUE iff sort simplification was possible. + If <Document> is true or the split level of the + used declaration clauses requires copying a + simplified copy of the clause is returned in + <*Changed>. + Otherwise the clause is destructively + simplified. +***********************************************************/ +{ + if (Theory != (SORTTHEORY)NULL) { + TERM Atom,Term; + SOJU SortPair; + SORT TermSort,LitSort; + LIST Indexes,NewClauses,Clauses,Scan; + int i,lc,j,OldSplitLevel; + CLAUSE Copy; + CONDITION Cond; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_SortSimplification :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(Clause, Flags, Precedence); +#endif + + lc = clause_LastConstraintLitIndex(Clause); + i = clause_FirstLitIndex(); + j = 0; + OldSplitLevel = clause_SplitLevel(Clause); + Copy = Clause; + Indexes = list_Nil(); + Clauses = list_Nil(); + + while (i <= lc) { + + Atom = clause_LiteralAtom(clause_GetLiteral(Copy, i)); + Term = term_FirstArgument(Atom); + SortPair = sort_ComputeSortNoResidues(Theory, Term, Copy, i, + Flags, Precedence); + TermSort = sort_PairSort(SortPair); + NewClauses = sort_ConditionClauses(sort_PairCondition(SortPair)); + sort_ConditionPutClauses(sort_PairCondition(SortPair),list_Nil()); + LitSort = sort_TheorySortOfSymbol(Theory,term_TopSymbol(Atom)); + + if ((Cond = sort_TheoryIsSubsortOfNoResidues(Theory, TermSort, LitSort)) != (CONDITION)NULL) { + + if (j == 0 && flag_GetFlagValue(Flags, flag_PSSI)) { + fputs("\nSortSimplification: ", stdout); + clause_Print(Copy); + fputs(" ==>[ ", stdout); + } + + NewClauses = list_Nconc(NewClauses,sort_ConditionClauses(Cond)); + sort_ConditionPutClauses(Cond,list_Nil()); + sort_ConditionDelete(Cond); + + for (Scan = NewClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (Clause == Copy && + (Document || + prfs_SplitLevelCondition(clause_SplitLevel(list_Car(Scan)),OldSplitLevel,Level))) + Copy = clause_Copy(Clause); + clause_UpdateSplitDataFromPartner(Copy, list_Car(Scan)); + if (flag_GetFlagValue(Flags, flag_PSSI)) + printf("%d ",clause_Number(list_Car(Scan))); + } + + if (Document) + Indexes = list_Cons((POINTER)(i+j), Indexes); + + clause_DeleteLiteral(Copy, i, Flags, Precedence); + Clauses = list_Nconc(NewClauses,Clauses); + j++; + lc--; + } + else { + list_Delete(NewClauses); + i++; + } + sort_DeleteSortPair(SortPair); + sort_Delete(LitSort); + } + +#ifdef CHECK + clause_Check(Copy, Flags, Precedence); +#endif + + if (j > 0) { + if (Document) + red_DocumentSortSimplification(Copy,Indexes,Clauses); + else + list_Delete(Clauses); + clause_ReInit(Copy, Flags, Precedence); + if (flag_GetFlagValue(Flags, flag_PSSI)) { + fputs("] ", stdout); + clause_Print(Copy); + } + if (Copy != Clause) + *Changed = Copy; + return TRUE; + } + } + + return FALSE; +} + +static void red_ExchangeClauses(CLAUSE *RedClause, CLAUSE *Copy, LIST *Result) +/********************************************************** + INPUT: Two pointers to clauses and a pointer to a list. + RETURNS: Nothing. + EFFECT: If *Copy is NULL, nothing is done. Otherwise *RedClause + is added to the list, *Copy is assigned to *RedClause, + and NULL is assigned to *Copy. +***********************************************************/ +{ + if (*Copy) { + *Result = list_Cons(*RedClause,*Result); + *RedClause = *Copy; + *Copy = (CLAUSE)NULL; + } +} + + + +static BOOL red_SimpleStaticReductions(CLAUSE *RedClause, FLAGSTORE Flags, + PRECEDENCE Precedence, LIST* Result) +/********************************************************** + INPUT: A clause (by reference), a flag store and a + precedence. + RETURNS: TRUE if <*RedClause> is redundant. + If the <DocProof> flag is false and no copying is necessary + with respect to splitting, the clause is destructively changed, + otherwise (intermediate) copies are made and returned in <*Result>. + EFFECT: Used reductions are tautology deletion and + obvious reductions. +***********************************************************/ +{ + CLAUSE Copy; + BOOL DocProof; + +#ifdef CHECK + if (!clause_IsClause(*RedClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_SimpleStaticReductions :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(*RedClause, Flags, Precedence); +#endif + + Copy = (CLAUSE)NULL; + DocProof = flag_GetFlagValue(Flags, flag_DOCPROOF); + + if (flag_GetFlagValue(Flags, flag_RTAUT) != flag_RTAUTOFF && + red_Tautology(*RedClause, Flags, Precedence)) + return TRUE; + + if (flag_GetFlagValue(Flags, flag_ROBV)) { + red_ObviousReductions(*RedClause, DocProof, Flags, Precedence, &Copy); + red_ExchangeClauses(RedClause, &Copy, Result); + } + + if (flag_GetFlagValue(Flags, flag_RCON)) { + red_Condensing(*RedClause, DocProof, Flags, Precedence, &Copy); + red_ExchangeClauses(RedClause, &Copy, Result); + } + + return FALSE; +} + + + + +static BOOL red_StaticReductions(PROOFSEARCH Search, CLAUSE *Clause, + CLAUSE *Subsumer, LIST* Result, NAT Mode) +/********************************************************** + INPUT: A proof search object, a clause (by reference) to be reduced, + a shared index of clauses and the mode of the reductions, + determining which sets (Usable, WorkedOff) in <Search> + are considered for reductions. + RETURNS: TRUE iff the clause is redundant. + If the <DocProof> flag is false and no copying is necessary + with respect to splitting, the clause is destructively changed, + otherwise (intermediate) copies are made and returned in <*Result>. + If <Clause> gets redundant with respect to forward subsumption, + the subsuming clause is returned in <*Subsumer>. + EFFECT: Used reductions are tautology deletion, obvious reductions, + forward subsumption, forward rewriting, forward contextual + rewriting, forward matching replacement resolution, + sort simplification, unit conflict and static soft typing. + Depending on <Mode>, then clauses are reduced with respect + to WorkedOff or Usable Clauses. +***********************************************************/ +{ + CLAUSE Copy; + BOOL Redundant; + SHARED_INDEX Index; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + +#ifdef CHECK + if (!clause_IsClause(*Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_StaticReductions:"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(*Clause, Flags, Precedence); +#endif + + Index = (red_OnlyWorkedOffMode(Mode) ? + prfs_WorkedOffSharingIndex(Search) : prfs_UsableSharingIndex(Search)); + Copy = (CLAUSE)NULL; + Redundant = red_SimpleStaticReductions(Clause, Flags, Precedence, Result); + + if (Redundant) + return Redundant; + + /* Assignment Equation Deletion */ + if (flag_GetFlagValue(Flags, flag_RAED) != flag_RAEDOFF && + red_AssignmentEquationDeletion(*Clause, Flags, Precedence, &Copy, + prfs_NonTrivClauseNumber(Search), + (flag_GetFlagValue(Flags, flag_RAED) == flag_RAEDPOTUNSOUND))) { + red_ExchangeClauses(Clause, &Copy, Result); + if (clause_IsEmptyClause(*Clause)) + return FALSE; + } + + /* Subsumption */ + if (flag_GetFlagValue(Flags, flag_RFSUB)) { + *Subsumer = red_ForwardSubsumption(*Clause, Index, Flags, Precedence); + if ((Redundant = (*Subsumer != (CLAUSE)NULL))) + return Redundant; + } + + /* Forward Rewriting and Forward Contextual Rewriting */ + if ((flag_GetFlagValue(Flags, flag_RFREW) && + red_RewriteRedClause(*Clause, Index, Flags, Precedence, + &Copy, prfs_LastBacktrackLevel(Search))) || + (flag_GetFlagValue(Flags, flag_RFCRW) && + red_ContextualRewriting(Search, *Clause, Mode, + prfs_LastBacktrackLevel(Search), &Copy))) { + red_ExchangeClauses(Clause, &Copy, Result); + Redundant = red_SimpleStaticReductions(Clause, Flags, Precedence, Result); + if (Redundant) + return Redundant; + if (clause_IsEmptyClause(*Clause)) + return FALSE; + if (flag_GetFlagValue(Flags, flag_RFSUB)) { + *Subsumer = red_ForwardSubsumption(*Clause, Index, Flags, Precedence); + if ((Redundant = (*Subsumer != (CLAUSE)NULL))) + return Redundant; + } + } + + /* Sort Simplification */ + if (red_OnlyWorkedOffMode(Mode) && flag_GetFlagValue(Flags, flag_RSSI)) { + red_SortSimplification(prfs_DynamicSortTheory(Search), *Clause, + prfs_LastBacktrackLevel(Search), + flag_GetFlagValue(Flags, flag_DOCPROOF), + Flags, Precedence, &Copy); + red_ExchangeClauses(Clause, &Copy, Result); + if (clause_IsEmptyClause(*Clause)) + return FALSE; + } + + /* Matching Replacement Resolution */ + if (flag_GetFlagValue(Flags, flag_RFMRR)) { + red_MatchingReplacementResolution(*Clause, Index, Flags, Precedence, + &Copy, prfs_LastBacktrackLevel(Search)); + red_ExchangeClauses(Clause, &Copy, Result); + if (clause_IsEmptyClause(*Clause)) + return FALSE; + } + + /* Unit Conflict */ + if (flag_GetFlagValue(Flags, flag_RUNC)) { + red_UnitConflict(*Clause, Index, Flags, Precedence, + &Copy, prfs_LastBacktrackLevel(Search)); + red_ExchangeClauses(Clause, &Copy, Result); + if (clause_IsEmptyClause(*Clause)) + return FALSE; + } + + /* Static Soft Typing */ + if (red_OnlyWorkedOffMode(Mode) && flag_GetFlagValue(Flags, flag_RSST)) + Redundant = red_ClauseDeletion(prfs_StaticSortTheory(Search),*Clause, + Flags, Precedence); + +#ifdef CHECK + clause_Check(*Clause, Flags, Precedence); +#endif + + return Redundant; +} + +static BOOL red_SelectedStaticReductions(PROOFSEARCH Search, CLAUSE *Clause, + CLAUSE *Subsumer, LIST* Result, + NAT Mode) +/********************************************************** + INPUT: A proof search object, a clause (by reference) to be reduced, + and the mode of the reductions, determining which sets + (Usable, WorkedOff) in <Search> are considered for reductions. + EFFECT: Used reductions are tautology deletion, obvious reductions, + forward subsumption, forward rewriting, forward matching + replacement resolution, sort simplification, unit conflict + and static soft typing. + Depending on <Mode>, the clauses are reduced with respect + to WorkedOff and/or Usable Clauses. + RETURNS: TRUE iff the clause is redundant. + If the <DocProof> flag is false and no copying is necessary + with respect to splitting, the clause is destructively changed, + otherwise (intermediate) copies are made and returned in <*Result>. + If <Clause> gets redundant with respect to forward subsumption, + the subsuming clause is returned in <*Subsumer>. +***********************************************************/ +{ + CLAUSE Copy; + BOOL Redundant ,Rewritten, Tried, ContextualRew, StandardRew; + SHARED_INDEX WoIndex,UsIndex; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + +#ifdef CHECK + if (!clause_IsClause(*Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_SelectedStaticReductions:"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(*Clause, Flags, Precedence); +#endif + + WoIndex = (SHARED_INDEX)NULL; + UsIndex = (SHARED_INDEX)NULL; + if (red_WorkedOffMode(Mode)) + WoIndex = prfs_WorkedOffSharingIndex(Search); + if (red_UsableMode(Mode)) + UsIndex = prfs_UsableSharingIndex(Search); + Copy = (CLAUSE)NULL; + Redundant = red_SimpleStaticReductions(Clause, Flags, Precedence, Result); + + if (Redundant) + return Redundant; + + if (flag_GetFlagValue(Flags, flag_RAED) != flag_RAEDOFF && + red_AssignmentEquationDeletion(*Clause, Flags, Precedence, &Copy, + prfs_NonTrivClauseNumber(Search), + (flag_GetFlagValue(Flags, flag_RAED)==flag_RAEDPOTUNSOUND))) { + red_ExchangeClauses(Clause, &Copy, Result); + if (clause_IsEmptyClause(*Clause)) + return FALSE; + } + + if (flag_GetFlagValue(Flags, flag_RFSUB)) { + *Subsumer = (CLAUSE)NULL; + if (WoIndex != NULL) { + *Subsumer = red_ForwardSubsumption(*Clause, WoIndex, Flags, Precedence); + if (*Subsumer != (CLAUSE)NULL) + return TRUE; + } + if (UsIndex != NULL) { + *Subsumer = red_ForwardSubsumption(*Clause, UsIndex, Flags, Precedence); + if (*Subsumer != (CLAUSE)NULL) + return TRUE; + } + } + + StandardRew = flag_GetFlagValue(Flags, flag_RFREW); + ContextualRew = flag_GetFlagValue(Flags, flag_RFCRW); + + Rewritten = (StandardRew || ContextualRew); + Tried = FALSE; + while (Rewritten) { + Rewritten = FALSE; + + if (WoIndex != NULL && + ((StandardRew && + red_RewriteRedClause(*Clause, WoIndex, Flags, Precedence, &Copy, + prfs_LastBacktrackLevel(Search))) || + (ContextualRew && + red_ContextualRewriting(Search, *Clause, red_WORKEDOFF, + prfs_LastBacktrackLevel(Search), &Copy)))) { + Rewritten = TRUE; + red_ExchangeClauses(Clause, &Copy, Result); + Redundant = red_SimpleStaticReductions(Clause, Flags, + Precedence, Result); + if (Redundant) + return Redundant; + if (clause_IsEmptyClause(*Clause)) + return FALSE; + if (flag_GetFlagValue(Flags, flag_RFSUB)) { + *Subsumer = (CLAUSE)NULL; + *Subsumer = red_ForwardSubsumption(*Clause, WoIndex, + Flags, Precedence); + if (*Subsumer != (CLAUSE)NULL) + return TRUE; /* Clause is redundant */ + if (UsIndex != NULL) { + *Subsumer = red_ForwardSubsumption(*Clause, UsIndex, + Flags, Precedence); + if (*Subsumer != (CLAUSE)NULL) + return TRUE; + } + } + } + + if (UsIndex != NULL && + (!Tried || Rewritten) && + ((StandardRew && + red_RewriteRedClause(*Clause, UsIndex, Flags, Precedence, + &Copy, prfs_LastBacktrackLevel(Search))) || + (ContextualRew && + red_ContextualRewriting(Search, *Clause, red_USABLE, + prfs_LastBacktrackLevel(Search), &Copy)))) { + Rewritten = TRUE; + red_ExchangeClauses(Clause, &Copy, Result); + Redundant = red_SimpleStaticReductions(Clause, Flags, + Precedence, Result); + if (Redundant) + return Redundant; + if (clause_IsEmptyClause(*Clause)) + return FALSE; + if (flag_GetFlagValue(Flags, flag_RFSUB)) { + *Subsumer = (CLAUSE)NULL; + if (WoIndex != NULL) + *Subsumer = red_ForwardSubsumption(*Clause, WoIndex, + Flags, Precedence); + if (*Subsumer != (CLAUSE)NULL) + return TRUE; + *Subsumer = red_ForwardSubsumption(*Clause, UsIndex, + Flags, Precedence); + if (*Subsumer != (CLAUSE)NULL) + return TRUE; + } + } + + Tried = TRUE; + } /* end of while(Rewritten) */ + + + if (flag_GetFlagValue(Flags, flag_RSSI)) { + red_SortSimplification(prfs_DynamicSortTheory(Search), *Clause, + prfs_LastBacktrackLevel(Search), + flag_GetFlagValue(Flags, flag_DOCPROOF), + Flags, Precedence, &Copy); + red_ExchangeClauses(Clause, &Copy, Result); + if (clause_IsEmptyClause(*Clause)) + return FALSE; + } + + if (flag_GetFlagValue(Flags, flag_RFMRR)) { + if (WoIndex) + red_MatchingReplacementResolution(*Clause, WoIndex, Flags, Precedence, + &Copy, prfs_LastBacktrackLevel(Search)); + red_ExchangeClauses(Clause, &Copy, Result); + if (clause_IsEmptyClause(*Clause)) + return FALSE; + if (UsIndex) + red_MatchingReplacementResolution(*Clause, UsIndex, Flags, Precedence, + &Copy, prfs_LastBacktrackLevel(Search)); + red_ExchangeClauses(Clause, &Copy, Result); + if (clause_IsEmptyClause(*Clause)) + return FALSE; + } + + if (flag_GetFlagValue(Flags, flag_RUNC)) { + if (WoIndex) + red_UnitConflict(*Clause, WoIndex, Flags, Precedence, + &Copy, prfs_LastBacktrackLevel(Search)); + red_ExchangeClauses(Clause, &Copy, Result); + if (clause_IsEmptyClause(*Clause)) + return FALSE; + if (UsIndex) + red_UnitConflict(*Clause, UsIndex, Flags, Precedence, + &Copy, prfs_LastBacktrackLevel(Search)); + red_ExchangeClauses(Clause, &Copy, Result); + if (clause_IsEmptyClause(*Clause)) + return FALSE; + } + + if (flag_GetFlagValue(Flags, flag_RSST)) + Redundant = red_ClauseDeletion(prfs_StaticSortTheory(Search),*Clause, + Flags, Precedence); + +#ifdef CHECK + clause_Check(*Clause, Flags, Precedence); +#endif + + return Redundant; +} + + +CLAUSE red_ReductionOnDerivedClause(PROOFSEARCH Search, CLAUSE Clause, + NAT Mode) +/************************************************************** + INPUT: A proof search object, a derived clause and a mode + indicating which indexes should be used for reductions. + RETURNS: The non-redundant clause after reducing <Clause>, + NULL if <Clause> is redundant. + EFFECT: Clauses probably generated, but redundant are kept according + to the <DocProof> flag and the split level of involved clauses. + depending on <Mode>, then clauses are reduced + with respect to WorkedOff and/or Usable Clauses. +***************************************************************/ +{ + CLAUSE RedClause; + LIST Redundant; + +#ifdef CHECK + cont_SaveState(); +#endif + + Redundant = list_Nil(); + RedClause = (CLAUSE)NULL; + + if (red_StaticReductions(Search,&Clause,&RedClause,&Redundant,Mode)) { + /* Clause is redundant */ + red_HandleRedundantDerivedClauses(Search, Redundant, Clause); + list_Delete(Redundant); + if (RedClause && + prfs_SplitLevelCondition(clause_SplitLevel(RedClause),clause_SplitLevel(Clause), + prfs_LastBacktrackLevel(Search))) { + split_KeepClauseAtLevel(Search,Clause,clause_SplitLevel(RedClause)); + } + else + if (flag_GetFlagValue(prfs_Store(Search), flag_DOCPROOF)) + prfs_InsertDocProofClause(Search,Clause); + else + clause_Delete(Clause); + Clause = (CLAUSE)NULL; + } + else { + red_HandleRedundantDerivedClauses(Search, Redundant, Clause); + list_Delete(Redundant); + } + +#ifdef CHECK + cont_CheckState(); +#endif + + return Clause; +} + +CLAUSE red_CompleteReductionOnDerivedClause(PROOFSEARCH Search, CLAUSE Clause, + NAT Mode) +/************************************************************** + INPUT: A proof search object, a derived clause and a mode determining + which clauses to consider for reduction. + RETURNS: The non-redundant clause after reducing <Clause>, + NULL if <Clause> is redundant. + EFFECT: Clauses probably generated, but redundant are kept according + to the <DocProof> flag and the split level of involved clauses. + The clause is reduced with respect to all indexes determined + by <Mode> +***************************************************************/ +{ + CLAUSE RedClause; + LIST Redundant; + +#ifdef CHECK + cont_SaveState(); +#endif + + Redundant = list_Nil(); + RedClause = (CLAUSE)NULL; + + if (red_SelectedStaticReductions(Search,&Clause,&RedClause,&Redundant,Mode)) { + /* <Clause> is redundant */ + red_HandleRedundantDerivedClauses(Search, Redundant, Clause); + list_Delete(Redundant); + if (RedClause && + prfs_SplitLevelCondition(clause_SplitLevel(RedClause),clause_SplitLevel(Clause), + prfs_LastBacktrackLevel(Search))) { + split_KeepClauseAtLevel(Search, Clause, clause_SplitLevel(RedClause)); + } + else + if (flag_GetFlagValue(prfs_Store(Search), flag_DOCPROOF)) + prfs_InsertDocProofClause(Search, Clause); + else + clause_Delete(Clause); + Clause = (CLAUSE)NULL; + } + else { + red_HandleRedundantDerivedClauses(Search, Redundant, Clause); + list_Delete(Redundant); + } + +#ifdef CHECK + cont_CheckState(); +#endif + + return Clause; +} + + +LIST red_BackReduction(PROOFSEARCH Search, CLAUSE Clause, NAT Mode) +/************************************************************** + INPUT: A proof search object, a clause and a mode flag. + RETURNS: A list of reduced clauses in usable and worked-off + (depending on <Mode>) in <Search> with respect to <Clause>. + The original clauses that become redundant are either deleted + or kept for proof documentation or splitting. + EFFECT: The original clauses that become redundant are either deleted + or kept for proof documentation or splitting. +***************************************************************/ +{ + LIST Result, Redundant; + FLAGSTORE Flags; + PRECEDENCE Precedence; + +#ifdef CHECK + cont_SaveState(); +#endif + + Result = list_Nil(); + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + /* Subsumption */ + if (flag_GetFlagValue(Flags, flag_RBSUB)) { + Redundant = list_Nil(); + if (red_WorkedOffMode(Mode)) + Redundant = red_BackSubsumption(Clause, + prfs_WorkedOffSharingIndex(Search), + Flags, Precedence); + if (red_UsableMode(Mode)) + Redundant = list_Nconc(Redundant, + red_BackSubsumption(Clause, + prfs_UsableSharingIndex(Search), + Flags, Precedence)); + red_HandleRedundantIndexedClauses(Search, Redundant, Clause); + list_Delete(Redundant); + } + + /* Matching Replacement Resolution */ + if (flag_GetFlagValue(Flags, flag_RBMRR)) { + Redundant = list_Nil(); + if (red_WorkedOffMode(Mode)) + Redundant = red_BackMatchingReplacementResolution(Clause, + prfs_WorkedOffSharingIndex(Search), + Flags, Precedence, &Result); + if (red_UsableMode(Mode)) + Redundant = list_Nconc(Redundant, + red_BackMatchingReplacementResolution(Clause, + prfs_UsableSharingIndex(Search), + Flags, Precedence, &Result)); + red_HandleRedundantIndexedClauses(Search, Redundant, Clause); + list_Delete(Redundant); + } + + /* Standard Rewriting */ + if (flag_GetFlagValue(Flags, flag_RBREW)) { + Redundant = list_Nil(); + if (red_WorkedOffMode(Mode)) + Redundant = red_BackRewriting(Clause,prfs_WorkedOffSharingIndex(Search), + Flags, Precedence, &Result); + if (red_UsableMode(Mode)) + Redundant = list_Nconc(Redundant, + red_BackRewriting(Clause, + prfs_UsableSharingIndex(Search), + Flags, Precedence, &Result)); + + red_HandleRedundantIndexedClauses(Search, Redundant, Clause); + list_Delete(Redundant); + } + + /* Contextual Rewriting */ + if (flag_GetFlagValue(Flags, flag_RBCRW)) { + Redundant = list_Nil(); + if (red_WorkedOffMode(Mode)) + Redundant = red_BackContextualRewriting(Search, Clause, red_WORKEDOFF, + &Result); + if (red_UsableMode(Mode)) + Redundant = list_Nconc(Redundant, + red_BackContextualRewriting(Search, Clause, + red_USABLE, &Result)); + + red_HandleRedundantIndexedClauses(Search, Redundant, Clause); + list_Delete(Redundant); + } + +#ifdef CHECK + cont_CheckState(); +#endif + + return Result; +} + + +static __inline__ LIST red_MergeClauseListsByWeight(LIST L1, LIST L2) +/************************************************************** + INPUT: Two lists of clauses, sorted by weight. + RETURNS: + EFFECT: +***************************************************************/ +{ + return list_NNumberMerge(L1, L2, (NAT (*)(POINTER))clause_Weight); +} + + +LIST red_CompleteReductionOnDerivedClauses(PROOFSEARCH Search, + LIST DerivedClauses, NAT Mode, + int Bound, NAT BoundMode, + int *BoundApplied) +/************************************************************** + INPUT: A proof search object, a list of newly derived (unshared) clauses, + a mode determining which clause lists to consider for reduction, + a bound and a bound mode to cut off generated clauses. + RETURNS: A list of empty clauses that may be derived during the + reduction process. + <*BoundApplied> is set to the mode dependent value of the + smallest clause if a clause is deleted because of a bound. + EFFECT: The <DerivedClauses> are destructively reduced and reduced clauses + from the indexes are checked out and all finally reduced clauses + are checked into the indexes. Depending on <Mode> either the + WorkedOff, Usable or both indexes are considered. + The <DocProof> Flag is considered. +***************************************************************/ +{ + LIST EmptyClauses,NewClauses,Scan; + NAT ClauseBound; + CLAUSE Clause; + FLAGSTORE Flags; + +#ifdef CHECK + cont_SaveState(); +#endif + + EmptyClauses = list_Nil(); + DerivedClauses = clause_ListSortWeighed(DerivedClauses); + ClauseBound = 0; + Flags = prfs_Store(Search); + + while (!list_Empty(DerivedClauses)) { +#ifdef WIN + clock_PingOneSecond(); +#endif + Clause = list_NCar(&DerivedClauses); + if (prfs_SplitStackEmpty(Search)) /* Otherwise splitting not compatible with bound deletion */ + Clause = red_CompleteReductionOnDerivedClause(Search, Clause, Mode); + + if (Clause != NULL && BoundMode != flag_BOUNDMODEUNLIMITED && + Bound != flag_BOUNDSTARTUNLIMITED && !clause_IsFromInput(Clause) && + !clause_IsFromSplitting(Clause)) { + switch (BoundMode) { + case flag_BOUNDMODERESTRICTEDBYWEIGHT: + ClauseBound = clause_Weight(Clause); + break; + case flag_BOUNDMODERESTRICTEDBYDEPTH: + ClauseBound = clause_ComputeTermDepth(Clause); + break; + default: + misc_StartUserErrorReport(); + misc_UserErrorReport("\n Error while applying bound restrictions:"); + misc_UserErrorReport("\n You selected an unknown bound mode.\n"); + misc_FinishUserErrorReport(); + } + if (ClauseBound > Bound) { + if (flag_GetFlagValue(Flags, flag_PBDC)) { + fputs("\nDeleted by bound: ", stdout); + clause_Print(Clause); + } + clause_Delete(Clause); + if (*BoundApplied == -1 || ClauseBound < *BoundApplied) + *BoundApplied = ClauseBound; + Clause = (CLAUSE)NULL; + } + } + + if (Clause != (CLAUSE)NULL && /* For clauses below bound, splitting is */ + !prfs_SplitStackEmpty(Search)) /* compatible with bound deletion */ + Clause = red_CompleteReductionOnDerivedClause(Search, Clause, Mode); + + if (Clause) { + prfs_IncKeptClauses(Search); + if (flag_GetFlagValue(Flags, flag_PKEPT)) { + fputs("\nKept: ", stdout); + clause_Print(Clause); + } + if (clause_IsEmptyClause(Clause)) + EmptyClauses = list_Cons(Clause,EmptyClauses); + else { + NewClauses = red_BackReduction(Search, Clause, Mode); + prfs_IncDerivedClauses(Search, list_Length(NewClauses)); + if (flag_GetFlagValue(Flags, flag_PDER)) + for (Scan=NewClauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) { + fputs("\nDerived: ", stdout); + clause_Print(list_Car(Scan)); + } + NewClauses = split_ExtractEmptyClauses(NewClauses,&EmptyClauses); + + prfs_InsertUsableClause(Search,Clause); + NewClauses = list_NumberSort(NewClauses, (NAT (*) (POINTER)) clause_Weight); + DerivedClauses = red_MergeClauseListsByWeight(DerivedClauses,NewClauses); + } + } + } + +#ifdef CHECK + cont_CheckState(); +#endif + + return EmptyClauses; +} + + + +static CLAUSE red_CDForwardSubsumer(CLAUSE RedCl, st_INDEX Index, + FLAGSTORE Flags, PRECEDENCE Precedence) +/********************************************************** + INPUT: A pointer to a non-empty clause, an index of + clauses, a flag store and a precedence. + RETURNS: The first clause from the Approx Set which + subsumes 'RedCl'. +***********************************************************/ +{ + TERM Atom,AtomGen; + LIST LitScan; + int i,length; + CLAUSE CandCl; + +#ifdef CHECK + if (!clause_IsClause(RedCl, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_CDForwardSubsumer :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedCl, Flags, Precedence); +#endif + + length = clause_Length(RedCl); + + for (i = 0; i < length; i++) { + Atom = clause_GetLiteralAtom(RedCl, i); + AtomGen = st_ExistGen(cont_LeftContext(), Index, Atom); + + while (AtomGen) { + for (LitScan = term_SupertermList(AtomGen); + !list_Empty(LitScan); LitScan = list_Cdr(LitScan)) { + CandCl = clause_LiteralOwningClause(list_Car(LitScan)); + + if (clause_GetLiteral(CandCl,clause_FirstLitIndex()) == (LITERAL)list_Car(LitScan) && + subs_Subsumes(CandCl, RedCl, clause_FirstLitIndex(), i)) { + st_CancelExistRetrieval(); + return CandCl; + } + } + AtomGen = st_NextCandidate(); + } + } + return (CLAUSE)NULL; +} + + +static BOOL red_CDForwardSubsumption(CLAUSE RedClause, st_INDEX Index, + FLAGSTORE Flags, PRECEDENCE Precedence) +/********************************************************** + INPUT: A clause, an index of clauses, a flag store and + a precedence. + RETURNS: The boolean value TRUE if the clause is subsumed + by an indexed clause, if so, the clause is deleted, + either really or locally. +***********************************************************/ +{ + BOOL IsSubsumed; + CLAUSE Subsumer; + +#ifdef CHECK + if (!clause_IsClause(RedClause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_CDForwardSubSumption :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedClause, Flags, Precedence); +#endif + IsSubsumed = FALSE; + Subsumer = red_CDForwardSubsumer(RedClause, Index, Flags, Precedence); + + if (clause_Exists(Subsumer)) { + IsSubsumed = TRUE; + + if (flag_GetFlagValue(Flags, flag_DOCSST) && + flag_GetFlagValue(Flags, flag_PSUB)) { + fputs("\nFSubsumption:", stdout); + clause_Print(RedClause); + printf(" by %d ",clause_Number(Subsumer)); + } + } + return IsSubsumed; +} + + +static void red_CDBackSubsumption(CLAUSE RedCl, FLAGSTORE Flags, + PRECEDENCE Precedence, + LIST* UsListPt, LIST* WOListPt, + st_INDEX Index) +/********************************************************** + INPUT: A pointer to a non-empty clause, a flag store, + a precedence, and an index of clauses. + RETURNS: Nothing. +***********************************************************/ +{ + TERM Atom,AtomInst; + CLAUSE SubsumedCl; + LIST Scan, SubsumedList; + +#ifdef CHECK + if (!clause_IsClause(RedCl, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_CDBackupSubSumption :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedCl, Flags, Precedence); +#endif + + SubsumedList = list_Nil(); + + if (!clause_IsEmptyClause(RedCl)) { + Atom = clause_GetLiteralAtom(RedCl, clause_FirstLitIndex()); + AtomInst = st_ExistInstance(cont_LeftContext(), Index, Atom); + + while(AtomInst) { + for (Scan = term_SupertermList(AtomInst); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + SubsumedCl = clause_LiteralOwningClause(list_Car(Scan)); + if ((RedCl != SubsumedCl) && + subs_Subsumes(RedCl, SubsumedCl, clause_FirstLitIndex(), + clause_LiteralGetIndex(list_Car(Scan))) && + !list_PointerMember(SubsumedList, SubsumedCl)) + SubsumedList = list_Cons(SubsumedCl, SubsumedList); + } + AtomInst = st_NextCandidate(); + } + + for (Scan = SubsumedList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + SubsumedCl = list_Car(Scan); + + if (flag_GetFlagValue(Flags, flag_DOCSST) && flag_GetFlagValue(Flags, flag_PSUB)) { + fputs("\nBSubsumption: ", stdout); + clause_Print(SubsumedCl); + printf(" by %d ",clause_Number(RedCl)); + } + + + if (clause_GetFlag(SubsumedCl,WORKEDOFF)) { + *WOListPt = list_PointerDeleteOneElement(*WOListPt, SubsumedCl); + }else { + *UsListPt = list_PointerDeleteOneElement(*UsListPt, SubsumedCl); + } + clause_DeleteFlatFromIndex(SubsumedCl, Index); + } + list_Delete(SubsumedList); + } +} + + +static LIST red_CDDerivables(SORTTHEORY Theory, CLAUSE GivenClause, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A sort theory, a clause, a flag store and a + precedence. + RETURNS: A list of clauses derivable from <GivenClause> and + the declaration clauses in <Theory>. +***************************************************************/ +{ + LIST ListOfDerivedClauses; + +#ifdef CHECK + if (!(clause_IsClause(GivenClause, Flags, Precedence))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_CDDeriveables :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(GivenClause, Flags, Precedence); +#endif + + if (clause_HasTermSortConstraintLits(GivenClause)) + ListOfDerivedClauses = inf_ForwardSortResolution(GivenClause, + sort_TheoryIndex(Theory), + Theory, TRUE, + Flags, Precedence); + else + ListOfDerivedClauses = inf_ForwardEmptySort(GivenClause, + sort_TheoryIndex(Theory), + Theory, TRUE, + Flags, Precedence); + + return ListOfDerivedClauses; +} + + +static BOOL red_CDReduce(SORTTHEORY Theory, CLAUSE RedClause, + FLAGSTORE Flags, PRECEDENCE Precedence, + LIST *ApproxUsListPt, LIST *ApproxWOListPt, + st_INDEX Index) +/************************************************************** + INPUT: A sort theory, an unshared clause, a flag store, + a precedence, their index and two pointers to the + sort reduction subproof usable and worked off list. + RETURNS: TRUE iff <RedClause> is redundant with respect to + clauses in the index or theory. + EFFECT: <RedClause> is destructively changed. + The <DocProof> flag is changed temporarily. +***************************************************************/ +{ + CLAUSE Copy; + +#ifdef CHECK + clause_Check(RedClause, Flags, Precedence); +#endif + + Copy = (CLAUSE)NULL; /* Only needed for interface */ + + red_ObviousReductions(RedClause, FALSE, Flags, Precedence, &Copy); + red_SortSimplification(Theory, RedClause, NAT_MAX, FALSE, + Flags, Precedence, &Copy); + + if (clause_IsEmptyClause(RedClause)) + return FALSE; + + red_Condensing(RedClause, FALSE, Flags, Precedence, &Copy); + + if (red_CDForwardSubsumption(RedClause, Index, Flags, Precedence)) + return TRUE; + else { /* RedClause isn't subsumed! */ + red_CDBackSubsumption(RedClause, Flags, Precedence, + ApproxUsListPt, ApproxWOListPt, Index); + clause_InsertFlatIntoIndex(RedClause, Index); + *ApproxUsListPt = list_Cons(RedClause, *ApproxUsListPt); + } + +#ifdef CHECK + clause_Check(RedClause, Flags, Precedence); + if (Copy != (CLAUSE)NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_CDReduce :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + +#endif + + return FALSE; +} + + +BOOL red_ClauseDeletion(SORTTHEORY Theory, CLAUSE RedClause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A sort theory, a clause (unshared), a flag store + and a precedence. + RETURNS: TRUE iff the sort constraint of the clause is + unsolvable with respect to the sort theory. +***************************************************************/ +{ + if (Theory != (SORTTHEORY)NULL) { + CLAUSE ConstraintClause, GivenClause; + LIST ApproxUsableList, ApproxWOList, EmptyClauses, ApproxDerivables, Scan; + int i,nc, Count, OldClauseCounter; + st_INDEX Index; + +#ifdef CHECK + if (!(clause_IsClause(RedClause, Flags, Precedence))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_ClauseDeletion :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } + clause_Check(RedClause, Flags, Precedence); +#endif + + if (clause_HasEmptyConstraint(RedClause) || !flag_GetFlagValue(Flags, flag_RSST)) + return FALSE; + + if (flag_GetFlagValue(Flags, flag_DOCSST)) { + fputs("\n\nStatic Soft Typing tried on: ", stdout); + clause_Print(RedClause); + } + + Index = st_IndexCreate(); + Scan = list_Nil(); + nc = clause_NumOfConsLits(RedClause); + OldClauseCounter = clause_Counter(); + + /* Make constraint clause, insert it into the Approx-usable-list: */ + + for (i = clause_FirstLitIndex(); i < nc; i++) + Scan = list_Cons(term_Copy(clause_LiteralAtom( + clause_GetLiteral(RedClause, i))), Scan); + + Scan = list_NReverse(Scan); + ConstraintClause = clause_Create(Scan, list_Nil(), list_Nil(), + Flags, Precedence); + list_Delete(Scan); + clause_InitSplitData(ConstraintClause); + clause_AddParentClause(ConstraintClause, clause_Number(RedClause)); + clause_AddParentLiteral(ConstraintClause, clause_FirstLitIndex()); + clause_SetFromClauseDeletion(ConstraintClause); + clause_InsertFlatIntoIndex(ConstraintClause, Index); + ApproxUsableList = list_List(ConstraintClause); + ApproxWOList = list_Nil(); + + /* fputs("\nConstraint clause: ",stdout); clause_Print(ConstraintClause); */ + + /* Now the lists are initialized, the subproof is started: */ + + EmptyClauses = list_Nil(); + Count = 0; + + if (flag_GetFlagValue(Flags, flag_DOCSST)) { + puts("\n*************** Static Soft Typing Subproof: ***************"); + puts("The usable list:"); + clause_ListPrint(ApproxUsableList); + puts("\nThe worked-off list:"); + clause_ListPrint(ApproxWOList); + /* fputs("\nAll indexed clauses: ", stdout); + clause_PrintAllIndexedClauses(ShIndex); */ + } + while (!list_Empty(ApproxUsableList) && list_Empty(EmptyClauses)) { + GivenClause = list_Car(ApproxUsableList); + clause_SetFlag(GivenClause,WORKEDOFF); + + if (flag_GetFlagValue(Flags, flag_DOCSST)) { + fputs("\n\tSubproof Given clause: ", stdout); + clause_Print(GivenClause); fflush(stdout); + } + ApproxWOList = list_Cons(GivenClause, ApproxWOList); + ApproxUsableList = list_PointerDeleteOneElement(ApproxUsableList,GivenClause); + ApproxDerivables = red_CDDerivables(Theory,GivenClause, Flags, Precedence); + ApproxDerivables = split_ExtractEmptyClauses(ApproxDerivables, &EmptyClauses); + + if (!list_Empty(EmptyClauses)) { /* Exit while loop! */ + if (flag_GetFlagValue(Flags, flag_DOCSST)) { + fputs("\nStatic Soft Typing not successful: ", stdout); + clause_Print(list_Car(EmptyClauses)); + } + clause_DeleteClauseList(ApproxDerivables); + ApproxDerivables = list_Nil(); + } + else { + CLAUSE DerClause; + for (Scan = ApproxDerivables; !list_Empty(Scan) && list_Empty(EmptyClauses); + Scan = list_Cdr(Scan)) { + DerClause = (CLAUSE)list_Car(Scan); + if (red_CDReduce(Theory, DerClause, Flags, Precedence, + &ApproxUsableList, &ApproxWOList, Index)) + clause_Delete(DerClause); + else{ + Count++; + if (flag_GetFlagValue(Flags, flag_DOCSST)) { + putchar('\n'); + clause_Print(DerClause); + } + if (clause_IsEmptyClause(DerClause)) + EmptyClauses = list_Cons(DerClause,EmptyClauses); + } + list_Rplaca(Scan,(CLAUSE)NULL); + } + + if (!list_Empty(EmptyClauses)) { + if (flag_GetFlagValue(Flags, flag_DOCSST)) { + fputs(" Static Soft Typing not successful!", stdout); + clause_Print(list_Car(EmptyClauses)); + } + clause_DeleteClauseList(ApproxDerivables); /* There still may be clauses in the list */ + ApproxDerivables = list_Nil(); + } + else { + list_Delete(ApproxDerivables); + ApproxDerivables = list_Nil(); + } + } + } + + if (!list_Empty(EmptyClauses)) { + if (flag_GetFlagValue(Flags, flag_DOCSST)) { + puts("\nStatic Soft Typing failed, constraint solvable."); + puts("************ Static Soft Typing Subproof finished. ************"); + } + } + else + if (flag_GetFlagValue(Flags, flag_PSST)) { + fputs("\nStatic Soft Typing deleted: ", stdout); + clause_Print(RedClause); + } + + /* Cleanup */ + clause_DeleteClauseListFlatFromIndex(ApproxUsableList, Index); + clause_DeleteClauseListFlatFromIndex(ApproxWOList, Index); + st_IndexDelete(Index); + clause_SetCounter(OldClauseCounter); + + if (!list_Empty(EmptyClauses)) { + clause_DeleteClauseList(EmptyClauses); + return FALSE; + } + + return TRUE; + +#ifdef CHECK + clause_Check(RedClause, Flags, Precedence); +#endif + } + return FALSE; +} + +LIST red_SatUnit(PROOFSEARCH Search, LIST ClauseList) +/********************************************************* + INPUT: A proof search object and a list of unshared clauses. + RETURNS: A possibly empty list of empty clauses. + EFFECT: Does a shallow saturation of the conclauses depending on the + flag_SATUNIT flag. + The <DocProof> flag is considered. +**********************************************************/ +{ + CLAUSE Given,Clause; + LIST Scan, Derivables, EmptyClauses, BackReduced; + NAT n, Derived; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + Derived = flag_GetFlagValue(Flags, flag_CNFPROOFSTEPS); + EmptyClauses = list_Nil(); + + ClauseList = clause_ListSortWeighed(ClauseList); + + while (!list_Empty(ClauseList) && list_Empty(EmptyClauses)) { + Given = (CLAUSE)list_NCar(&ClauseList); + Given = red_ReductionOnDerivedClause(Search, Given, red_USABLE); + if (Given) { + if (clause_IsEmptyClause(Given)) + EmptyClauses = list_List(Given); + else { + BackReduced = red_BackReduction(Search, Given, red_USABLE); + + if (Derived != 0) { + Derivables = inf_BoundedDepthUnitResolution(Given, + prfs_UsableSharingIndex(Search), + FALSE, Flags, Precedence); + n = list_Length(Derivables); + if (n > Derived) + Derived = 0; + else + Derived = Derived - n; + } + else + Derivables = list_Nil(); + + Derivables = list_Nconc(BackReduced,Derivables); + Derivables = split_ExtractEmptyClauses(Derivables, &EmptyClauses); + + prfs_InsertUsableClause(Search, Given); + + for(Scan = Derivables; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Clause = (CLAUSE)list_Car(Scan); + clause_SetDepth(Clause,0); + } + ClauseList = list_Nconc(ClauseList,Derivables); + Derivables = list_Nil(); + } + } + } + for(Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) + prfs_InsertUsableClause(Search, list_Car(Scan)); + list_Delete(ClauseList); + return EmptyClauses; +} + +static CLAUSE red_SpecialInputReductions(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/********************************************************* + INPUT: A clause and a flag store. + RETURNS: The clause where the logical constants TRUE, FALSE + are removed. + EFFECT: The clause is destructively changed. +**********************************************************/ +{ + int i,end; + LIST Indexes; + TERM Atom; + +#ifdef CHECK + clause_Check(Clause, Flags, Precedence); +#endif + + Indexes = list_Nil(); + end = clause_LastAntecedentLitIndex(Clause); + + for (i = clause_FirstConstraintLitIndex(Clause); i <= end; i++) { + Atom = clause_LiteralAtom(clause_GetLiteral(Clause,i)); + if (fol_IsTrue(Atom)) + Indexes = list_Cons((POINTER)i,Indexes); + } + + end = clause_LastSuccedentLitIndex(Clause); + + for (i = clause_FirstSuccedentLitIndex(Clause); i <= end; i++) { + Atom = clause_LiteralAtom(clause_GetLiteral(Clause,i)); + if (fol_IsFalse(Atom)) + Indexes = list_Cons((POINTER)i,Indexes); + } + + clause_DeleteLiterals(Clause,Indexes, Flags, Precedence); + list_Delete(Indexes); + + return Clause; +} + + +LIST red_ReduceInput(PROOFSEARCH Search, LIST ClauseList) +/********************************************************* + INPUT: A proof search object and a list of unshared clauses. + RETURNS: A list of empty clauses. + EFFECT: Interreduces the clause list and inserts the clauses into <Search>. + Keeps track of derived and kept clauses. + Time limits and the DocProof flag are considered. +**********************************************************/ +{ + CLAUSE Given; + LIST Scan, EmptyClauses, BackReduced; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + EmptyClauses = list_Nil(); + ClauseList = clause_ListSortWeighed(list_Copy(ClauseList)); + ClauseList = split_ExtractEmptyClauses(ClauseList, &EmptyClauses); + + while (!list_Empty(ClauseList) && list_Empty(EmptyClauses) && + (flag_GetFlagValue(Flags,flag_TIMELIMIT) == flag_TIMELIMITUNLIMITED || + flag_GetFlagValue(Flags, flag_TIMELIMIT) > clock_GetSeconds(clock_OVERALL))) { + Given = (CLAUSE)list_NCar(&ClauseList); +#ifdef CHECK + if (!clause_IsClause(Given, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_ReduceInput :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + Given = red_SpecialInputReductions(Given, Flags, Precedence); + Given = red_ReductionOnDerivedClause(Search, Given, red_USABLE); + if (Given) { + prfs_IncKeptClauses(Search); + if (clause_IsEmptyClause(Given)) + EmptyClauses = list_List(Given); + else { + BackReduced = red_BackReduction(Search, Given, red_USABLE); + prfs_IncDerivedClauses(Search, list_Length(BackReduced)); + BackReduced = split_ExtractEmptyClauses(BackReduced, &EmptyClauses); + prfs_InsertUsableClause(Search, Given); + BackReduced = clause_ListSortWeighed(BackReduced); + ClauseList = red_MergeClauseListsByWeight(ClauseList, BackReduced); + } + } + } + for(Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) + prfs_InsertUsableClause(Search, list_Car(Scan)); + list_Delete(ClauseList); + return EmptyClauses; +} + + +LIST red_SatInput(PROOFSEARCH Search) +/********************************************************* + INPUT: A proof search object. + RETURNS: A list of derived empty clauses. + EFFECT: Does a saturation from the conjectures into the axioms/conjectures + Keeps track of derived and kept clauses. Keeps track of a possible + time limit. + Considers the Usable clauses in <Search> and a possible time limit. +**********************************************************/ +{ + CLAUSE Given; + LIST Scan, ClauseList, Derivables, EmptyClauses; + int n; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + EmptyClauses = list_Nil(); + ClauseList = list_Nil(); + Scan = prfs_UsableClauses(Search); + n = list_Length(Scan); + + while(!list_Empty(Scan) && + n > 0 && + (flag_GetFlagValue(Flags,flag_TIMELIMIT) == flag_TIMELIMITUNLIMITED || + flag_GetFlagValue(Flags, flag_TIMELIMIT) > clock_GetSeconds(clock_OVERALL))) { + Given = (CLAUSE)list_Car(Scan); + if (clause_GetFlag(Given,CONCLAUSE)) { + Derivables = inf_BoundedDepthUnitResolution(Given, + prfs_UsableSharingIndex(Search), + FALSE, Flags, Precedence); + n -= list_Length(Derivables); + ClauseList = list_Nconc(Derivables,ClauseList); + } + Scan = list_Cdr(Scan); + } + + prfs_IncDerivedClauses(Search, list_Length(ClauseList)); + EmptyClauses = red_ReduceInput(Search, ClauseList); + list_Delete(ClauseList); + ClauseList = list_Nil(); + if (list_Empty(EmptyClauses)) { + Scan=prfs_UsableClauses(Search); + while (!list_Empty(Scan) && + n > 0 && + (flag_GetFlagValue(Flags,flag_TIMELIMIT)==flag_TIMELIMITUNLIMITED || + flag_GetFlagValue(Flags, flag_TIMELIMIT) > clock_GetSeconds(clock_OVERALL))) { + Given = (CLAUSE)list_Car(Scan); + if (clause_GetFlag(Given,CONCLAUSE) && clause_IsFromInput(Given)) { + Derivables = inf_BoundedDepthUnitResolution(Given, + prfs_UsableSharingIndex(Search), + TRUE, Flags, Precedence); + n -= list_Length(Derivables); + ClauseList = list_Nconc(Derivables,ClauseList); + } + Scan = list_Cdr(Scan); + } + prfs_IncDerivedClauses(Search, list_Length(ClauseList)); + EmptyClauses = red_ReduceInput(Search, ClauseList); + list_Delete(ClauseList); + } + return EmptyClauses; +} + +void red_CheckSplitSubsumptionCondition(PROOFSEARCH Search) +/********************************************************* + INPUT: A proof search object. + EFFECT: For all deleted clauses in the split stack, it + is checked whether they are subsumed by some + existing clause. If they are not, a core is dumped. + Used for debugging. +**********************************************************/ +{ + LIST Scan1,Scan2; + CLAUSE Clause; + FLAGSTORE Flags; + PRECEDENCE Precedence; + + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + for (Scan1=prfs_SplitStack(Search);!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) + for (Scan2=prfs_SplitDeletedClauses(list_Car(Scan1));!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) { + Clause = (CLAUSE)list_Car(Scan2); + if (!red_ForwardSubsumer(Clause, prfs_WorkedOffSharingIndex(Search), + Flags, Precedence) && + !red_ForwardSubsumer(Clause, prfs_UsableSharingIndex(Search), + Flags, Precedence) && + !red_ClauseDeletion(prfs_StaticSortTheory(Search),Clause, + Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_CheckSplitSubsumptionCondition: No clause found implying "); + clause_Print(Clause); + misc_ErrorReport("\n Current Split: "); + prfs_PrintSplit(list_Car(Scan1)); + misc_FinishErrorReport(); + } + } +} diff --git a/test/spass/rules-red.h b/test/spass/rules-red.h new file mode 100644 index 0000000000000000000000000000000000000000..2775ab27c902077c63362c2e3461998a3aa70851 --- /dev/null +++ b/test/spass/rules-red.h @@ -0,0 +1,111 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * REDUCTION RULES * */ +/* * * */ +/* * $Module: REDRULES * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _REDRULES_ +#define _REDRULES_ + +#include "sort.h" +#include "subsumption.h" +#include "condensing.h" +#include "search.h" +#include "rules-split.h" +#include "rules-inf.h" +#include "doc-proof.h" +#include "clock.h" +#include "closure.h" + +/**************************************************************/ +/* Constants */ +/**************************************************************/ + +extern const NAT red_USABLE; +extern const NAT red_WORKEDOFF; +extern const NAT red_ALL; + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +static __inline__ BOOL red_WorkedOffMode(NAT Mode) +{ + return (Mode == red_WORKEDOFF || Mode == red_ALL); +} + +static __inline__ BOOL red_OnlyWorkedOffMode(NAT Mode) +{ + return (Mode == red_WORKEDOFF); +} + +static __inline__ BOOL red_UsableMode(NAT Mode) +{ + return (Mode == red_USABLE || Mode == red_ALL); +} + +static __inline__ BOOL red_AllMode(NAT Mode) +{ + return (Mode == red_ALL); +} + + +void red_Init(void); + + +LIST red_CompleteReductionOnDerivedClauses(PROOFSEARCH, LIST, NAT, int, NAT, int*); +CLAUSE red_ReductionOnDerivedClause(PROOFSEARCH, CLAUSE, NAT); +CLAUSE red_CompleteReductionOnDerivedClause(PROOFSEARCH, CLAUSE, NAT); +LIST red_BackReduction(PROOFSEARCH, CLAUSE, NAT); +LIST red_SatUnit(PROOFSEARCH, LIST); +LIST red_SatInput(PROOFSEARCH); +LIST red_ReduceInput(PROOFSEARCH, LIST); +BOOL red_ClauseDeletion(SORTTHEORY, CLAUSE, FLAGSTORE, PRECEDENCE); + + +void red_CheckSplitSubsumptionCondition(PROOFSEARCH); + + +#endif diff --git a/test/spass/rules-sort.c b/test/spass/rules-sort.c new file mode 100644 index 0000000000000000000000000000000000000000..74f8c9f9a154aa3d63e2e25351cf3f8a5cbe4973 --- /dev/null +++ b/test/spass/rules-sort.c @@ -0,0 +1,1763 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INFERENCE RULES FOR SORTS * */ +/* * * */ +/* * $Module: SORTRULES * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "rules-sort.h" + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +static LIST inf_GetForwardPartnerLits(LITERAL, st_INDEX); +static SORT inf_GetSortFromLits(LIST, SORTTHEORY); + + +static BOOL inf_SubsortPrecheck(CLAUSE Clause, LIST TLits, LITERAL Special, + st_INDEX Index, SORTTHEORY SortTheory) +/************************************************************** + INPUT: A clause, a list of constraint literal indices in + that clause, a special literal, an index of clauses, + and the actual sort theory. + RETURNS: TRUE, if there exists any subsort of the <TLits> sort. +***************************************************************/ +{ + SORT tSort, unifierSort; + LIST unifiers; + BOOL result; + + unifiers = inf_GetForwardPartnerLits(clause_GetLiteral(Clause,(int)list_Car(TLits)), + Index); + unifierSort = inf_GetSortFromLits(unifiers, SortTheory); + list_Delete(unifiers); + + tSort = sort_TopSort(); + for (; !list_Empty(TLits); TLits = list_Cdr(TLits)) { + TERM actAtom = clause_GetLiteralAtom(Clause, (int)list_Car(TLits)); + tSort = sort_Intersect(sort_TheorySortOfSymbol(SortTheory, term_TopSymbol(actAtom)), + tSort); + } + tSort = list_PointerDeleteDuplicates(tSort); + + if (Special == NULL) + result = sort_TheoryIsSubsortOf(SortTheory, unifierSort, tSort); + else { + SORT extraSort; + extraSort = sort_TheorySortOfSymbol(SortTheory, clause_LiteralPredicate(Special)); + result = sort_TheoryIsSubsortOfExtra(SortTheory, extraSort, unifierSort, tSort); + sort_Delete(extraSort); + } + + sort_Delete(tSort); + sort_Delete(unifierSort); + + return result; +} + +static LIST inf_GetSortResolutionPartnerLits(TERM Atom, st_INDEX Index) +/************************************************************** + INPUT: A clause, and an Index of clauses. + RETURNS: A list of literals with which sortresolution is possible. + MEMORY: Allocates memory for the list. +***************************************************************/ +{ + LIST Result, TermList, LitScan; + LITERAL NextLit; + CLAUSE Clause; + +#ifdef CHECK + if (!term_IsAtom(Atom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GetSortResolutionPartnerLits: Variable as atom input.\n"); + misc_FinishErrorReport(); + } +#endif + + Result = list_Nil(); + TermList = st_GetUnifier(cont_LeftContext(), Index, cont_RightContext(), Atom); + + for ( ; !list_Empty(TermList); TermList = list_Pop(TermList)) { + + if (term_IsAtom(list_Car(TermList))) { + + for (LitScan = sharing_NAtomDataList(list_Car(TermList)); + !list_Empty(LitScan); + LitScan = list_Cdr(LitScan)){ + NextLit = list_Car(LitScan); + Clause = clause_LiteralOwningClause(NextLit); + + if (clause_LiteralIsPositive(NextLit) && + clause_LiteralGetFlag(NextLit,STRICTMAXIMAL) && + clause_GetFlag(Clause, WORKEDOFF) && + clause_HasSolvedConstraint(Clause) && + !list_PointerMember(Result, NextLit)) + Result = list_Cons(NextLit, Result); + } + } + } + + return Result; +} + + +static CLAUSE inf_BuildConstraintHyperResolvent(CLAUSE Clause, LIST Lits, + SUBST Subst, LIST Foundlits, + FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A <Clause> where the sort constraint is resolved, + a list <Lits> of constraint indices in <Clause> where + all corresponding constraints have the same term, + the overall substitution <Subst>, + a list <Foundlits> of literals of found partner clauses, + a flag store and a precedence. + RETURNS: A clause, the resolvent of a resolution step. +***************************************************************/ +{ + CLAUSE NewClause, ClauseCopy; + LIST Constraint, Antecedent, Succedent, ParentCls, ParentLits, Scan; + TERM Atom; + SYMBOL MaxVar,MaxCand; + int i,bound, depth; + BOOL IsFromEmptySort; + LIST Partners; + + ParentCls = list_Nil(); + ParentLits = list_Nil(); + Constraint = list_Nil(); + Antecedent = list_Nil(); + Succedent = list_Nil(); + Partners = list_Nil(); + depth = clause_Depth(Clause); + + for (Scan=Foundlits; !list_Empty(Scan); Scan=list_Cdr(Scan)) + depth = misc_Max(depth, + clause_Depth(clause_LiteralOwningClause(list_Car(Scan)))); + + ClauseCopy = clause_Copy(Clause); + Partners = list_Cons(ClauseCopy, Partners); + clause_SubstApply(Subst, ClauseCopy); + + IsFromEmptySort = term_IsVariable(term_FirstArgument( + clause_GetLiteralAtom(Clause, (int)list_Car(Lits)))); + + bound = clause_LastConstraintLitIndex(ClauseCopy); + + for (i = clause_FirstLitIndex(); i <= bound; i++) + if (!list_PointerMember(Lits, (POINTER)i)) { + Atom = term_Copy(clause_GetLiteralAtom(ClauseCopy, i)); + Constraint = list_Cons(Atom, Constraint); + } + else { + ParentCls = list_Cons((POINTER)clause_Number(ClauseCopy), ParentCls); + ParentLits = list_Cons((POINTER)i, ParentLits); + } + + bound = clause_LastAntecedentLitIndex(ClauseCopy); + for ( ; i <= bound; i++) { + Atom = term_Copy(clause_GetLiteralAtom(ClauseCopy, i)); + Antecedent = list_Cons(Atom, Antecedent); + } + bound = clause_LastSuccedentLitIndex(ClauseCopy); + for (; i <= bound; i++) { + Atom = term_Copy(clause_GetLiteralAtom(ClauseCopy, i)); + Succedent = list_Cons(Atom, Succedent); + } + bound = clause_LastConstraintLitIndex(Clause); + for (i = clause_FirstLitIndex(); i <= bound; i++) { + /* Hier sollen die gematchten Constraintliterale dazu fuehren, dass die */ + /* c,a und s- literale der Partnerclauses in die Listen kommen... */ + + if (list_PointerMember(Lits, (POINTER)i)) { + CLAUSE PartnerCopy; + LITERAL PLit; + TERM PAtom; + SUBST NewSubst,RightSubst; + int j,lc,la,n,PLitInd; + + Atom = clause_GetLiteralAtom(ClauseCopy, i); + NewClause = clause_CreateUnnormalized(Constraint, Antecedent, Succedent); + + list_Delete(Constraint); + list_Delete(Antecedent); + list_Delete(Succedent); + Constraint = list_Nil(); + Antecedent = list_Nil(); + Succedent = list_Nil(); + + /* Find corresponding Foundlit: */ + for (Scan = Foundlits; + term_TopSymbol(Atom) != + term_TopSymbol(clause_LiteralAtom(list_Car(Scan))); + Scan = list_Cdr(Scan)); + PLit = list_Car(Scan); + PLitInd = clause_LiteralGetIndex(PLit); + PartnerCopy = clause_Copy(clause_LiteralOwningClause(PLit)); + Partners = list_Cons(PartnerCopy, Partners); + ParentCls = list_Cons((POINTER)clause_Number(PartnerCopy), ParentCls); + ParentLits = list_Cons((POINTER)PLitInd, ParentLits); + MaxVar = clause_SearchMaxVar(ClauseCopy); + MaxCand = clause_SearchMaxVar(NewClause); + MaxVar = ((MaxVar > MaxCand) ? MaxVar : MaxCand); + /* MaxVar is the maximal variable in the new clause or the ClauseCopy, */ + /* the latter to guarantee the stability of variable names. */ + + clause_RenameVarsBiggerThan(PartnerCopy, MaxVar); + PLit = clause_GetLiteral(PartnerCopy, PLitInd); + PAtom = clause_LiteralAtom(PLit); + + cont_Check(); + if (!unify_UnifyNoOC(cont_LeftContext(), PAtom, cont_RightContext(), Atom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_BuildConstraintHyperResolvent: Unification failed."); + misc_FinishErrorReport(); + } + subst_ExtractUnifier(cont_LeftContext(), &RightSubst, cont_RightContext(), &NewSubst); + cont_Reset(); + + clause_SubstApply(NewSubst, NewClause); + clause_SubstApply(NewSubst, ClauseCopy); + subst_Delete(NewSubst); + + n = clause_Length(PartnerCopy); + lc = clause_LastConstraintLitIndex(PartnerCopy); + la = clause_LastAntecedentLitIndex(PartnerCopy); + for (j = clause_FirstLitIndex(); j < n; j++) { + if (j <= lc) + Constraint = list_Cons(subst_Apply(RightSubst, + term_Copy(clause_GetLiteralAtom(PartnerCopy, j))), + Constraint); + else if (j <= la) + Antecedent = list_Cons(subst_Apply(RightSubst, + term_Copy(clause_GetLiteralAtom(PartnerCopy, j))), + Antecedent); + else if (j != PLitInd) + Succedent = list_Cons(subst_Apply(RightSubst, + term_Copy(clause_GetLiteralAtom(PartnerCopy, j))), + Succedent); + } + + subst_Delete(RightSubst); + + n = clause_Length(NewClause); + lc = clause_LastConstraintLitIndex(NewClause); + la = clause_LastAntecedentLitIndex(NewClause); + + for (j = clause_FirstLitIndex(); j < n; j++) { + if (j <= lc) + Constraint = list_Cons(term_Copy(clause_GetLiteralAtom(NewClause, j)), + Constraint); + else if (j <= la) + Antecedent = list_Cons(term_Copy(clause_GetLiteralAtom(NewClause, j)), + Antecedent); + else + Succedent = list_Cons(term_Copy(clause_GetLiteralAtom(NewClause, j)), + Succedent); + } + clause_Delete(NewClause); + clause_DecreaseCounter(); + } + } + NewClause = clause_Create(Constraint, Antecedent, Succedent, Flags,Precedence); + + list_Delete(Constraint); + list_Delete(Antecedent); + list_Delete(Succedent); + + if (IsFromEmptySort) + clause_SetFromEmptySort(NewClause); + else + clause_SetFromSortResolution(NewClause); + + clause_SetDepth(NewClause, depth + 1); + + clause_SetSplitDataFromList(NewClause, Partners); + clause_DeleteClauseList(Partners); + + clause_SetParentClauses(NewClause, list_NReverse(ParentCls)); + clause_SetParentLiterals(NewClause, list_NReverse(ParentLits)); + + return NewClause; +} + + +static LIST inf_ConstraintHyperResolvents(CLAUSE Clause, LIST Lits, + SUBST Subst, LIST Restlits, + LIST Foundlits, st_INDEX Index, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A <Clause> where the sort constraint is resolved, + a list <Lits> of constraint indices in <Clause> where + all corresponding constraints have the same term, + the overall substitution <Subst>, + a list <Restlits> of constraint indeces for which + a partner clause is searched with respect to <Index>, + a list <Foundlits> of literals of already found partner clauses, + a flag store and a precedence. + RETURNS: The list of possible resolvents. +***************************************************************/ +{ + if (list_Empty(Restlits)) + return list_List(inf_BuildConstraintHyperResolvent(Clause,Lits,Subst, + Foundlits, Flags, + Precedence)); + else { + CLAUSE PartnerCopy; + LITERAL Lit, PLit; + LIST Result, NextLits; + TERM AtomCopy; + SUBST NewSubst, RightSubst, HelpSubst; + SYMBOL MaxVar, MaxCand; + int PLitInd; + + Result = list_Nil(); + Lit = clause_GetLiteral(Clause, (int) list_Car(Restlits)); + AtomCopy = subst_Apply(Subst, term_Copy(clause_LiteralAtom(Lit))); + NextLits = inf_GetSortResolutionPartnerLits(AtomCopy,Index); + MaxVar = clause_MaxVar(Clause); + MaxCand = clause_AtomMaxVar(AtomCopy); + MaxVar = (symbol_GreaterVariable(MaxVar, MaxCand) ? MaxVar : MaxCand); + + for ( ; !list_Empty(NextLits); NextLits = list_Pop(NextLits)) { + PLit = list_Car(NextLits); + PLitInd = clause_LiteralGetIndex(PLit); + Foundlits = list_Cons(PLit, Foundlits); + PartnerCopy = clause_Copy(clause_LiteralOwningClause(PLit)); + + clause_RenameVarsBiggerThan(PartnerCopy, MaxVar); + PLit = clause_GetLiteral(PartnerCopy, PLitInd); + + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(), AtomCopy, + cont_RightContext(), clause_LiteralAtom(PLit)); + subst_ExtractUnifier(cont_LeftContext(), &NewSubst, cont_RightContext(), &RightSubst); + cont_Reset(); + + subst_Delete(RightSubst); + HelpSubst = NewSubst; + NewSubst = subst_Compose(NewSubst, subst_Copy(Subst)); + + Result = list_Nconc(inf_ConstraintHyperResolvents(Clause, Lits, NewSubst, + list_Cdr(Restlits), + Foundlits, Index, Flags, + Precedence), + Result); + subst_Delete(NewSubst); + subst_Delete(HelpSubst); + clause_Delete(PartnerCopy); + + Foundlits = list_Pop(Foundlits); + } + term_Delete(AtomCopy); + + return Result; + } +} + + +LIST inf_BackwardSortResolution(CLAUSE GivenClause, st_INDEX Index, + SORTTHEORY SortTheory, BOOL Precheck, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause with a solved sort constraint, an index of clauses, + a sort theory, a boolean flag indicating whether the subsort + precheck can be applied, a flag store and a precedence. + RETURNS: A list of clauses inferred from the GivenClause by + SortResolution with the given clause. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST result; + int i, ls; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence) || + !clause_HasSolvedConstraint(GivenClause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_BackwardSortResolution: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + result = list_Nil(); + ls = clause_LastSuccedentLitIndex(GivenClause); + + for (i = clause_FirstSuccedentLitIndex(GivenClause); i <= ls; i++) { + LITERAL pLit; + TERM pAtom; + + pLit = clause_GetLiteral(GivenClause, i); + pAtom = clause_LiteralAtom(pLit); + + if (clause_LiteralGetFlag(pLit,STRICTMAXIMAL) && + clause_LiteralIsSort(pLit)) { + LIST termList; + termList = st_GetUnifier(cont_LeftContext(),Index,cont_RightContext(),pAtom); + + for ( ; !list_Empty(termList); termList = list_Pop(termList)){ + if (term_IsAtom(list_Car(termList)) && + !term_IsVariable(term_FirstArgument(list_Car(termList)))) { + + LIST litScan; + litScan = sharing_NAtomDataList(list_Car(termList)); + for ( ; !list_Empty(litScan); litScan = list_Cdr(litScan)) { + LITERAL gLit; + CLAUSE gClause; + gLit = list_Car(litScan); + gClause = clause_LiteralOwningClause(gLit); + if (clause_LiteralGetIndex(gLit) < clause_FirstAntecedentLitIndex(gClause) && + clause_GetFlag(gClause,WORKEDOFF)) { + TERM gAtom; + int lc, gi, j; + LIST tLits, restLits; + gAtom = clause_LiteralAtom(gLit); + lc = clause_LastConstraintLitIndex(gClause); + gi = clause_LiteralGetIndex(gLit); + tLits = list_List((POINTER)gi); + restLits = list_Nil(); + for (j = clause_FirstLitIndex(); j <= lc; j++) { + LITERAL tCand; + tCand = clause_GetLiteral(gClause, j); + if (j != gi && + term_FirstArgument(clause_LiteralAtom(tCand)) + == term_FirstArgument(gAtom)) { + tLits = list_Cons((POINTER)j, tLits); + restLits = list_Cons((POINTER)j, restLits); + } + } + + if (!Precheck || + inf_SubsortPrecheck(gClause,tLits,pLit,Index,SortTheory)) { + CLAUSE pClauseCopy; + SYMBOL minVar; + LIST foundLits; + SUBST leftSubst, rightSubst; + pClauseCopy = clause_Copy(GivenClause); + minVar = clause_MaxVar(gClause); + foundLits = list_List(pLit); + + clause_RenameVarsBiggerThan(pClauseCopy, minVar); + pAtom = clause_GetLiteralAtom(pClauseCopy, i); + /* set, to unify correctly! */ + + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(), gAtom, cont_RightContext(), pAtom); + subst_ExtractUnifier(cont_LeftContext(), &leftSubst, + cont_RightContext(), &rightSubst); + cont_Reset(); + + subst_Delete(rightSubst); + + result = + list_Nconc(inf_ConstraintHyperResolvents(gClause, tLits, + leftSubst, restLits, + foundLits, Index, + Flags, Precedence), + result); + + pAtom = clause_LiteralAtom(pLit); + + subst_Delete(leftSubst); + list_Delete(foundLits); + clause_Delete(pClauseCopy); + } /* if Precheck */ + list_Delete(tLits); + list_Delete(restLits); + } + } + } + } + } + } + return result; +} + + +LIST inf_ForwardSortResolution(CLAUSE GivenClause, st_INDEX Index, + SORTTHEORY SortTheory, BOOL Precheck, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause with an unsolved sort constraint, an index of clauses, + a sort theory, a boolean flag indicating whether the subsort + precheck can be applied, a flag store and a precedence. + RETURNS: A list of clauses inferred from the GivenClause by + SortResolution on the given clause. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result, TLits, RestLits; + int i, j, lc; + BOOL Hit; + TERM TAtom; + +#ifdef CHECK + if (!clause_IsClause(GivenClause, Flags, Precedence) || + !clause_HasTermSortConstraintLits(GivenClause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_ForwardSortResolution: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + Result = list_Nil(); + lc = clause_LastConstraintLitIndex(GivenClause); + Hit = FALSE; + + i = clause_FirstLitIndex(); + while (i <= lc && !Hit) { + TAtom = clause_GetLiteralAtom(GivenClause, i); + if (!term_IsVariable(term_FirstArgument(TAtom))) + Hit = TRUE; + else + i++; + } + + if (!Hit) + return list_Nil(); + + /* added because of compiler warnings */ + TAtom = clause_GetLiteralAtom(GivenClause, i); + + /* Search the other T_i from <GivenClause> */ + TLits = list_List((POINTER)i); + for (j = i+1; j <= lc; j++) { + if (term_FirstArgument(clause_GetLiteralAtom(GivenClause, j)) + == term_FirstArgument(TAtom)) + TLits = list_Cons((POINTER)j, TLits); + } + RestLits = list_Copy(TLits); + + if (!Precheck || + inf_SubsortPrecheck(GivenClause, TLits, NULL, Index, SortTheory)) { + + Result = inf_ConstraintHyperResolvents(GivenClause, TLits, subst_Nil(), + RestLits, list_Nil(), Index, Flags, + Precedence); + + } + list_Delete(RestLits); + list_Delete(TLits); + + return Result; +} + + +LIST inf_BackwardEmptySort(CLAUSE GivenClause, st_INDEX Index, + SORTTHEORY SortTheory, BOOL Precheck, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause with a solved sort constraint, an 'Index' of clauses, + a sort theory, a boolean flag indicating whether the subsort + precheck can be applied, a flag store and a precedence. + RETURNS: A list of clauses inferred from the GivenClause by + EmptySort with the given clause. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST result; + int i, ls; + +#ifdef CHECK + if (!(clause_IsClause(GivenClause, Flags, Precedence)) || + !clause_HasSolvedConstraint(GivenClause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_BackwardEmptySort: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + result = list_Nil(); + + ls = clause_LastSuccedentLitIndex(GivenClause); + + for (i = clause_FirstSuccedentLitIndex(GivenClause); i <= ls; i++) { + LITERAL pLit = clause_GetLiteral(GivenClause, i); + TERM pAtom = clause_LiteralAtom(pLit); + + if (clause_LiteralGetFlag(pLit,STRICTMAXIMAL) && + clause_LiteralIsSort(pLit)) { + LIST unifiers = st_GetUnifier(cont_LeftContext(),Index,cont_RightContext(),pAtom); + + for ( ; !list_Empty(unifiers); unifiers = list_Pop(unifiers)){ + if (term_IsAtom(list_Car(unifiers)) && + term_IsVariable(term_FirstArgument(list_Car(unifiers)))) { + LIST litScan = sharing_NAtomDataList(list_Car(unifiers)); + + for ( ; !list_Empty(litScan); litScan = list_Cdr(litScan)){ + LITERAL gLit = list_Car(litScan); + CLAUSE gClause = clause_LiteralOwningClause(gLit); + + if (clause_LiteralGetIndex(gLit) < clause_FirstAntecedentLitIndex(gClause) && + clause_GetFlag(gClause,WORKEDOFF) && + clause_HasOnlyVarsInConstraint(gClause, Flags, Precedence)) { + TERM gAtom = clause_LiteralAtom(gLit); + SYMBOL var = term_TopSymbol(term_FirstArgument(gAtom)); + int lc = clause_LastConstraintLitIndex(gClause); + int gi = clause_LiteralGetIndex(gLit); + BOOL varOccursNoMore; + int j, bound; + + varOccursNoMore = TRUE; + bound = clause_LastSuccedentLitIndex(gClause); + + for (j = clause_FirstAntecedentLitIndex(gClause); + (j <= bound) && varOccursNoMore; + j++) { + if (term_ContainsSymbol(clause_GetLiteralAtom(gClause, j), var)) + varOccursNoMore = FALSE; + } + + if (varOccursNoMore) { + LIST tLits, restLits; + + /* Search the other T_i from <gClause> */ + tLits = list_List((POINTER)gi); + restLits = list_Nil(); + for (j = clause_FirstLitIndex(); j <= lc; j++) { + LITERAL tCand = clause_GetLiteral(gClause, j); + + if (j != gi && + term_FirstArgument(clause_LiteralAtom(tCand)) + == term_FirstArgument(gAtom)) { + tLits = list_Cons((POINTER)j, tLits); + restLits = list_Cons((POINTER)j, restLits); + } + } + + if (!Precheck || + inf_SubsortPrecheck(gClause,tLits,pLit,Index,SortTheory)) { + CLAUSE pCopy = clause_Copy(GivenClause); + SYMBOL minVar = clause_MaxVar(gClause); + LIST foundLits = list_List(pLit); + SUBST leftSubst, rightSubst; + + clause_RenameVarsBiggerThan(pCopy, minVar); + pAtom = clause_GetLiteralAtom(pCopy, i); + /* set, to adress the renamed term! */ + + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(), gAtom, cont_RightContext(), pAtom); + subst_ExtractUnifier(cont_LeftContext(), &leftSubst, + cont_RightContext(), &rightSubst); + cont_Reset(); + + subst_Delete(rightSubst); + + result = + list_Nconc(inf_ConstraintHyperResolvents(gClause, tLits, + leftSubst,restLits, + foundLits, Index, + Flags, Precedence), + result); + + list_Delete(foundLits); + subst_Delete(leftSubst); + clause_Delete(pCopy); + + pAtom = clause_LiteralAtom(pLit); + /* reset to original clauses literal! */ + } /* if Precheck */ + list_Delete(tLits); + list_Delete(restLits); + } + } + } + } + } + } + } + return result; +} + + +LIST inf_ForwardEmptySort(CLAUSE GivenClause, st_INDEX Index, + SORTTHEORY SortTheory, BOOL Precheck, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, an index of clauses, a sort theory, + a boolean flag indicating whether the subsort + precheck can be applied, a flag store and a precedence. + The constraint of <GivenClause> is necessarily unsolved + RETURNS: A list of clauses inferred from the GivenClause by + EmptySort on the given clause. + MEMORY: A list of clauses is produced, where memory for the list + and the clauses is allocated. +***************************************************************/ +{ + LIST Result, TLits, RestLits; + int i, j, lc, ls; + BOOL Hit; + TERM TAtom; + SYMBOL Var; + +#ifdef CHECK + if (clause_HasTermSortConstraintLits(GivenClause) || + clause_HasSolvedConstraint(GivenClause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_ForwardEmptySort: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + Result = list_Nil(); + lc = clause_LastConstraintLitIndex(GivenClause); + Hit = FALSE; + + i = clause_FirstLitIndex(); + while (i <= lc && !Hit) { + TAtom = clause_GetLiteralAtom(GivenClause, i); + + if (term_IsVariable(term_FirstArgument(TAtom))) { + Var = term_TopSymbol(term_FirstArgument(TAtom)); + ls = clause_LastSuccedentLitIndex(GivenClause); + Hit = TRUE; + /* Check if the variable occurs in antecedent or succedent literals */ + for (j = clause_FirstAntecedentLitIndex(GivenClause); + j <= ls && Hit; j++) { + if (term_ContainsSymbol(clause_GetLiteralAtom(GivenClause,j), Var)) + Hit = FALSE; /* Variable occurs in antecedent/constraint literal */ + } + } + if (!Hit) + i++; + } + + if (!Hit) + return list_Nil(); + + TAtom = clause_GetLiteralAtom(GivenClause, i); + Var = term_TopSymbol(term_FirstArgument(TAtom)); + + /* Search the other T_i(t) literals */ + TLits = list_List((POINTER)i); + for (j = i+1; j <= lc; j++) { + TERM TCand; + + TCand = clause_GetLiteralAtom(GivenClause, j); + + if (symbol_Equal(term_TopSymbol(term_FirstArgument(TCand)), Var)) + TLits = list_Cons((POINTER)j, TLits); + } + RestLits = list_Copy(TLits); + + if (!Precheck || + inf_SubsortPrecheck(GivenClause, TLits, NULL, Index, SortTheory)) { + + Result = inf_ConstraintHyperResolvents(GivenClause, TLits, subst_Nil(), + RestLits, list_Nil(), Index, Flags, + Precedence); + + } + list_Delete(RestLits); + list_Delete(TLits); + + return Result; +} + +static LIST inf_GetForwardPartnerLits(LITERAL Literal, st_INDEX Index) +/************************************************************** + INPUT: A monadic literal, and an index of clauses. + RETURNS: A list of monadic succedent literals whose subterm + is unifiable with the (one) subterm of <Literal>. + The literals are strict maximal in their respective clauses, + the clauses are "WORKEDOFF" and either the subterm + is not a variable or the clause has an empty constraint. + MEMORY: Allocates memory for the list. +***************************************************************/ +{ + LIST result, unifiers, atomScan, litScan; + +#ifdef CHECK + if (!clause_LiteralIsLiteral(Literal) || !clause_LiteralIsSort(Literal)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GetForwardPartnerLits: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + result = list_Nil(); + /* Search unifiers for the literal's subterm */ + unifiers = st_GetUnifier(cont_LeftContext(), Index, cont_RightContext(), + term_FirstArgument(clause_LiteralAtom(Literal))); + + for ( ; !list_Empty(unifiers); unifiers = list_Pop(unifiers)) { + + if (!term_IsAtom(list_Car(unifiers))) { /* Can happen if arg is variable */ + + for (atomScan = term_SupertermList(list_Car(unifiers)); + !list_Empty(atomScan); + atomScan = list_Cdr(atomScan)) { + TERM atomCand; + atomCand = (TERM) list_Car(atomScan); + if (term_IsDeclaration(atomCand)) { + /* We are looking for an unary atom */ + + for (litScan = sharing_NAtomDataList(atomCand); + !list_Empty(litScan); + litScan = list_Cdr(litScan)) { + LITERAL nextLit; + CLAUSE nextClause; + nextLit = list_Car(litScan); + nextClause = clause_LiteralOwningClause(nextLit); + + if (clause_LiteralIsPositive(nextLit) && + clause_LiteralGetFlag(nextLit,STRICTMAXIMAL) && + clause_GetFlag(nextClause, WORKEDOFF) && + (!term_IsVariable(list_Car(unifiers)) || + clause_HasEmptyConstraint(nextClause)) && + clause_HasSolvedConstraint(nextClause)) { + /* Add the literal from the copied clause */ + result = list_Cons(nextLit, result); + } + } /* litScan */ + } /* if IsAtom */ + } /* atomScan */ + } /* ! variable */ + } /* unifiers */ + return result; +} + +static BOOL inf_LiteralsHaveSameSubtermAndAreFromSameClause(LITERAL L1, LITERAL L2) +/************************************************************** + INPUT: Two literals. + RETURNS: TRUE, if both literals have the same term and are + from the same clause, FALSE otherwise. + Since both literals are shared, pointer equality + is used to detect this. + This function is used by inf_GetBackwardPartnerLits(). +***************************************************************/ +{ + return (term_FirstArgument(clause_LiteralAtom(L1)) + == term_FirstArgument(clause_LiteralAtom(L2)) && + clause_LiteralOwningClause(L1) == clause_LiteralOwningClause(L2)); +} + +static void inf_GetBackwardPartnerLits(LITERAL Literal, st_INDEX Index, + LIST* ConstraintLits, LIST* Unifiers, + BOOL IsFromEmptySort, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A literal, an index of clauses, two pointers to lists, + a boolean value, a flag store and a precedence. + RETURNS: + MEMORY: Allocates memory for the list. +***************************************************************/ +{ + LIST candidates, atomScan, litScan; + LITERAL nextLit; + CLAUSE nextClause; + +#ifdef CHECK + if (!clause_LiteralIsLiteral(Literal) || !clause_LiteralIsSort(Literal)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_GetBackwardPartnerLits: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + candidates = st_GetUnifier(cont_LeftContext(), Index, cont_RightContext(), + term_FirstArgument(clause_LiteralAtom(Literal))); + + for ( ; !list_Empty(candidates); candidates = list_Pop(candidates)) { + if (!term_IsAtom(list_Car(candidates))) { /* May happen if arg is variable */ + /* Consider variable unifiers only if called from BackwardEmptySort */ + for (atomScan = term_SupertermList(list_Car(candidates)); + !list_Empty(atomScan); + atomScan = list_Cdr(atomScan)) { + TERM atomCand; + atomCand = (TERM) list_Car(atomScan); + if (term_IsDeclaration(atomCand)) { + /* We are looking for unary atoms */ + + for (litScan = sharing_NAtomDataList(atomCand); + !list_Empty(litScan); + litScan = list_Cdr(litScan)) { + nextLit = list_Car(litScan); + nextClause = clause_LiteralOwningClause(nextLit); + + if (clause_GetFlag(nextClause, WORKEDOFF)) { + if (clause_LiteralIsPositive(nextLit)) { + if (clause_LiteralGetFlag(nextLit,STRICTMAXIMAL) && + (!term_IsVariable(list_Car(candidates)) || + clause_HasEmptyConstraint(nextClause)) && + clause_HasSolvedConstraint(nextClause) && + !symbol_Equal(clause_LiteralPredicate(Literal), + clause_LiteralPredicate(nextLit))) { + /* Don't consider literals with same top symbol as given literal */ + /* since the given clause must be part of any inference */ + *Unifiers = list_Cons(nextLit, *Unifiers); + } + } else if (clause_LiteralGetIndex(nextLit) < clause_FirstAntecedentLitIndex(nextClause) && + ((!term_IsVariable(list_Car(candidates)) && !IsFromEmptySort) || + (term_IsVariable(list_Car(candidates)) && IsFromEmptySort && + clause_HasOnlyVarsInConstraint(nextClause,Flags, Precedence)))) { + *ConstraintLits = list_Cons(nextLit, *ConstraintLits); + } + } + } /* litScan */ + } + } /* atomScan */ + } + } /* candidates */ + + /* We have to avoid constraint literals from the same clause with the same + term or variable, since those would create the same result clause. */ + *ConstraintLits = + list_DeleteDuplicates(*ConstraintLits, + (BOOL (*)(POINTER,POINTER)) inf_LiteralsHaveSameSubtermAndAreFromSameClause); +} + +static void inf_MakeClausesDisjoint(CLAUSE GClause, LIST Literals) +/************************************************************** + INPUT: A clause and a non-empty list of literals. + EFFECT: All input clauses, those pointed to by the literals, + are variable disjointly renamed. +***************************************************************/ +{ + SYMBOL maxVar, maxCand; + CLAUSE lastClause; + + maxVar = clause_MaxVar(GClause); + lastClause = clause_LiteralOwningClause(list_Car(Literals)); + clause_RenameVarsBiggerThan(lastClause, maxVar); + Literals = list_Cdr(Literals); + + for ( ; !list_Empty(Literals); Literals = list_Cdr(Literals)) { + CLAUSE actClause; + + clause_UpdateMaxVar(lastClause); + maxCand = clause_MaxVar(lastClause); + maxVar = (symbol_GreaterVariable(maxVar,maxCand)? maxVar : maxCand); + + actClause = clause_LiteralOwningClause(list_Car(Literals)); + clause_RenameVarsBiggerThan(actClause, maxVar); + } +} + +static void inf_CopyUnifierClauses(LIST Literals) +/************************************************************** + INPUT: A list of literals. + EFFECT: Replaces all literals by pointers to literals of copies + of the respective clauses. +***************************************************************/ +{ + for ( ; !list_Empty(Literals); Literals = list_Cdr(Literals)) { + CLAUSE actClause; + int i; + + actClause = clause_LiteralOwningClause(list_Car(Literals)); + i = clause_LiteralGetIndex(list_Car(Literals)); + actClause = clause_Copy(actClause); + list_Rplaca(Literals, clause_GetLiteral(actClause, i)); /* Set to literal from copy */ + } +} + +static void inf_DeleteUnifierClauses(LIST Literals) +/************************************************************** + INPUT: A list of literals. + EFFECT: Deletes all clauses the literals point to. +***************************************************************/ +{ + for ( ; !list_Empty(Literals); Literals = list_Cdr(Literals)) { + clause_Delete(clause_LiteralOwningClause(list_Car(Literals))); + list_Rplaca(Literals, NULL); + } +} + +static SORT inf_GetSortFromLits(LIST Literals, SORTTHEORY SortTheory) +/************************************************************** + INPUT: A list of literals and a sort theory. + RETURNS: The sort created from the literals' predicates. +***************************************************************/ +{ + SORT result = sort_TopSort(); + + for ( ; !list_Empty(Literals); Literals = list_Cdr(Literals)) { + SORT newSort = sort_TheorySortOfSymbol(SortTheory, + clause_LiteralPredicate(list_Car(Literals))); + + result = sort_Intersect(newSort, result); + } + + list_PointerDeleteDuplicates(result); + + return result; +} + +static LIST inf_ApplyWeakening(CLAUSE Clause, LIST TLits, LIST Partners, + CONDITION Condition, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a list of constraint indices in <Clause>, + a list of maximal, monadic succedent literals, + a subsort condition, a flag store and a precedence. + RETURNS: A one-element list with a clause derived from the + clause and the partner clauses by the Weakening or + Empty Sort rule. + The flag store is needed to create the result clause. + MEMORY: Memory is allocated for the returned list and the clause. +***************************************************************/ +{ + LIST scan, parents; + LIST constraint, antecedent, succedent; + LIST parentClauses, parentLits; /* clause numbers and literal indices */ + int i, bound, depth; + TERM tSubterm; + CLAUSE newClause; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence) || list_Empty(TLits) || + list_Empty(Partners) || Condition == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_ApplyWeakening: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + constraint = antecedent = succedent = list_Nil(); + parentClauses = parentLits = list_Nil(); + parents = list_Nil(); /* Used to set split data */ + depth = clause_Depth(Clause); + tSubterm = term_FirstArgument(clause_GetLiteralAtom(Clause, (int)list_Car(TLits))); + + /* Now collect the literals of the new clause */ + /* First consider the condition atoms */ + for (scan=sort_ConditionConstraint(Condition); !list_Empty(scan); scan=list_Cdr(scan)) { + TERM termCopy; + + termCopy = term_Copy(list_Car(scan)); + term_ReplaceVariable(termCopy, sort_ConditionVar(Condition), tSubterm); + constraint = list_Cons(cont_CopyAndApplyBindings(cont_LeftContext(), termCopy), + constraint); + term_Delete(termCopy); /* constraint contains a copy */ + } + for (scan=sort_ConditionAntecedent(Condition); !list_Empty(scan); scan=list_Cdr(scan)) { + TERM termCopy; + + termCopy = term_Copy(list_Car(scan)); + term_ReplaceVariable(termCopy, sort_ConditionVar(Condition), tSubterm); + antecedent = list_Cons(cont_CopyAndApplyBindings(cont_LeftContext(), termCopy), + antecedent); + term_Delete(termCopy); /* antecedent contains a copy */ + } + for (scan=sort_ConditionSuccedent(Condition); !list_Empty(scan); scan=list_Cdr(scan)) { + TERM termCopy; + + termCopy = term_Copy(list_Car(scan)); + term_ReplaceVariable(termCopy, sort_ConditionVar(Condition), tSubterm); + succedent = list_Cons(cont_CopyAndApplyBindings(cont_LeftContext(), termCopy), + succedent); + term_Delete(termCopy); /* succedent contains a copy */ + } + /* update parents and depth from condition clauses */ + for (scan=sort_ConditionClauses(Condition); !list_Empty(scan); scan=list_Cdr(scan)) { + CLAUSE condClause; + + condClause = list_Car(scan); + parents = list_Cons(condClause, parents); + parentClauses = list_Cons((POINTER)clause_Number(condClause), parentClauses); + parentLits = list_Cons((POINTER)clause_FirstSuccedentLitIndex(condClause), parentLits); + depth = misc_Max(depth, clause_Depth(condClause)); + } + + /* Now we consider the partner clauses */ + for (scan = Partners; !list_Empty(scan); scan = list_Cdr(scan)) { + LITERAL pLit; + CLAUSE pClause; + int pi; + + pLit = list_Car(scan); + pClause = clause_LiteralOwningClause(pLit); + pi = clause_LiteralGetIndex(pLit); + bound = clause_LastConstraintLitIndex(pClause); + for (i = clause_FirstLitIndex(); i <= bound; i++) { + constraint = list_Cons(cont_CopyAndApplyBindings(cont_RightContext(), + clause_GetLiteralAtom(pClause,i)), + constraint); + } + bound = clause_LastAntecedentLitIndex(pClause); + for (i = clause_FirstAntecedentLitIndex(pClause); i <= bound; i++) { + antecedent = list_Cons(cont_CopyAndApplyBindings(cont_RightContext(), + clause_GetLiteralAtom(pClause,i)), + antecedent); + } + bound = clause_LastSuccedentLitIndex(pClause); + for (i = clause_FirstSuccedentLitIndex(pClause); i <= bound; i++) { + if (i != pi) + succedent = list_Cons(cont_CopyAndApplyBindings(cont_RightContext(), + clause_GetLiteralAtom(pClause,i)), + succedent); + } + + parents = list_Cons(pClause, parents); + + parentClauses = list_Cons((POINTER)clause_Number(pClause), parentClauses); + parentLits = list_Cons((POINTER) pi, parentLits); + + depth = misc_Max(depth, clause_Depth(pClause)); + } + + /* Last but not least we consider the <Clause> itself */ + bound = clause_LastConstraintLitIndex(Clause); + for (i = clause_FirstLitIndex(); i <= bound; i++) { + if (!list_PointerMember(TLits, (POINTER)i)) + constraint = list_Cons(cont_CopyAndApplyBindings(cont_LeftContext(), + clause_GetLiteralAtom(Clause,i)), + constraint); + else { + parentClauses = list_Cons((POINTER)clause_Number(Clause), parentClauses); + parentLits = list_Cons((POINTER)i, parentLits); + } + } + bound = clause_LastAntecedentLitIndex(Clause); + for (i = clause_FirstAntecedentLitIndex(Clause); i <= bound; i++) { + antecedent = list_Cons(cont_CopyAndApplyBindings(cont_LeftContext(), + clause_GetLiteralAtom(Clause,i)), + antecedent); + } + bound = clause_LastSuccedentLitIndex(Clause); + for (i = clause_FirstSuccedentLitIndex(Clause); i <= bound; i++) { + succedent = list_Cons(cont_CopyAndApplyBindings(cont_LeftContext(), + clause_GetLiteralAtom(Clause,i)), + succedent); + } + + parents = list_Cons(Clause, parents); + + /* Now we've got all data we need */ + newClause = clause_Create(constraint, antecedent, succedent, Flags,Precedence); + + list_Delete(constraint); + list_Delete(antecedent); + list_Delete(succedent); + + if (term_IsVariable(tSubterm)) + clause_SetFromEmptySort(newClause); + else + clause_SetFromSortResolution(newClause); + + clause_SetDepth(newClause, depth+1); + clause_SetFlag(newClause, DOCCLAUSE); + + clause_SetSplitDataFromList(newClause, parents); + list_Delete(parents); + + clause_SetParentClauses(newClause, parentClauses); + clause_SetParentLiterals(newClause, parentLits); + + return list_List(newClause); +} + +static LIST inf_InternWeakening(CLAUSE Clause, LIST TLits, LIST Unifiers, + LITERAL Special, LIST SojuList, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A <Clause> with unsolved sort constraint, + a list <TLits> of constraint indices in <Clause> where + all corresponding constraints have the same term, + a list <Unifiers> of monadic succedent literals whose + subterm is unifiable with the subterm of the <TLits>, + and a flag store. + If called from a backward rule the literal <Special> + will be the succedent literal from the respective + GivenClause, that must be part of every considered + SOJU sort. If called from a forward rule <Special> is NULL. + A list <SojuList> of sort pairs. + A flag store and a precedence. + RETURNS: The list of possible resolvents. + EFFECT: ATTENTION: <SojuList> is deleted. + MEMORY: Memory is allocated for the returned list and the clauses. +***************************************************************/ +{ + LIST result, myUnifiers; + TERM searchTerm; + int stack; + + LIST scan; +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence) || list_Empty(TLits) || + list_Empty(Unifiers)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_InternWeakening: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + putchar('\n'); clause_Print(Clause); + fputs("\nT_k = ", stdout); + for (scan = TLits; !list_Empty(scan); scan = list_Cdr(scan)) { + clause_LiteralPrint(clause_GetLiteral(Clause, (int)list_Car(scan))); + putchar(' '); + } + fputs("\nS_k =", stdout); + for (scan = Unifiers; !list_Empty(scan); scan = list_Cdr(scan)) { + putchar('\n'); + clause_LiteralPrint(list_Car(scan)); + fputs(" in ", stdout); + clause_Print(clause_LiteralOwningClause(list_Car(scan))); + } + putchar('\n'); + + if (list_Empty(SojuList)) + return list_Nil(); + + /*return list_Nil();*/ + /* Und Schluss */ + + result = list_Nil(); + + myUnifiers = list_Copy(Unifiers); + inf_CopyUnifierClauses(myUnifiers); + inf_MakeClausesDisjoint(Clause, myUnifiers); + + searchTerm = + term_FirstArgument(clause_GetLiteralAtom(Clause, (int)list_Car(TLits))); + + stack = stack_Bottom(); + + for ( ; !list_Empty(SojuList); SojuList = list_Pop(SojuList)) { + SOJU actSoju = list_Car(SojuList); + + fputs("\nSOJU: ", stdout); sort_PairPrint(actSoju); fflush(stdout); + + if (Special == NULL || + sort_ContainsSymbol(sort_PairSort(actSoju), + clause_LiteralPredicate(Special))) { + LIST actSortSymbols, symbolScan, unifierScan, subset; + + actSortSymbols = sort_GetSymbolsFromSort(sort_PairSort(actSoju)); + subset = list_Nil(); + + symbolScan = actSortSymbols; + unifierScan = myUnifiers; + + do { + while (!list_Empty(symbolScan) && !list_Empty(unifierScan)) { + LITERAL actLit = list_Car(unifierScan); + + if (symbol_Equal(clause_LiteralPredicate(list_Car(unifierScan)), + (SYMBOL)list_Car(symbolScan))) { + cont_StartBinding(); + if (unify_UnifyNoOC(cont_LeftContext(), searchTerm, cont_RightContext(), + term_FirstArgument(clause_LiteralAtom(actLit)))) { + /* Found corresponding literal for sort symbol */ + stack_Push(symbolScan); + stack_Push(list_Cdr(unifierScan)); + subset = list_Cons(actLit, subset); + /* Now search literals for the next sort symbol */ + symbolScan = list_Cdr(symbolScan); + + if (!list_Empty(symbolScan)) + /* Start search for literal at the beginning of unifier list */ + unifierScan = myUnifiers; + else + unifierScan = list_Cdr(unifierScan); + } else { + cont_BackTrack(); + unifierScan = list_Cdr(unifierScan); + } + } else + unifierScan = list_Cdr(unifierScan); + } + + if (list_Empty(symbolScan)) { + /*putchar('\n'); + clause_LiteralListPrint(subset);*/ + /* Found subset */ + result = list_Nconc(inf_ApplyWeakening(Clause, TLits, subset, + sort_PairCondition(actSoju), + Flags, Precedence), + result); + } + + while (!stack_Empty(stack) && list_Empty(stack_Top())) { + /* No more literals */ + stack_NPop(2); + cont_BackTrack(); + subset = list_Pop(subset); + } + + if (!stack_Empty(stack)) { + /* Implies that stack_Top is a non-empty list */ + unifierScan = stack_PopResult(); + symbolScan = stack_PopResult(); + cont_BackTrack(); + subset = list_Pop(subset); + } + } while (!stack_Empty(stack) || !list_Empty(unifierScan)); + + list_Delete(actSortSymbols); + } + sort_PairDelete(actSoju); + } /* For all SOJUs */ + + inf_DeleteUnifierClauses(myUnifiers); + list_Delete(myUnifiers); + + return result; +} + +LIST inf_ForwardWeakening(CLAUSE GivenClause, st_INDEX Index, + SORTTHEORY SortTheory, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, an index of clauses, a sort theory, a flag store + and a precedence. + The sort constraint of the clause must contain a non-variable term + (this implies the sort constraint is unsolved). + RETURNS: A list of clauses derived from the GivenClause by + the Weakening rule. + MEMORY: Memory is allocated for the returned list and the clauses. +***************************************************************/ +{ + LIST result; + int i, lc; + BOOL hit; + +#ifdef CHECK + if (!clause_HasTermSortConstraintLits(GivenClause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_ForwardWeakening: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + result = list_Nil(); + lc = clause_LastConstraintLitIndex(GivenClause); + hit = FALSE; + + for (i = clause_FirstLitIndex(); i <= lc && !hit; i++) { + + if (!term_IsVariable(term_FirstArgument(clause_GetLiteralAtom(GivenClause, i)))) { + /* Condition implies that constraint is unsolved */ + LITERAL tLit; + LIST unifiers; + int j; + + tLit = clause_GetLiteral(GivenClause, i); + hit = TRUE; /* Try only the first appropriate constraint literal */ + unifiers = inf_GetForwardPartnerLits(tLit, Index); + + if (!list_Empty(unifiers)) { + TERM tAtom; + LIST tLits, sojuList; + SORT tSort, unifierSort; + + tAtom = clause_GetLiteralAtom(GivenClause, i); + + /* Search the other T_k(t) in GivenClause */ + tLits = list_Nil(); + tSort = sort_TopSort(); + for (j = lc; j > i; j--) { + TERM actAtom; + actAtom = clause_GetLiteralAtom(GivenClause, j); + if (term_FirstArgument(actAtom) == term_FirstArgument(tAtom)) { + tLits = list_Cons((POINTER)j, tLits); + tSort = sort_Intersect(sort_TheorySortOfSymbol(SortTheory, term_TopSymbol(actAtom)), + tSort); + } + } + tLits = list_Cons((POINTER)i, tLits); + tSort = sort_Intersect(sort_TheorySortOfSymbol(SortTheory, term_TopSymbol(tAtom)), + tSort); + list_PointerDeleteDuplicates(tSort); + /* Necessary for Christoph's function */ + + unifierSort = inf_GetSortFromLits(unifiers, SortTheory); + sojuList = sort_TheoryComputeAllSubsortHits(SortTheory, unifierSort, tSort); + sort_Delete(unifierSort); + sort_Delete(tSort); + + result = + list_Nconc(inf_InternWeakening(GivenClause, tLits, unifiers, NULL, + sojuList, Flags, Precedence), + result); + + list_Delete(tLits); + list_Delete(unifiers); + } + } + } + return result; +} + +LIST inf_BackwardWeakening(CLAUSE GivenClause, st_INDEX Index, + SORTTHEORY SortTheory, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause with solved sort constraint, an index of clauses, + a sort theory, a flag store and a precedence. + RETURNS: A list of clauses inferred from the GivenClause by + the Weakening rule. + MEMORY: Memory is allocated for the list and the clauses. +***************************************************************/ +{ + LIST result; + int i, ls; + +#ifdef CHECK + if (!clause_HasSolvedConstraint(GivenClause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_BackwardWeakening: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + result = list_Nil(); + ls = clause_LastSuccedentLitIndex(GivenClause); + + for (i = clause_FirstSuccedentLitIndex(GivenClause); i <= ls; i++) { + LITERAL sLit; + TERM sAtom; + + sLit = clause_GetLiteral(GivenClause, i); + sAtom = clause_LiteralAtom(sLit); + if (clause_LiteralGetFlag(sLit, STRICTMAXIMAL) && + clause_LiteralIsSort(sLit) && + (!term_IsVariable(term_FirstArgument(sAtom)) || + clause_HasEmptyConstraint(GivenClause))) { + LIST unifiers, partners; + SORT unifierSort; + + unifiers = partners = list_Nil(); + inf_GetBackwardPartnerLits(sLit,Index,&partners,&unifiers,FALSE,Flags, + Precedence); + unifiers = list_Cons(sLit, unifiers); + /* <partners> holds monadic constraint literals */ + /* <unifiers> holds monadic, maximal succedent literals */ + unifierSort = inf_GetSortFromLits(unifiers, SortTheory); + + for ( ; !list_Empty(partners); partners = list_Pop(partners)) { + LITERAL tLit; + CLAUSE tClause; + TERM tAtom; + int ti; + int lc; + int j; + LIST tLits, sojuList; + SORT tSort; + + tLit = list_Car(partners); + tClause = clause_LiteralOwningClause(tLit); + tAtom = clause_LiteralAtom(tLit); + ti = clause_LiteralGetIndex(tLit); + lc = clause_LastConstraintLitIndex(tClause); + + /* Search the other T_k(t) in GivenClause */ + tLits = list_Nil(); + tSort = sort_TopSort(); + for (j = lc; j >= clause_FirstLitIndex(); j--) { + TERM actAtom; + + actAtom = clause_GetLiteralAtom(tClause, j); + if (j != ti && + term_FirstArgument(actAtom) == term_FirstArgument(tAtom)) { + tLits = list_Cons((POINTER)j, tLits); + tSort = sort_Intersect(sort_TheorySortOfSymbol(SortTheory, term_TopSymbol(actAtom)), + tSort); + } + } + tLits = list_Cons((POINTER)ti, tLits); + tSort = sort_Intersect(sort_TheorySortOfSymbol(SortTheory, term_TopSymbol(tAtom)), + tSort); + list_PointerDeleteDuplicates(tSort); + + sojuList = sort_TheoryComputeAllSubsortHits(SortTheory, unifierSort, tSort); + sort_Delete(tSort); + + cont_StartBinding(); + unify_UnifyNoOC(cont_LeftContext(), tAtom, + cont_RightContext(), sAtom); + + result = + list_Nconc(inf_InternWeakening(tClause, tLits, unifiers, sLit, + sojuList, Flags, Precedence), + result); + + cont_BackTrack(); + + list_Delete(tLits); + } + sort_Delete(unifierSort); + list_Delete(unifiers); + } + } + + return result; +} + +LIST inf_ForwardEmptySortPlusPlus(CLAUSE GivenClause, st_INDEX Index, + SORTTHEORY SortTheory, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, an 'Index' of clauses, a sort theory, a flag store + and a precedence. + The sort constraint of the clause must not contain a + non-variable term, but the sort constraint has to be unsolved. + RETURNS: A list of clauses derived from the GivenClause by + the Empty Sort rule. + MEMORY: Memory is allocated for the returned list and the clauses. +***************************************************************/ +{ + LIST result; + int i, lc; + BOOL hit; + +#ifdef CHECK + if (clause_HasTermSortConstraintLits(GivenClause) || + clause_HasSolvedConstraint(GivenClause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_ForwardEmptySortPlusPlus: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + result = list_Nil(); + lc = clause_LastConstraintLitIndex(GivenClause); + hit = FALSE; + + for (i = clause_FirstLitIndex(); i <= lc && !hit; i++) { + + if (term_IsVariable(term_FirstArgument(clause_GetLiteralAtom(GivenClause,i)))) { + LITERAL tLit; + TERM var; + int j, ls; + BOOL varOccursNoMore; + + tLit = clause_GetLiteral(GivenClause, i); + var = term_FirstArgument(clause_LiteralAtom(tLit)); + ls = clause_LastSuccedentLitIndex(GivenClause); + varOccursNoMore = TRUE; + /* Check if the variable occurs in antecedent or succedent literals */ + for (j = clause_FirstAntecedentLitIndex(GivenClause); + (j <= ls) && varOccursNoMore; j++) { + if (term_ContainsSymbol(clause_GetLiteralAtom(GivenClause,j), + term_TopSymbol(var))) + varOccursNoMore = FALSE; + } + + if (varOccursNoMore) { + /* Condition implies that constraint is unsolved */ + LIST unifiers; + + unifiers = inf_GetForwardPartnerLits(tLit, Index); + hit = TRUE; /* We found the first appropriate constraint literal */ + + if (!list_Empty(unifiers)) { + TERM tAtom = clause_LiteralAtom(tLit); + LIST tLits, sojuList; + SORT tSort, unifierSort; + + /* Search the other T_k(t) in GivenClause */ + tLits = list_Nil(); + tSort = sort_TopSort(); + for (j = lc; j > i; j--) { + TERM actAtom; + + actAtom = clause_GetLiteralAtom(GivenClause, j); + if (term_FirstArgument(actAtom) == var) { /* tClause is shared */ + tLits = list_Cons((POINTER)j, tLits); + tSort = sort_Intersect(sort_TheorySortOfSymbol(SortTheory, + term_TopSymbol(actAtom)), + tSort); + } + } + tLits = list_Cons((POINTER)i, tLits); + tSort = sort_Intersect(sort_TheorySortOfSymbol(SortTheory, + term_TopSymbol(tAtom)), + tSort); + list_PointerDeleteDuplicates(tSort); + + unifierSort = inf_GetSortFromLits(unifiers, SortTheory); + sojuList = sort_TheoryComputeAllSubsortHits(SortTheory, unifierSort, tSort); + + sort_Delete(unifierSort); + sort_Delete(tSort); + + result = + list_Nconc(inf_InternWeakening(GivenClause, tLits, unifiers, NULL, + sojuList, Flags, Precedence), + result); + + list_Delete(tLits); + list_Delete(unifiers); + } + } + } + } + return result; +} + +LIST inf_BackwardEmptySortPlusPlus(CLAUSE GivenClause, st_INDEX Index, + SORTTHEORY SortTheory, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause with solved sort constraint, an index of clauses, + a sort theory, a flag store and a precedence. + RETURNS: A list of clauses inferred from the GivenClause by + the Empty Sort rule. + MEMORY: Memory is allocated for the list and the clauses. +***************************************************************/ +{ + LIST result; + int i, ls; + +#ifdef CHECK + if (!clause_HasSolvedConstraint(GivenClause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_BackwardEmptySortPlusPlus: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + result = list_Nil(); + ls = clause_LastSuccedentLitIndex(GivenClause); + + for (i = clause_FirstSuccedentLitIndex(GivenClause); i <= ls; i++) { + LITERAL sLit; + TERM sAtom; + + sLit = clause_GetLiteral(GivenClause, i); + sAtom = clause_LiteralAtom(sLit); + if (clause_LiteralGetFlag(sLit,STRICTMAXIMAL) && + clause_LiteralIsSort(sLit) && + (!term_IsVariable(term_FirstArgument(sAtom)) || + clause_HasEmptyConstraint(GivenClause))) { + LIST unifiers, partners; + SORT unifierSort; + + unifiers = partners = list_Nil(); + inf_GetBackwardPartnerLits(sLit, Index, &partners, &unifiers, TRUE, Flags, + Precedence); + unifiers = list_Cons(sLit, unifiers); + /* <partners> holds monadic constraint literals */ + /* <unifiers> holds monadic, maximal succedent literals */ + + unifierSort = inf_GetSortFromLits(unifiers, SortTheory); + + for ( ; !list_Empty(partners); partners = list_Pop(partners)) { + LITERAL tLit; + CLAUSE tClause; + TERM tAtom; + int ti; + int li; + TERM var; + BOOL varOccursNoMore; + int j; + + tLit = list_Car(partners); + tClause = clause_LiteralOwningClause(tLit); + tAtom = clause_LiteralAtom(tLit); + ti = clause_LiteralGetIndex(tLit); + li = clause_LastSuccedentLitIndex(tClause); + var = term_FirstArgument(tAtom); + varOccursNoMore = TRUE; + for (j = clause_FirstAntecedentLitIndex(tClause); + j <= li && varOccursNoMore; + j++) { + if (term_ContainsSymbol(clause_GetLiteralAtom(tClause,j), + term_TopSymbol(var))) + varOccursNoMore = FALSE; + } + + if (varOccursNoMore) { + /* Condition implies that constraint is unsolved */ + int lc; + LIST tLits, sojuList; + SORT tSort; + + lc = clause_LastConstraintLitIndex(tClause); + + /* Search the other T_k(t) in GivenClause */ + tLits = list_Nil(); + tSort = sort_TopSort(); + for (j = lc; j >= clause_FirstLitIndex(); j--) { + TERM actAtom; + + actAtom = clause_GetLiteralAtom(tClause, j); + if (j != ti && + term_TopSymbol(term_FirstArgument(actAtom)) == term_TopSymbol(var)) { + tLits = list_Cons((POINTER)j, tLits); + tSort = sort_Intersect(sort_TheorySortOfSymbol(SortTheory, term_TopSymbol(actAtom)), + tSort); + } + } + tLits = list_Cons((POINTER)ti, tLits); + tSort = sort_Intersect(sort_TheorySortOfSymbol(SortTheory, term_TopSymbol(tAtom)), + tSort); + list_PointerDeleteDuplicates(tSort); + + sojuList = sort_TheoryComputeAllSubsortHits(SortTheory, unifierSort, tSort); + sort_Delete(tSort); + + cont_StartBinding(); + unify_UnifyNoOC(cont_LeftContext(), tAtom, + cont_RightContext(), sAtom); + + result = + list_Nconc(inf_InternWeakening(tClause, tLits, unifiers, sLit, + sojuList, Flags, Precedence), + result); + + cont_BackTrack(); + + list_Delete(tLits); + } + } + sort_Delete(unifierSort); + list_Delete(unifiers); + } + } + + return result; +} diff --git a/test/spass/rules-sort.h b/test/spass/rules-sort.h new file mode 100644 index 0000000000000000000000000000000000000000..6b83c94f1c4a91e7a67911e97f23879264957625 --- /dev/null +++ b/test/spass/rules-sort.h @@ -0,0 +1,79 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INFERENCE RULES FOR SORTS * */ +/* * * */ +/* * $Module: SORTRULES * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _SORTRULES_ +#define _SORTRULES_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "sort.h" +#include "unify.h" +#include "clause.h" +#include "flags.h" + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +LIST inf_ForwardSortResolution(CLAUSE, st_INDEX, SORTTHEORY, BOOL, FLAGSTORE, + PRECEDENCE); +LIST inf_BackwardSortResolution(CLAUSE, st_INDEX, SORTTHEORY, BOOL, FLAGSTORE, + PRECEDENCE); +LIST inf_ForwardEmptySort(CLAUSE, st_INDEX, SORTTHEORY, BOOL, FLAGSTORE, + PRECEDENCE); +LIST inf_BackwardEmptySort(CLAUSE, st_INDEX, SORTTHEORY, BOOL, FLAGSTORE, + PRECEDENCE); +LIST inf_ForwardWeakening(CLAUSE, st_INDEX, SORTTHEORY, FLAGSTORE, PRECEDENCE); +LIST inf_BackwardWeakening(CLAUSE, st_INDEX, SORTTHEORY, FLAGSTORE, PRECEDENCE); +LIST inf_ForwardEmptySortPlusPlus(CLAUSE, st_INDEX, SORTTHEORY, FLAGSTORE, + PRECEDENCE); +LIST inf_BackwardEmptySortPlusPlus(CLAUSE, st_INDEX, SORTTHEORY, FLAGSTORE, + PRECEDENCE); + +#endif diff --git a/test/spass/rules-split.c b/test/spass/rules-split.c new file mode 100644 index 0000000000000000000000000000000000000000..7ee420a9935febbbc3e13dd459aa48dc02bfc4cb --- /dev/null +++ b/test/spass/rules-split.c @@ -0,0 +1,460 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SPLITTING OF CLAUSES * */ +/* * * */ +/* * $Module: SPLIT * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 2000 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "rules-split.h" + +static LIST split_DeleteClausesDependingOnLevelFromList(PROOFSEARCH,LIST, int, LIST*); +static LIST split_DeleteInvalidClausesFromList(PROOFSEARCH, int, LIST); +static void split_DeleteInvalidClausesFromStack(PROOFSEARCH); +static LIST split_RemoveUnnecessarySplits(PROOFSEARCH, CLAUSE); + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + + +LIST split_Backtrack(PROOFSEARCH PS, CLAUSE EmptyClause, CLAUSE* SplitClause) +/************************************************************** + INPUT: A proofsearch object, an empty clause and a pointer to a clause + used as return value. + RETURNS: A list of clauses deleted in the backtracked split levels. + <*SplitClause> is set to the split clause for the right branch + of the splitting step, or NULL, if the tableau is finished. + EFFECT: Backtracks the top of the split stack wrt the empty clause's level +***************************************************************/ +{ + SPLIT ActBacktrackSplit; + LIST RecoverList, Scan; + int Backtracklevel; + + ActBacktrackSplit = (SPLIT)NULL; + RecoverList = split_RemoveUnnecessarySplits(PS, EmptyClause); + Backtracklevel = clause_SplitLevel(EmptyClause); + *SplitClause = NULL; + + /* Backtrack all split levels bigger than the level of the empty clause */ + while (!prfs_SplitStackEmpty(PS) && (prfs_ValidLevel(PS) > Backtracklevel)) { + ActBacktrackSplit = prfs_SplitStackTop(PS); + prfs_SplitStackPop(PS); + if (prfs_SplitFatherClause(ActBacktrackSplit) != (CLAUSE)NULL) { + RecoverList = list_Cons(prfs_SplitFatherClause(ActBacktrackSplit), + RecoverList); + prfs_SplitSetFatherClause(ActBacktrackSplit, NULL); + } + RecoverList = list_Nconc(prfs_SplitDeletedClauses(ActBacktrackSplit), + RecoverList); + clause_DeleteClauseList(prfs_SplitBlockedClauses(ActBacktrackSplit)); + prfs_SplitFree(ActBacktrackSplit); + prfs_DecValidLevel(PS); + } + + /* Backtrack further for all right branches on top of the stack */ + while (!prfs_SplitStackEmpty(PS) && + list_Empty(prfs_SplitBlockedClauses(prfs_SplitStackTop(PS)))) { + ActBacktrackSplit = prfs_SplitStackTop(PS); + prfs_SplitStackPop(PS); + if (prfs_SplitFatherClause(ActBacktrackSplit) != (CLAUSE)NULL) + RecoverList = list_Cons(prfs_SplitFatherClause(ActBacktrackSplit), + RecoverList); + RecoverList = list_Nconc(prfs_SplitDeletedClauses(ActBacktrackSplit), + RecoverList); + prfs_SplitFree(ActBacktrackSplit); + prfs_DecValidLevel(PS); + } + + if (!prfs_SplitStackEmpty(PS)) { + /* Enter the right branch of the splitting step */ + int SplitMinus1; + LIST RightClauses; + + SplitMinus1 = prfs_ValidLevel(PS) - 1; + ActBacktrackSplit = prfs_SplitStackTop(PS); + + RecoverList = list_Nconc(prfs_SplitDeletedClauses(ActBacktrackSplit), + RecoverList); + prfs_SplitSetDeletedClauses(ActBacktrackSplit, list_Nil()); + RecoverList = split_DeleteInvalidClausesFromList(PS, SplitMinus1, + RecoverList); + + RightClauses = prfs_SplitBlockedClauses(ActBacktrackSplit); + prfs_SplitSetBlockedClauses(ActBacktrackSplit, list_Nil()); + for (Scan = RightClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (clause_Number(list_Car(Scan)) == 0) { + /* Found the right clause, the negation clauses have number -1. */ +#ifdef CHECK + if (*SplitClause != NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In split_Backtrack:"); + misc_ErrorReport(" Found two blocked clauses "); + misc_ErrorReport("\n with clause number 0 (this marks the clause "); + misc_ErrorReport("\n for the right branch of the tableau)."); + misc_FinishErrorReport(); + } +#endif + *SplitClause = list_Car(Scan); + } + + clause_NewNumber((CLAUSE) list_Car(Scan)); + clause_AddParentClause((CLAUSE) list_Car(Scan), clause_Number(EmptyClause)); + clause_AddParentLiteral((CLAUSE) list_Car(Scan), 0); /* dummy literal */ + } + +#ifdef CHECK + if (*SplitClause == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In split_Backtrack: Didn´t find a blocked clause"); + misc_ErrorReport("\n with clause number 0. (this marks the clause "); + misc_ErrorReport("\n for the right branch of the tableau)."); + misc_FinishErrorReport(); + } +#endif + + RecoverList = list_Nconc(RightClauses, RecoverList); + + /* Then, delete clauses from current level (Hack) */ + prfs_DecValidLevel(PS); + prfs_MoveInvalidClausesDocProof(PS); + split_DeleteInvalidClausesFromStack(PS); + prfs_IncValidLevel(PS); + } else { + /* Don't delete clauses from current level (split is top level) */ + prfs_MoveInvalidClausesDocProof(PS); + for (Scan = RecoverList; !list_Empty(Scan); Scan = list_Cdr(Scan)) + prfs_InsertDocProofClause(PS, list_Car(Scan)); + list_Delete(RecoverList); + RecoverList = list_Nil(); + } + prfs_SetLastBacktrackLevel(PS, prfs_ValidLevel(PS)); + + return RecoverList; +} + + +static LIST split_DeleteClausesDependingOnLevelFromList(PROOFSEARCH Search, + LIST ClauseList, + int Level, LIST* New) +/************************************************************** + INPUT: A proof search object, a list of unshared clauses + and a split level. + EFFECT: Deletes all clauses depending on split level from + <ClauseList>. + All split stored deleted clauses from the level of + the deleted clauses from <ClauseList> are stored in + <*New>. + RETURNS: The updated list and the recover clauses in <*New>. +***************************************************************/ +{ + LIST Scan; + CLAUSE Clause; + SPLIT Reinsert; + + for (Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Clause = list_Car(Scan); + if (clause_DependsOnSplitLevel(Clause, Level)) { + Reinsert = prfs_GetSplitOfLevel(clause_SplitLevel(Clause), Search); + if (prfs_SplitDeletedClauses(Reinsert) != list_Nil()) { + *New = list_Nconc(prfs_SplitDeletedClauses(Reinsert), *New); + prfs_SplitSetDeletedClauses(Reinsert, list_Nil()); + } + prfs_InsertDocProofClause(Search,Clause); + list_Rplaca(Scan, NULL); + } + } + return list_PointerDeleteElement(ClauseList, NULL); +} + + +static LIST split_DeleteClausesDependingOnLevelFromSet(PROOFSEARCH PS, + LIST ClauseList, + int SplitLevel) +/************************************************************** + INPUT: A PROOFSEARCH object, a list of shared clauses + and a split level. + RETURNS: A list of clauses that have to be recovered possibly. + EFFECT: Clauses from the clause list depending on <SplitLevel> + are moved to the doc proof index of <PS>. + All formerly redundant clauses that were reduced by a clause + of the same split level as a clause from the list depending + on <SplitLevel> are returned. +***************************************************************/ +{ + LIST scan, delList, recover; + CLAUSE clause; + SPLIT reinsert; + + delList = recover = list_Nil(); + + for (scan = ClauseList; !list_Empty(scan); scan = list_Cdr(scan)){ + clause = list_Car(scan); + if (clause_DependsOnSplitLevel(clause, SplitLevel)) { + reinsert = prfs_GetSplitOfLevel(clause_SplitLevel(clause), PS); + recover = list_Nconc(prfs_SplitDeletedClauses(reinsert), recover); + prfs_SplitSetDeletedClauses(reinsert, list_Nil()); + delList = list_Cons(clause, delList); + } + } + + /* WARNING: The following move operations change the worked off */ + /* and usable sets of the proof search object destructively. */ + /* So it's impossible to move those function calls into the */ + /* loop above. */ + for ( ; !list_Empty(delList); delList = list_Pop(delList)) { + clause = list_Car(delList); + if (clause_GetFlag(clause, WORKEDOFF)) + prfs_MoveWorkedOffDocProof(PS, clause); + else + prfs_MoveUsableDocProof(PS, clause); + } + return recover; +} + + + +static LIST split_DeleteInvalidClausesFromList(PROOFSEARCH Search, int Level, + LIST ClauseList) +/************************************************************** + INPUT: A proof search object, a split level and a list of clauses. + RETURNS: The list where invalid clauses wrt 'Level' are deleted. + EFFECT: The invalid clauses are stored in the doc proof index + of the proof search object if necessary. +***************************************************************/ +{ + LIST Scan; + CLAUSE Clause; + + /*printf("\nDiese Liste soll von ungueltigen (Level > %d) " + "befreit werden: \n",Level);fflush(stdout); + clause_ListPrint(ClauseList);*/ + + for (Scan = ClauseList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + Clause = list_Car(Scan); + if (!prfs_IsClauseValid(Clause,Level)) { + prfs_InsertDocProofClause(Search,Clause); + list_Rplaca(Scan, NULL); + } + } + return list_PointerDeleteElement(ClauseList, NULL); +} + +static void split_DeleteInvalidClausesFromStack(PROOFSEARCH Search) +/************************************************************** + INPUT: A proof search object. + EFFECT: All clauses in the split stack of <Search> that have a higher + split level than the current <Search> split level are deleted. +***************************************************************/ +{ + LIST Scan1,Scan2,ClauseList; + int Level; + CLAUSE Clause; + + Level = prfs_ValidLevel(Search); + + for (Scan1=prfs_SplitStack(Search);!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { + ClauseList = prfs_SplitDeletedClauses(list_Car(Scan1)); + for (Scan2 = ClauseList; !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) { + Clause = (CLAUSE)list_Car(Scan2); + if (!prfs_IsClauseValid(Clause,Level)) { + prfs_InsertDocProofClause(Search,Clause); + list_Rplaca(Scan2, NULL); + } + } + prfs_SplitSetDeletedClauses(list_Car(Scan1),list_PointerDeleteElement(ClauseList, NULL)); + } +} + + +static LIST split_RemoveUnnecessarySplits(PROOFSEARCH PS, CLAUSE EmptyClause) +/************************************************************** + INPUT: An empty clause and a proof search object + EFFECT: Removes all splits up to the last backtrack level + that were not necessary to derive the empty clause. + RETURNS: A list of recovered clauses. +***************************************************************/ +{ + LIST Scan; + LIST Recover, New; + LIST Deleted; + LIST ScanStack; + + int SplitLevel; + int LastBacktrackLevel; + SPLIT Split,ScanSplit; + + Scan = prfs_SplitStack(PS); + SplitLevel = prfs_ValidLevel(PS); + LastBacktrackLevel = prfs_LastBacktrackLevel(PS); + Recover = list_Nil(); + + while (SplitLevel > LastBacktrackLevel) { + if (prfs_SplitIsUnused(list_Car(Scan)) && + !clause_DependsOnSplitLevel(EmptyClause, SplitLevel)) { + New = list_Nil(); + Split = list_Car(Scan); + + /*printf("\n\t Removed: %d",prfs_SplitSplitLevel(Split));*/ + + clause_DeleteClauseList(prfs_SplitBlockedClauses(Split)); + prfs_SplitSetBlockedClauses(Split, list_Nil()); + + Recover = list_Nconc(prfs_SplitDeletedClauses(Split), Recover); + prfs_SplitSetDeletedClauses(Split, list_Nil()); + + if (prfs_SplitFatherClause(Split) != (CLAUSE)NULL) { + Recover = list_Cons(prfs_SplitFatherClause(Split),Recover); + prfs_SplitSetFatherClause(Split,NULL); + } + Recover = split_DeleteClausesDependingOnLevelFromList(PS, Recover, SplitLevel, &New); + + ScanStack = prfs_SplitStack(PS); + while (!list_StackEmpty(ScanStack) && + prfs_SplitSplitLevel((ScanSplit = (SPLIT)list_Car(ScanStack))) > LastBacktrackLevel) { + Deleted = prfs_SplitDeletedClauses(ScanSplit); + prfs_SplitSetDeletedClauses(ScanSplit, list_Nil()); /* IMPORTANT!, see next line */ + Deleted = split_DeleteClausesDependingOnLevelFromList(PS, Deleted, SplitLevel, &New); + prfs_SplitSetDeletedClauses(ScanSplit, Deleted); + ScanStack = list_Cdr(ScanStack); + } + + while (!list_Empty(New)) { + Deleted = list_Nil(); + Recover = list_Nconc(split_DeleteClausesDependingOnLevelFromList(PS, New, SplitLevel, &Deleted), + Recover); + New = Deleted; + } + Recover = list_Nconc(Recover, + split_DeleteClausesDependingOnLevelFromSet(PS, prfs_UsableClauses(PS), SplitLevel)); + Recover = list_Nconc(Recover, + split_DeleteClausesDependingOnLevelFromSet(PS, prfs_WorkedOffClauses(PS), SplitLevel)); + + prfs_SplitSetUsed(Split); + } + + SplitLevel--; + Scan = list_Cdr(Scan); + } + return Recover; +} + + +void split_DeleteClauseAtLevel(PROOFSEARCH PS, CLAUSE Clause, int Level) +/************************************************************** + INPUT: A clause, a level and a proofsearch object + RETURNS: Nothing. + EFFECT: <Clause> is deleted from the usable or worked off set + and made unshared. +***************************************************************/ +{ + if (clause_GetFlag(Clause,WORKEDOFF)) + prfs_ExtractWorkedOff(PS, Clause); + else + prfs_ExtractUsable(PS, Clause); + + split_KeepClauseAtLevel(PS, Clause, Level); +} + + +void split_KeepClauseAtLevel(PROOFSEARCH PS, CLAUSE Clause, int Level) +/************************************************************** + INPUT: A clause and a level as int. + RETURNS: None. + MEMORY: A copy of clause is made and kept within the split stack. +***************************************************************/ +{ + SPLIT Split; + + Split = prfs_GetSplitOfLevel(Level, PS); + prfs_SplitSetDeletedClauses(Split,list_Cons(Clause, prfs_SplitDeletedClauses(Split))); +} + + +LIST split_ExtractEmptyClauses(LIST Clauses, LIST* EmptyClauses) +/************************************************************** + INPUT: A list of clauses and a pointer to a list of empty clauses. + RETURNS: <Clauses> without all empty clauses where the empty clauses + are moved to <EmptyClauses> + MEMORY: Destructive on <Clauses>. +***************************************************************/ +{ + LIST Scan; + CLAUSE Clause; + + for (Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Clause = (CLAUSE)list_Car(Scan); + if (clause_IsEmptyClause(Clause)) { + *EmptyClauses = list_Cons(Clause,*EmptyClauses); + list_Rplaca(Scan,NULL); + } + } + Clauses = list_PointerDeleteElement(Clauses,NULL); + + return Clauses; +} + +CLAUSE split_SmallestSplitLevelClause(LIST Clauses) +/************************************************************** + INPUT: A non-empty list of clauses. + RETURNS: The clause with the smallest split level. +***************************************************************/ +{ + CLAUSE Result; + + Result = (CLAUSE)list_Car(Clauses); + Clauses = list_Cdr(Clauses); + + while (!list_Empty(Clauses)) { + if (clause_SplitLevel(Result) > clause_SplitLevel(list_Car(Clauses))) + Result = list_Car(Clauses); + Clauses = list_Cdr(Clauses); + } + + return Result; +} diff --git a/test/spass/rules-split.h b/test/spass/rules-split.h new file mode 100644 index 0000000000000000000000000000000000000000..3423fa3d1d48c60ab43cc2e7e07b4b225c98698d --- /dev/null +++ b/test/spass/rules-split.h @@ -0,0 +1,70 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SPLITTING OF CLAUSES * */ +/* * * */ +/* * $Module: SPLIT * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 2000 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _RULES_SPLIT_ +#define _RULES_SPLIT_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "clause.h" +#include "search.h" + + +/**************************************************************/ +/* Function Prototypes */ +/**************************************************************/ + +LIST split_Backtrack(PROOFSEARCH, CLAUSE, CLAUSE*); +void split_KeepClauseAtLevel(PROOFSEARCH, CLAUSE, int); +void split_DeleteClauseAtLevel(PROOFSEARCH, CLAUSE, int); +LIST split_ExtractEmptyClauses(LIST, LIST*); +CLAUSE split_SmallestSplitLevelClause(LIST); + + +#endif diff --git a/test/spass/rules-ur.c b/test/spass/rules-ur.c new file mode 100644 index 0000000000000000000000000000000000000000..bd076517827b3e425f1ae829a99a0df9fd470d61 --- /dev/null +++ b/test/spass/rules-ur.c @@ -0,0 +1,385 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * UR-RESOLUTION * */ +/* * * */ +/* * $Module: INFERENCE RULES * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/* $RCSfile$ */ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "rules-ur.h" +#include "list.h" + + +static LIST inf_GetURPartnerLits(TERM Atom, LITERAL Lit, + BOOL Unit, SHARED_INDEX Index) +/************************************************************** + INPUT: An atom, a literal, a boolean flag and a SHARED_INDEX. + RETURNS: A list of literals with sign complementary to <Lit> + that are unifiable with <Atom>. If <Unit> is true, + only literals from unit clauses are returned, if <Unit> + is false, only literals from non-unit clauses are + returned. + EFFECT: <Atom> is a copy of <Lit>'s atom where some substitution + was applied and equality literals might have been swapped. + <Lit> is just needed to check whether the unifiable + literals are complementary. +***************************************************************/ +{ + LIST Result, Unifiers, LitScan; + LITERAL PLit; + int length; + + Result = list_Nil(); + Unifiers = st_GetUnifier(cont_LeftContext(), sharing_Index(Index), + cont_RightContext(), Atom); + for ( ; !list_Empty(Unifiers); Unifiers = list_Pop(Unifiers)) { + if (!term_IsVariable(list_Car(Unifiers))) { + for (LitScan = sharing_NAtomDataList(list_Car(Unifiers)); + !list_Empty(LitScan); LitScan = list_Cdr(LitScan)) { + PLit = list_Car(LitScan); + length = clause_Length(clause_LiteralOwningClause(PLit)); + if (clause_LiteralsAreComplementary(Lit, PLit) && + ((Unit && length==1) || (!Unit && length!=1))) + /* The partner literals must have complementary sign and + if <Unit> == TRUE they must be from unit clauses, + if <Unit> == FALSE they must be from non-unit clauses. */ + Result = list_Cons(PLit, Result); + } + } + } + return Result; +} + + +static CLAUSE inf_CreateURUnitResolvent(CLAUSE Clause, int i, SUBST Subst, + LIST FoundMap, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A non-unit clause, a literal index from the clause, + a substitution, a list of pairs (l1, l2) of literals, + where l1 is from the non-unit clause and l2 is from a + unit clause, a flag store and a precedence. + RETURNS: The resolvent of this UR resolution inference. The + clause consists of the literal at index <i> in <Clause> + after application of <Subst>. + EFFECT: The flag store and the precedence are needed to create + the new clause. +***************************************************************/ +{ + CLAUSE Result, PClause; + LITERAL Lit; + TERM Atom; + LIST Parents; + NAT depth; + + /* Create atom for resolvent */ + Atom = subst_Apply(Subst, term_Copy(clause_GetLiteralAtom(Clause, i))); + /* Create clause */ + Parents = list_List(Atom); + if (i <= clause_LastConstraintLitIndex(Clause)) + Result = clause_Create(Parents, list_Nil(), list_Nil(), Flags, Precedence); + else if (i <= clause_LastAntecedentLitIndex(Clause)) + Result = clause_Create(list_Nil(), Parents, list_Nil(), Flags, Precedence); + else + Result = clause_Create(list_Nil(), list_Nil(), Parents, Flags, Precedence); + list_Delete(Parents); + + /* Get parent clauses and literals, calculate depth of resolvent */ + Parents = list_List(Clause); + depth = clause_Depth(Clause); + for ( ; !list_Empty(FoundMap); FoundMap = list_Cdr(FoundMap)) { + Lit = list_PairSecond(list_Car(FoundMap)); /* Literal from unit */ + PClause = clause_LiteralOwningClause(Lit); + Parents = list_Cons(PClause, Parents); + depth = misc_Max(depth, clause_Depth(PClause)); + clause_AddParentClause(Result, clause_Number(PClause)); + clause_AddParentLiteral(Result, clause_LiteralGetIndex(Lit)); + + Lit = list_PairFirst(list_Car(FoundMap)); /* Is from <Clause> */ + clause_AddParentClause(Result, clause_Number(Clause)); + clause_AddParentLiteral(Result, clause_LiteralGetIndex(Lit)); + } + clause_SetFromURResolution(Result); + clause_SetDepth(Result, depth+1); + clause_SetSplitDataFromList(Result, Parents); + list_Delete(Parents); + + return Result; +} + + +static LIST inf_SearchURResolvents(CLAUSE Clause, int i, LIST FoundMap, + LIST RestLits, SUBST Subst, + SYMBOL GlobalMaxVar, SHARED_INDEX Index, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A non-unit clause, a literal index from <Clause>. + <FoundMap> is a list of pairs (l1,l2) of unifiable literals, + where l1 is from <Clause> and l2 is from a unit clause. + <RestLits> is a list of literals from <Clause> where + we haven't found unifiable literals from unit clauses + so far. + <Subst> is the overall substitution for <Clause> + (not for the unit-clauses!). + <GlobalMaxVar> is the maximal variable encountered so far. + <Index> is used to search unifiable literals. + The flag store and the precedence are needed to create + the new clauses. + RETURNS: A list of UR resolution resolvents. +***************************************************************/ +{ + if (list_Empty(RestLits)) { + /* Stop the recursion */ + return list_List(inf_CreateURUnitResolvent(Clause, i, Subst, FoundMap, + Flags, Precedence)); + } else { + LITERAL Lit, PLit; + SYMBOL NewMaxVar; + SUBST NewSubst, RightSubst; + TERM AtomCopy, PAtom; + LIST Result, Partners; + BOOL Swapped; + + Result = list_Nil(); + Swapped = FALSE; + /* Choose the unmatched literal with the most symbols */ + RestLits = clause_MoveBestLiteralToFront(list_Copy(RestLits), Subst, + GlobalMaxVar, + clause_HyperLiteralIsBetter); + Lit = list_Car(RestLits); + RestLits = list_Pop(RestLits); + AtomCopy = subst_Apply(Subst, term_Copy(clause_LiteralAtom(Lit))); + + /* The following 'endless' loop runs twice for equality literals */ + /* and only once for other literals. */ + while (TRUE) { + Partners = inf_GetURPartnerLits(AtomCopy, Lit, TRUE, Index); + for ( ; !list_Empty(Partners); Partners = list_Pop(Partners)) { + PLit = list_Car(Partners); + + /* Rename the atom */ + PAtom = term_Copy(clause_LiteralAtom(PLit)); + term_StartMaxRenaming(GlobalMaxVar); + term_Rename(PAtom); + /* Get the new global maximal variable */ + NewMaxVar = term_MaxVar(PAtom); + if (symbol_GreaterVariable(GlobalMaxVar, NewMaxVar)) + NewMaxVar = GlobalMaxVar; + + /* Get the substitution */ + cont_Check(); + if (!unify_UnifyNoOC(cont_LeftContext(), AtomCopy, + cont_RightContext(), PAtom)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In inf_SearchURResolvents: Unification failed."); + misc_FinishErrorReport(); + } + subst_ExtractUnifier(cont_LeftContext(), &NewSubst, + cont_RightContext(), &RightSubst); + cont_Reset(); + subst_Delete(RightSubst); /* Forget substitution for unit clause */ + term_Delete(PAtom); /* Was just needed to get the substitution */ + + /* Build the composition of the substitutions */ + RightSubst = NewSubst; + NewSubst = subst_Compose(NewSubst, subst_Copy(Subst)); + subst_Delete(RightSubst); + + FoundMap = list_Cons(list_PairCreate(Lit, PLit), FoundMap); + + Result = list_Nconc(inf_SearchURResolvents(Clause,i,FoundMap,RestLits, + NewSubst,NewMaxVar,Index, + Flags, Precedence), + Result); + + list_PairFree(list_Car(FoundMap)); + FoundMap = list_Pop(FoundMap); + subst_Delete(NewSubst); + } + /* loop control */ + if (!fol_IsEquality(AtomCopy) || Swapped) + break; + else { + term_EqualitySwap(AtomCopy); + Swapped = TRUE; + } + } + /* cleanup */ + term_Delete(AtomCopy); + list_Delete(RestLits); + + return Result; + } +} + + +static LIST inf_NonUnitURResolution(CLAUSE Clause, int SpecialLitIndex, + LIST FoundMap, SUBST Subst, + SYMBOL GlobalMaxVar, SHARED_INDEX Index, + FLAGSTORE Flags, PRECEDENCE Precedence) +/************************************************************** + INPUT: A non-unit clause, a literal index from <Clause>. + <FoundMap> is a list of pairs (l1,l2) of unifiable literals, + where l1 is from <Clause> and l2 is from a unit clause. + At this point the list has at most one element. + <Subst> is the substitution for <Clause>. + <GlobalMaxVar> is the maximal variable encountered so far. + <Index> is used to search unifiable literals. + The flag store and the precedence are needed to create + the new clauses. + RETURNS: The list of UR resolution resolvents. + EFFECT: If inf_URResolution was called with a unit clause, + <SpecialLitIndex> is the index of a literal from a non-unit + clause, that is unifiable with the unit clause's literal, + otherwise it is set to -1. +***************************************************************/ +{ + LIST Result, RestLits; + int i, last; + + Result = list_Nil(); + RestLits = clause_GetLiteralListExcept(Clause, SpecialLitIndex); + last = clause_LastLitIndex(Clause); + for (i = clause_FirstLitIndex(); i <= last; i++) { + /* <i> is the index of the literal that remains in the resolvent */ + if (i != SpecialLitIndex) { + RestLits = list_PointerDeleteOneElement(RestLits, + clause_GetLiteral(Clause,i)); + + Result = list_Nconc(inf_SearchURResolvents(Clause, i, FoundMap, RestLits, + Subst, GlobalMaxVar, Index, + Flags, Precedence), + Result); + + RestLits = list_Cons(clause_GetLiteral(Clause, i), RestLits); + } + } + list_Delete(RestLits); + return Result; +} + + +LIST inf_URResolution(CLAUSE Clause, SHARED_INDEX Index, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, a shared index, a flag store and a precedence. + RETURNS: The list of UR resolution resolvents. + EFFECT: The flag store and the precedence are needed to create + the resolvents. +***************************************************************/ +{ + LIST Result; + + if (clause_Length(Clause) != 1) { + /* Clause isn't unit clause */ + Result = inf_NonUnitURResolution(Clause, -1, list_Nil(), subst_Nil(), + clause_MaxVar(Clause), Index, Flags, + Precedence); + } + else { + /* Clause is unit clause, so search partner literals in non-unit clauses */ + LITERAL Lit, PLit; + TERM Atom; + LIST Partners, FoundMap; + SYMBOL MaxVar, PMaxVar; + SUBST LeftSubst, RightSubst; + CLAUSE PClause; + int PLitInd; + BOOL Swapped; + + Result = list_Nil(); + Lit = clause_GetLiteral(Clause, clause_FirstLitIndex()); + Atom = term_Copy(clause_LiteralAtom(Lit)); + Swapped = FALSE; + + /* The following 'endless' loop runs twice for equality literals */ + /* and only once for other literals. */ + while (TRUE) { + /* Get complementary literals from non-unit clauses */ + Partners = inf_GetURPartnerLits(Atom, Lit, FALSE, Index); + + for ( ; !list_Empty(Partners); Partners = list_Pop(Partners)) { + PLit = list_Car(Partners); + PLitInd = clause_LiteralGetIndex(PLit); + PClause = clause_LiteralOwningClause(PLit); /* non-unit clause */ + + PMaxVar = clause_MaxVar(PClause); + term_StartMaxRenaming(PMaxVar); + term_Rename(Atom); /* Rename atom from unit clause */ + MaxVar = term_MaxVar(Atom); + if (symbol_GreaterVariable(PMaxVar, MaxVar)) + MaxVar = PMaxVar; + + /* Get the substitution */ + cont_Check(); + unify_UnifyNoOC(cont_LeftContext(), clause_LiteralAtom(PLit), + cont_RightContext(), Atom); + subst_ExtractUnifier(cont_LeftContext(), &LeftSubst, + cont_RightContext(), &RightSubst); + cont_Reset(); + /* We don't need the substitution for the unit clause */ + subst_Delete(RightSubst); + + FoundMap = list_List(list_PairCreate(PLit, Lit)); + + Result = list_Nconc(inf_NonUnitURResolution(PClause, PLitInd, FoundMap, + LeftSubst, MaxVar, Index, + Flags, Precedence), + Result); + + list_DeletePairList(FoundMap); + subst_Delete(LeftSubst); + } + /* loop control */ + if (!fol_IsEquality(Atom) || Swapped) + break; + else { + term_EqualitySwap(Atom); + Swapped = TRUE; + } + } /* end of endless loop */ + term_Delete(Atom); + } + return Result; +} diff --git a/test/spass/rules-ur.h b/test/spass/rules-ur.h new file mode 100644 index 0000000000000000000000000000000000000000..3bdc4272f07d36ec56365784b5944551f38945b6 --- /dev/null +++ b/test/spass/rules-ur.h @@ -0,0 +1,55 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * UR-RESOLUTION * */ +/* * * */ +/* * $Module: INFERENCE RULES * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/* $RCSfile$ */ + +#ifndef _UR_RESOLUTION_ +#define _UR_RESOLUTION_ + +#include "clause.h" +#include "sharing.h" +#include "flags.h" + +LIST inf_URResolution(CLAUSE, SHARED_INDEX, FLAGSTORE, PRECEDENCE); + +#endif diff --git a/test/spass/search.c b/test/spass/search.c new file mode 100644 index 0000000000000000000000000000000000000000..5833ada5abd1d22843e5c28eb07a9bc34e6aa178 --- /dev/null +++ b/test/spass/search.c @@ -0,0 +1,1271 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * REPRESENTATION OF PROOF SEARCH * */ +/* * * */ +/* * $Module: PROOF SEARCH * */ +/* * * */ +/* * Copyright (C) 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + + +#include "search.h" +#include "defs.h" + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +static SPLIT prfs_SplitCreate(PROOFSEARCH PS) +/************************************************************** + INPUT: A proofsearch object + RETURNS: A new split object, which is initialized. + MEMORY: Allocates memory for the SPLIT_NODE. + EFFECT: Increases the split level of the proof search object. +***************************************************************/ +{ + SPLIT Result; + + prfs_IncValidLevel(PS); + + Result = (SPLIT)memory_Malloc(sizeof(SPLIT_NODE)); + Result->splitlevel = prfs_ValidLevel(PS); + Result->used = FALSE; + Result->blockedClauses = list_Nil(); + Result->deletedClauses = list_Nil(); + Result->father = (CLAUSE) NULL; + return Result; +} + + +static void prfs_SplitDelete(SPLIT S) +/************************************************************** + INPUT: A split + RETURNS: Nothing. + MEMORY: Deletes blocked and deleted clauses. Frees the split. +***************************************************************/ +{ + clause_DeleteClauseList(S->blockedClauses); + clause_DeleteClauseList(S->deletedClauses); + if (S->father != (CLAUSE)NULL) + clause_Delete(S->father); + prfs_SplitFree(S); +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * DEBUGGING FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +BOOL prfs_Check(PROOFSEARCH Search) +/************************************************************** + INPUT: A proof search object. + EFFECT: None. + RETURNS: TRUE if all invariants about <Search> are valid. +***************************************************************/ +{ + LIST Scan,Clauses; + SPLIT Split; + CLAUSE Clause; + + for (Scan=prfs_UsableClauses(Search);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Clause = (CLAUSE)list_Car(Scan); + if (!clause_IsClause(Clause, prfs_Store(Search), prfs_Precedence(Search)) || + clause_GetFlag(Clause, WORKEDOFF) || + !prfs_IsClauseValid(Clause, prfs_ValidLevel(Search))) + return FALSE; + } + + for (Scan=prfs_WorkedOffClauses(Search);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Clause = (CLAUSE)list_Car(Scan); + if (!clause_IsClause(Clause, prfs_Store(Search), prfs_Precedence(Search)) || + !clause_GetFlag(Clause,WORKEDOFF) || + !prfs_IsClauseValid(Clause, prfs_ValidLevel(Search))) + return FALSE; + } + + for (Scan=prfs_SplitStack(Search); !list_Empty(Scan); Scan=list_Cdr(Scan)) { + Split = (SPLIT)list_Car(Scan); + if (prfs_SplitIsUsed(Split)) { + if (!list_Empty(prfs_SplitBlockedClauses(Split)) || + !list_Empty(prfs_SplitDeletedClauses(Split))) { + /*putchar('\n');prfs_PrintSplit(Split); putchar('\n');*/ + return FALSE; + } else { + for (Clauses=prfs_UsableClauses(Search);!list_Empty(Clauses);Clauses=list_Cdr(Clauses)) + if (clause_SplitLevel(list_Car(Clauses)) == prfs_SplitSplitLevel(Split)) { + /*puts("\n");prfs_PrintSplit(Split); + fputs("\n Clause must not exist: ",stdout); + clause_Print(list_Car(Clauses)); putchar('\n');*/ + return FALSE; + } + for (Clauses=prfs_WorkedOffClauses(Search);!list_Empty(Clauses);Clauses=list_Cdr(Clauses)) + if (clause_SplitLevel(list_Car(Clauses)) == prfs_SplitSplitLevel(Split)) { + /*puts("\n");prfs_PrintSplit(Split); + fputs("\n Clause must not exist: ",stdout); + clause_Print(list_Car(Clauses)); putchar('\n');*/ + return FALSE; + } + } + } + } + + if (prfs_ValidLevel(Search) == 0) { + if (!prfs_SplitStackEmpty(Search)) + return FALSE; + } else { + if (prfs_ValidLevel(Search) != prfs_SplitSplitLevel(prfs_SplitStackTop(Search))) + return FALSE; + } + + if (prfs_ValidLevel(Search) < prfs_LastBacktrackLevel(Search)) + return FALSE; + + return TRUE; +} + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * HIGH LEVEL FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +static void prfs_InsertInSortTheories(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + EFFECT: If the clause is a declaration clause it is inserted + into the dynamic and approximated dynamic sort theory. + RETURNS: Nothing. +***************************************************************/ +{ + if ((prfs_DynamicSortTheory(Search) != (SORTTHEORY)NULL || + prfs_ApproximatedDynamicSortTheory(Search) != (SORTTHEORY)NULL) && + clause_IsDeclarationClause(Clause)) { + int i,l; + LITERAL lit; + CLAUSE copy; + LIST approx; + l = clause_Length(Clause); + for (i = clause_FirstSuccedentLitIndex(Clause); i < l; i++) { + lit = clause_GetLiteral(Clause,i); + if (clause_LiteralIsMaximal(lit) && + symbol_IsBaseSort(term_TopSymbol(clause_LiteralSignedAtom(lit)))) { + if (prfs_DynamicSortTheory(Search) != (SORTTHEORY)NULL) { + copy = clause_Copy(Clause); + list_Delete(clause_ParentClauses(copy)); + clause_SetParentClauses(copy,list_Nil()); + list_Delete(clause_ParentLiterals(copy)); + clause_SetParentLiterals(copy,list_Nil()); + clause_SetNumber(copy,clause_Number(Clause)); + sort_TheoryInsertClause(prfs_DynamicSortTheory(Search),Clause, + copy,clause_GetLiteral(copy,i)); + } + if (prfs_ApproximatedDynamicSortTheory(Search) != (SORTTHEORY)NULL) { + approx = sort_ApproxMaxDeclClauses(Clause, prfs_Store(Search), + prfs_Precedence(Search)); + for ( ; !list_Empty(approx); approx = list_Pop(approx)) { + copy = (CLAUSE)list_Car(approx); + sort_TheoryInsertClause(prfs_ApproximatedDynamicSortTheory(Search), + Clause, copy, + clause_GetLiteral(copy,clause_FirstSuccedentLitIndex(copy))); + } + } + } + } + } +} + + +static void prfs_DeleteFromSortTheories(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + EFFECT: If the clause is a declaration clause it is deleted + from the dynamic and approximated dynamic sort theory. +***************************************************************/ +{ + if (clause_IsDeclarationClause(Clause)) { + if (prfs_DynamicSortTheory(Search) != (SORTTHEORY)NULL) + sort_TheoryDeleteClause(prfs_DynamicSortTheory(Search), Clause); + if (prfs_ApproximatedDynamicSortTheory(Search) != (SORTTHEORY)NULL) + sort_TheoryDeleteClause(prfs_ApproximatedDynamicSortTheory(Search), Clause); + } +} + + +void prfs_DeleteDocProof(PROOFSEARCH Search) +/************************************************************** + INPUT: A proof search object. + RETURNS: Nothing. + EFFECT: The docproof structures are deleted. +***************************************************************/ +{ + clause_DeleteSharedClauseList(prfs_DocProofClauses(Search), + prfs_DocProofSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); + if (prfs_DocProofSharingIndex(Search)) + sharing_IndexDelete(prfs_DocProofSharingIndex(Search)); + Search->dpindex = NULL; + Search->dplist = list_Nil(); +} + + +static void prfs_InternalDelete(PROOFSEARCH Search) +/************************************************************** + INPUT: A proof search object. + RETURNS: Nothing. + EFFECT: Most of the proofsearch object is deleted. + This function implements the common subset of + functionality of prfs_Clean and prfs_Delete. +***************************************************************/ +{ + LIST Scan; + + clause_DeleteClauseList(prfs_EmptyClauses(Search)); + list_DeleteWithElement(prfs_Definitions(Search), + (void (*)(POINTER)) def_Delete); + list_Delete(prfs_UsedEmptyClauses(Search)); + sort_TheoryDelete(prfs_StaticSortTheory(Search)); + sort_TheoryDelete(prfs_DynamicSortTheory(Search)); + sort_TheoryDelete(prfs_ApproximatedDynamicSortTheory(Search)); + clause_DeleteSharedClauseList(prfs_WorkedOffClauses(Search), + prfs_WorkedOffSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); + clause_DeleteSharedClauseList(prfs_UsableClauses(Search), + prfs_UsableSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); + clause_DeleteSharedClauseList(prfs_DocProofClauses(Search), + prfs_DocProofSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); + prfs_DeleteFinMonPreds(Search); + for (Scan=prfs_SplitStack(Search); !list_Empty(Scan); Scan=list_Cdr(Scan)) + prfs_SplitDelete(list_Car(Scan)); + list_Delete(prfs_SplitStack(Search)); +} + + +void prfs_Delete(PROOFSEARCH Search) +/************************************************************** + INPUT: A proof search object. + RETURNS: Nothing. + EFFECT: The whole structure including all its substructures + is deleted. +***************************************************************/ +{ + prfs_InternalDelete(Search); + + sharing_IndexDelete(prfs_WorkedOffSharingIndex(Search)); + sharing_IndexDelete(prfs_UsableSharingIndex(Search)); + if (prfs_DocProofSharingIndex(Search)) + sharing_IndexDelete(prfs_DocProofSharingIndex(Search)); + flag_DeleteStore(prfs_Store(Search)); + symbol_DeletePrecedence(prfs_Precedence(Search)); + memory_Free(Search,sizeof(PROOFSEARCH_NODE)); +} + + +void prfs_Clean(PROOFSEARCH Search) +/************************************************************** + INPUT: A proof search object. + RETURNS: Nothing. + EFFECT: All clauses are deleted. The structure is cleaned + and initialized. +***************************************************************/ +{ + prfs_InternalDelete(Search); + + Search->emptyclauses = list_Nil(); + Search->definitions = list_Nil(); + Search->usedemptyclauses = list_Nil(); + Search->wolist = list_Nil(); + Search->uslist = list_Nil(); + Search->finmonpreds = list_Nil(); + Search->astatic = (SORTTHEORY)NULL; + Search->adynamic = (SORTTHEORY)NULL; + Search->dynamic = (SORTTHEORY)NULL; + Search->dplist = list_Nil(); + + Search->stack = list_StackBottom(); + Search->validlevel = 0; + Search->lastbacktrack = 0; + Search->splitcounter = 0; + Search->keptclauses = 0; + Search->derivedclauses = 0; + Search->loops = 0; + Search->backtracked = 0; + Search->nontrivclausenumber = 0; + + symbol_ClearPrecedence(prfs_Precedence(Search)); +} + + +void prfs_SwapIndexes(PROOFSEARCH Search) +/************************************************************** + INPUT: A proof search object. + RETURNS: Nothing. + EFFECT: The usable and worked-off indexes are exchanged. +***************************************************************/ +{ + LIST Scan; + SHARED_INDEX Help; + + Help = prfs_WorkedOffSharingIndex(Search); + Scan = prfs_WorkedOffClauses(Search); + prfs_SetWorkedOffClauses(Search,prfs_UsableClauses(Search)); + Search->woindex = prfs_UsableSharingIndex(Search); + prfs_SetUsableClauses(Search, Scan); + Search->usindex = Help; + + for (Scan=prfs_UsableClauses(Search); !list_Empty(Scan); Scan=list_Cdr(Scan)) + clause_RemoveFlag(list_Car(Scan), WORKEDOFF); + for (Scan=prfs_WorkedOffClauses(Search);!list_Empty(Scan);Scan=list_Cdr(Scan)) + clause_SetFlag(list_Car(Scan), WORKEDOFF); +} + + +PROOFSEARCH prfs_Create(void) +/************************************************************** + INPUT: None. + RETURNS: A new proof search object. The worked off and usable + indexes are created whilst the docproof index and the + sort theories are not created, since they are not + needed in general. +***************************************************************/ +{ + PROOFSEARCH Result; + + Result = memory_Malloc(sizeof(PROOFSEARCH_NODE)); + + Result->emptyclauses = list_Nil(); + Result->definitions = list_Nil(); + Result->usedemptyclauses = list_Nil(); + Result->woindex = sharing_IndexCreate(); + Result->wolist = list_Nil(); + Result->usindex = sharing_IndexCreate(); + Result->uslist = list_Nil(); + Result->finmonpreds = list_Nil(); + + Result->astatic = (SORTTHEORY)NULL; + Result->adynamic = (SORTTHEORY)NULL; + Result->dynamic = (SORTTHEORY)NULL; + + Result->precedence = symbol_CreatePrecedence(); + + Result->store = flag_CreateStore(); + flag_InitStoreByDefaults(Result->store); + + Result->dpindex = (SHARED_INDEX)NULL; + Result->dplist = list_Nil(); + + Result->stack = list_StackBottom(); + Result->validlevel = 0; + Result->lastbacktrack = 0; + Result->splitcounter = 0; + Result->keptclauses = 0; + Result->derivedclauses = 0; + Result->loops = 0; + Result->backtracked = 0; + Result->nontrivclausenumber = 0; + + return Result; +} + + +void prfs_CopyIndices(PROOFSEARCH Search, PROOFSEARCH SearchCopy) +/************************************************************** + INPUT: A proof search object and a clean proof search object. + RETURNS: Nothing. + EFFECT: Copies the indices from Search to SearchCopy. + CAUTION: Splitstack and theories are not copied! +***************************************************************/ +{ + LIST Scan; + + /* If a DocProof index is required but not yet allocated in SearchCopy, + do it now */ + if (prfs_DocProofSharingIndex(Search) != NULL && + prfs_DocProofSharingIndex(SearchCopy) == NULL) + prfs_AddDocProofSharingIndex(SearchCopy); + + /* Copy usable, worked-off and docproof index */ + for (Scan = prfs_UsableClauses(Search); !list_Empty(Scan); Scan = list_Cdr(Scan)) + prfs_InsertUsableClause(SearchCopy, clause_Copy((CLAUSE) list_Car(Scan))); + + for (Scan = prfs_WorkedOffClauses(Search); !list_Empty(Scan); Scan = list_Cdr(Scan)) + prfs_InsertWorkedOffClause(SearchCopy, clause_Copy((CLAUSE) list_Car(Scan))); + + for (Scan = prfs_DocProofClauses(Search); !list_Empty(Scan); Scan = list_Cdr(Scan)) + prfs_InsertDocProofClause(SearchCopy, clause_Copy((CLAUSE) list_Car(Scan))); +} + + +void prfs_InsertWorkedOffClause(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + MEMORY: The clause is assumed to be unshared. + EFFECT: The clause is inserted into the worked off sharing index + and list of <Search>. The unshared literals are deleted. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsClause(Clause,prfs_Store(Search), prfs_Precedence(Search))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_InsertWorkedOffClause: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + clause_SetFlag(Clause,WORKEDOFF); + prfs_SetWorkedOffClauses(Search,list_Cons(Clause, prfs_WorkedOffClauses(Search))); + clause_InsertIntoSharing(Clause, prfs_WorkedOffSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); + prfs_InsertInSortTheories(Search, Clause); +} + + +void prfs_InsertUsableClause(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + MEMORY: The clause is assumed to be unshared. + EFFECT: The clause is inserted into the usable sharing index + and list of <Search> sorted with respect to their weight. + The unshared literals are deleted. +***************************************************************/ +{ + +#ifdef CHECK + if (!clause_IsClause(Clause, prfs_Store(Search), prfs_Precedence(Search)) || + clause_GetFlag(Clause, WORKEDOFF)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_InsertUsableClause: Illegal input."); + misc_FinishErrorReport(); + } + /* The invariant that no two clauses have the same clause number cannot */ + /* be guaranteed as long as e.g. several directly subsequent reductions */ + /* are applied to a clause that eventually gets a greater split level. */ +#endif + + prfs_SetUsableClauses(Search,clause_InsertWeighed(Clause, + prfs_UsableClauses(Search), + prfs_Store(Search), + prfs_Precedence(Search))); + clause_InsertIntoSharing(Clause, prfs_UsableSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); +} + + +void prfs_InsertDocProofClause(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + MEMORY: The clause is assumed to be unshared. + EFFECT: The clause is inserted into the proof documentation sharing index. + The unshared literals are deleted. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsClause(Clause, prfs_Store(Search), prfs_Precedence(Search))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_InsertDocProofClause: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (prfs_DocProofSharingIndex(Search) == (SHARED_INDEX)NULL) + clause_Delete(Clause); + else { + prfs_SetDocProofClauses(Search,list_Cons(Clause, prfs_DocProofClauses(Search))); + clause_InsertIntoSharing(Clause, prfs_DocProofSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); + } +} + + +void prfs_MoveUsableWorkedOff(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + EFFECT: The clause is inserted into the worked off sharing index + and list and it is deleted from the usable index and list. + In particular, the WorkedOff flag is set and if <Clause> is a + declaration clause, it is inserted into the respective sort theories. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsClause(Clause,prfs_Store(Search), prfs_Precedence(Search)) || + clause_GetFlag(Clause, WORKEDOFF)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_MoveUsableWorkedOff: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + prfs_SetUsableClauses(Search,list_PointerDeleteElement(prfs_UsableClauses(Search),Clause)); + clause_SetFlag(Clause,WORKEDOFF); + clause_MoveSharedClause(Clause, prfs_UsableSharingIndex(Search), + prfs_WorkedOffSharingIndex(Search), prfs_Store(Search), + prfs_Precedence(Search)); + prfs_SetWorkedOffClauses(Search,list_Cons(Clause, prfs_WorkedOffClauses(Search))); + prfs_InsertInSortTheories(Search, Clause); +} + + +void prfs_MoveWorkedOffDocProof(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + EFFECT: The clause is inserted into the doc proof sharing index + and list of <Search> and it is deleted from the worked off + index and list. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsClause(Clause, prfs_Store(Search), prfs_Precedence(Search)) || + !clause_GetFlag(Clause, WORKEDOFF)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_MoveWorkedOffDocProof: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + prfs_DeleteFromSortTheories(Search, Clause); + prfs_SetWorkedOffClauses(Search,list_PointerDeleteElement(prfs_WorkedOffClauses(Search),Clause)); + clause_RemoveFlag(Clause,WORKEDOFF); + + if (prfs_DocProofSharingIndex(Search) == (SHARED_INDEX)NULL) + clause_DeleteFromSharing(Clause,prfs_WorkedOffSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); + else { + clause_MoveSharedClause(Clause, prfs_WorkedOffSharingIndex(Search), + prfs_DocProofSharingIndex(Search),prfs_Store(Search), + prfs_Precedence(Search)); + prfs_SetDocProofClauses(Search,list_Cons(Clause, prfs_DocProofClauses(Search))); + } +} + + +void prfs_MoveUsableDocProof(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + EFFECT: The clause is inserted into the doc proof sharing index + and list of <Search> and it is deleted from the usable + index and list. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsClause(Clause, prfs_Store(Search), prfs_Precedence(Search)) || + clause_GetFlag(Clause, WORKEDOFF)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_MoveUsableDocProof: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + prfs_SetUsableClauses(Search,list_PointerDeleteElement(prfs_UsableClauses(Search),Clause)); + + if (prfs_DocProofSharingIndex(Search) == (SHARED_INDEX)NULL) + clause_DeleteFromSharing(Clause, prfs_UsableSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); + else { + clause_MoveSharedClause(Clause, prfs_UsableSharingIndex(Search), + prfs_DocProofSharingIndex(Search),prfs_Store(Search), + prfs_Precedence(Search)); + prfs_SetDocProofClauses(Search,list_Cons(Clause, prfs_DocProofClauses(Search))); + } +} + + +void prfs_MoveInvalidClausesDocProof(PROOFSEARCH Search) +/************************************************************** + INPUT: A proof search object. + RETURNS: Nothing. + EFFECT: All clauses that have a split level higher than the + current split level of <Search> are moved to the + proof documentation index. If it does not exist, i.e., + no proof documentation required, the clauses are + deleted. +***************************************************************/ +{ + LIST scan, invalid; + CLAUSE clause; + + invalid = list_Nil(); + for (scan = prfs_WorkedOffClauses(Search); !list_Empty(scan); + scan = list_Cdr(scan)) { + clause = (CLAUSE)list_Car(scan); + if (!prfs_IsClauseValid(clause, prfs_ValidLevel(Search))) + invalid = list_Cons(clause,invalid); + } + /* WARNING: The following move operation changes the worked off */ + /* set of the proof search object destructively. */ + /* So it's impossible to move those function calls into the */ + /* loop above. */ + for ( ; !list_Empty(invalid); invalid = list_Pop(invalid)) + prfs_MoveWorkedOffDocProof(Search,list_Car(invalid)); + + invalid = list_Nil(); + for (scan = prfs_UsableClauses(Search); !list_Empty(scan); + scan = list_Cdr(scan)) { + clause = (CLAUSE)list_Car(scan); + if (!prfs_IsClauseValid(clause, prfs_ValidLevel(Search))) + invalid = list_Cons(clause,invalid); + } + /* WARNING: The following move operation changes the usable */ + /* set of the proof search object destructively. */ + /* So it's impossible to move those function calls into the */ + /* loop above. */ + for ( ; !list_Empty(invalid); invalid = list_Pop(invalid)) + prfs_MoveUsableDocProof(Search,list_Car(invalid)); +} + + +void prfs_ExtractWorkedOff(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + EFFECT: The clause is removed from the worked off index and + list and returned as an unshared clause. + Sort theories are updated accordingly. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause) || !clause_GetFlag(Clause, WORKEDOFF)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_ExtractWorkedOff: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + prfs_DeleteFromSortTheories(Search, Clause); + clause_RemoveFlag(Clause,WORKEDOFF); + prfs_SetWorkedOffClauses(Search,list_PointerDeleteElement(prfs_WorkedOffClauses(Search),Clause)); + clause_MakeUnshared(Clause,prfs_WorkedOffSharingIndex(Search)); +} + + +void prfs_ExtractUsable(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + EFFECT: The clause is removed from the usable off index and + list and returned as an unshared clause. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause) || clause_GetFlag(Clause, WORKEDOFF)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_ExtractUsable: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + prfs_SetUsableClauses(Search,list_PointerDeleteElement(prfs_UsableClauses(Search),Clause)); + clause_MakeUnshared(Clause,prfs_UsableSharingIndex(Search)); +} + + +void prfs_ExtractDocProof(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + EFFECT: The clause is removed from the docproof off index and + list and returned as an unshared clause. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsUnorderedClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_ExtractDocProof: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + prfs_SetDocProofClauses(Search,list_PointerDeleteElement(prfs_DocProofClauses(Search),Clause)); + clause_MakeUnshared(Clause,prfs_DocProofSharingIndex(Search)); +} + + +void prfs_DeleteWorkedOff(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + EFFECT: The clause is deleted from the worked off index and list. + Sort theories are updated accordingly. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsClause(Clause, prfs_Store(Search), prfs_Precedence(Search)) || + !clause_GetFlag(Clause, WORKEDOFF)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_DeleteWorkedOff: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + prfs_DeleteFromSortTheories(Search, Clause); + prfs_SetWorkedOffClauses(Search,list_PointerDeleteElement(prfs_WorkedOffClauses(Search),Clause)); + clause_DeleteFromSharing(Clause, prfs_WorkedOffSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); +} + + +void prfs_DeleteUsable(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and a clause. + RETURNS: Nothing. + EFFECT: The clause is deleted from the usable index and list. +***************************************************************/ +{ +#ifdef CHECK + if (!clause_IsClause(Clause, prfs_Store(Search), prfs_Precedence(Search)) || + clause_GetFlag(Clause, WORKEDOFF)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_DeleteUsable: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + prfs_SetUsableClauses(Search,list_PointerDeleteElement(prfs_UsableClauses(Search),Clause)); + clause_DeleteFromSharing(Clause,prfs_UsableSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); +} + + +void prfs_PrintSplit(SPLIT Split) +/************************************************************** + INPUT: A split. + RETURNS: Nothing. + EFFECT: Prints the information kept in the split structure. +***************************************************************/ +{ + LIST Scan; + + printf("\n Split: %d %ld", prfs_SplitSplitLevel(Split), (long)Split); + fputs("\n Father: ", stdout); + if (prfs_SplitFatherClause(Split) != (CLAUSE)NULL) + clause_Print(prfs_SplitFatherClause(Split)); + else + fputs("No father, unnecessary split.", stdout); + + fputs("\n Split is ", stdout); + if (prfs_SplitIsUnused(Split)) + puts("unused."); + else + puts("used."); + fputs(" Blocked clauses:", stdout); + for (Scan=prfs_SplitBlockedClauses(Split);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + putchar('\n'); + putchar(' '); + clause_Print(list_Car(Scan)); + } + fputs("\n Deleted clauses:", stdout); + for (Scan=prfs_SplitDeletedClauses(Split);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + putchar('\n'); + putchar(' '); + clause_Print(list_Car(Scan)); + } +} + + +void prfs_PrintSplitStack(PROOFSEARCH PS) +/************************************************************** + INPUT: A proof search object. + RETURNS: Nothing. + EFFECT: Prints almost all the information kept in the + split stack structure. +***************************************************************/ +{ + LIST Scan; + + fputs("\n Splitstack:", stdout); + + for (Scan = prfs_SplitStack(PS); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + prfs_PrintSplit(list_Car(Scan)); + fputs("\n---------------------", stdout); + } +} + + +void prfs_Print(PROOFSEARCH Search) +/************************************************************** + INPUT: A proof search object. + RETURNS: void. + EFFECT: The proof search object is printed to stdout. +***************************************************************/ +{ + LIST Scan; + +#ifdef CHECK + if (!prfs_Check(Search)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_Print: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + printf("\n\n Proofsearch: Current Level: %d Last Backtrack Level: %d Splits: %d Loops: %d Backtracked: %d", + prfs_ValidLevel(Search),prfs_LastBacktrackLevel(Search),prfs_SplitCounter(Search), + prfs_Loops(Search),prfs_BacktrackedClauses(Search)); + if (prfs_NonTrivClauseNumber(Search)>0) + printf("\n Clause %d implies a non-trivial domain.", prfs_NonTrivClauseNumber(Search)); + else + fputs("\n Potentially trivial domain.", stdout); + fputs("\n Empty Clauses:", stdout); + for (Scan=prfs_EmptyClauses(Search);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + fputs("\n ", stdout); + clause_Print(list_Car(Scan)); + } + fputs("\n Definitions:", stdout); + for (Scan=prfs_Definitions(Search);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + putchar('\n'); + putchar(' '); + term_Print(list_Car(Scan)); + } + fputs("\n Worked Off Clauses:", stdout); + for (Scan=prfs_WorkedOffClauses(Search);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + putchar('\n'); + putchar(' '); + clause_Print(list_Car(Scan)); + } + fputs("\n Usable Clauses:", stdout); + for (Scan=prfs_UsableClauses(Search);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + putchar('\n'); + putchar(' '); + clause_Print(list_Car(Scan)); + } + fputs("\n Finite predicates:", stdout); + for (Scan=prfs_GetFinMonPreds(Search);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + fputs("\n ", stdout); + symbol_Print((SYMBOL)list_PairFirst(list_Car(Scan))); + fputs(": ", stdout); + term_TermListPrintPrefix(list_PairSecond(list_Car(Scan))); + } + prfs_PrintSplitStack(Search); + fputs("\n Static Sort Theory:", stdout); + sort_TheoryPrint(prfs_StaticSortTheory(Search)); + fputs("\n Dynamic Sort Theory:", stdout); + sort_TheoryPrint(prfs_DynamicSortTheory(Search)); + fputs("\n Approximated Dynamic Sort Theory:", stdout); + sort_TheoryPrint(prfs_ApproximatedDynamicSortTheory(Search)); + putchar('\n'); +} + + +CLAUSE prfs_DoSplitting(PROOFSEARCH PS, CLAUSE SplitClause, LIST Literals) +/************************************************************** + INPUT: An proof search object, an unshared clause to be splitted + where 'Literals' is the list of literals to keep (in their + order in the SplitClause). + RETURNS: A pointer to the (stack-, not sharing-) inserted splitted clause. + MEMORY: The blocked parts and the actparts literals are created + unshared, memory for the two (more for HornSplits) new + clausenodes is allocated. + EFFECT: A new SPLIT object is created on the split stack of the proof + search object. The clause for the right branch will get clause + number 0 to make it distinguishable from the negation clauses, + which get clause number -1. + All newly created clauses are influenced by some flags of the + internal flag store of the proof search object. + For example the maximal literals are influenced by + the weight of function symbols, which is defined by the + flag "flag_FUNCWEIGHT". +***************************************************************/ +{ + + SPLIT NewSplit; + CLAUSE NewClause, BlockedClause; + LITERAL NextLit,NewLit; + int i,j,lengthBlocked,lengthNew,lc,la,ls,nc,na,ns; + +#ifdef CHECK + if (list_Empty(Literals) || + !clause_IsClause(SplitClause, prfs_Store(PS), prfs_Precedence(PS))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_DoSplitting: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + prfs_DecSplitCounter(PS); + NewSplit = prfs_SplitCreate(PS); + + prfs_SplitSetFatherClause(NewSplit, SplitClause); + + lengthNew = list_Length(Literals); + lengthBlocked = clause_Length(SplitClause) - lengthNew; + + NewClause = clause_CreateBody(lengthNew); /* The left clause */ + BlockedClause = clause_CreateBody(lengthBlocked); /* The right clause */ + clause_DecreaseCounter(); /* reset internally increased counter! */ + clause_SetNumber(BlockedClause, 0); + /* To detect forgotten setting at insertion! */ + + lc = clause_LastConstraintLitIndex(SplitClause); + la = clause_LastAntecedentLitIndex(SplitClause); + ls = clause_LastSuccedentLitIndex(SplitClause); + + nc = na = ns = 0; + + j = clause_FirstLitIndex(); + + for (i = clause_FirstLitIndex(); i <= ls; i++) { + NextLit = clause_GetLiteral(SplitClause, i); + + NewLit = clause_LiteralCopy(NextLit); + + if ((lengthNew > 0) && /* To avoid access of Nirvana. */ + list_PointerMember(Literals, NextLit)) { + /* NewLit is literal for the NewClause. */ + + lengthNew--; + clause_SetLiteral(NewClause, j++, NewLit); + clause_LiteralSetOwningClause(NewLit, NewClause); + clause_AddParentClause(NewClause, clause_Number(SplitClause)); + clause_AddParentLiteral(NewClause, i); + if (i <= lc) + nc++; + else if (i <= la) + na++; + else + ns++; + + } else { /* NewLit is literal for the BlockedClause. */ + + clause_SetLiteral(BlockedClause, (i-j), NewLit); + clause_LiteralSetOwningClause(NewLit, BlockedClause); + clause_AddParentClause(BlockedClause, clause_Number(SplitClause)); + clause_AddParentLiteral(BlockedClause, i); + } + } /* end of 'for all literals'. */ + + clause_SetNumOfConsLits(NewClause, nc); + clause_SetNumOfConsLits(BlockedClause, + (clause_NumOfConsLits(SplitClause) - nc)); + clause_SetNumOfAnteLits(NewClause, na); + clause_SetNumOfAnteLits(BlockedClause, + (clause_NumOfAnteLits(SplitClause) - na)); + clause_SetNumOfSuccLits(NewClause, ns); + clause_SetNumOfSuccLits(BlockedClause, + (clause_NumOfSuccLits(SplitClause) - ns)); + + clause_ReInit(BlockedClause, prfs_Store(PS), prfs_Precedence(PS)); + clause_UpdateSplitDataFromNewSplitting(BlockedClause, SplitClause, + prfs_SplitSplitLevel(NewSplit)); + clause_SetFromSplitting(BlockedClause); + clause_SetParentLiterals(BlockedClause, + list_NReverse(clause_ParentLiterals(BlockedClause))); + + clause_SetDepth(BlockedClause, clause_Depth(SplitClause)+1); + + prfs_SplitAddBlockedClause(NewSplit, BlockedClause); + prfs_SplitSetDeletedClauses(NewSplit, list_Nil()); + + + prfs_SplitStackPush(PS, NewSplit); + + clause_ReInit(NewClause, prfs_Store(PS), prfs_Precedence(PS)); + clause_UpdateSplitDataFromNewSplitting(NewClause, SplitClause, + prfs_SplitSplitLevel(NewSplit)); + clause_SetFromSplitting(NewClause); + + clause_SetParentLiterals(NewClause, + list_NReverse(clause_ParentLiterals(NewClause))); + + clause_SetDepth(NewClause, clause_Depth(SplitClause)+1); + clause_RemoveFlag(NewClause, WORKEDOFF); + + if (clause_IsGround(NewClause)) { + /* Keep Clauses made from NewClause for refutation case! */ + CLAUSE UnitClause; + LIST AtomList; + + la = clause_LastAntecedentLitIndex(NewClause); + ls = clause_LastSuccedentLitIndex(NewClause); + + Literals = clause_ParentLiterals(NewClause); + + for (i = clause_FirstLitIndex(); i <= ls; i++) { + + NextLit = clause_GetLiteral(NewClause, i); + AtomList = list_List(term_Copy(clause_LiteralAtom(NextLit))); + + if (i <= la) + UnitClause = clause_Create(list_Nil(), list_Nil(), AtomList, + prfs_Store(PS), prfs_Precedence(PS)); + else + UnitClause = clause_Create(list_Nil(), AtomList, list_Nil(), + prfs_Store(PS), prfs_Precedence(PS)); + + clause_SetNumber(UnitClause, -1); + /* To detect forgotten setting at reinsertion! */ + clause_DecreaseCounter(); + /* Reset internally increased counter! */ + + list_Delete(AtomList); + + clause_SetFromSplitting(UnitClause); + clause_UpdateSplitDataFromNewSplitting(UnitClause, SplitClause, + prfs_SplitSplitLevel(NewSplit)); + clause_AddParentClause(UnitClause, clause_Number(NewClause)); + clause_AddParentLiteral(UnitClause, i); + clause_AddParentClause(UnitClause, clause_Number(SplitClause)); + clause_AddParentLiteral(UnitClause, (int)list_Car(Literals)); + Literals = list_Cdr(Literals); + prfs_SplitAddBlockedClause(NewSplit, UnitClause); + } + } + /* fputs("\n\nSPLITTING DONE!",stdout); + fputs("\nAus : ",stdout); clause_Print(SplitClause); fflush(stdout); + fputs("\nDer erste Teil: ",stdout); clause_Print(NewClause); fflush(stdout); + fputs("\nDer zweite Teil: ",stdout); + clause_Print(BlockedClause); fflush(stdout); + puts("\nDaher als BlockedClauses:"); + clause_ListPrint(prfs_SplitBlockedClauses(NewSplit)); fflush(stdout); + */ + return NewClause; +} + + +static LIST prfs_GetSplitLiterals(PROOFSEARCH PS, CLAUSE Clause) +/************************************************************** + INPUT: A Clause and a proofsearch object + RETURNS: A list of literals building the bigger part of a + variable-disjunct literal partition if one exists, + an empty list, else. + MEMORY: Allocates memory for the literal list. +***************************************************************/ +{ + LITERAL NextLit; + int i, length, OldLength; + LIST LitList, VarOcc, NextOcc; + BOOL Change; + +#ifdef CHECK + if (!clause_IsClause(Clause, prfs_Store(PS), prfs_Precedence(PS))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In prfs_GetSplitLiterals: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + LitList = list_Nil(); + + if (prfs_SplitCounter(PS) != 0) { + + if (clause_HasSuccLits(Clause)) { + if (clause_HasGroundSuccLit(Clause)) { + + NextLit = clause_GetGroundSuccLit(Clause); + LitList = list_Cons(NextLit, LitList); + + for (i = clause_LastAntecedentLitIndex(Clause);i >= clause_FirstLitIndex();i--) { + NextLit = clause_GetLiteral(Clause, i); + if (term_IsGround(clause_LiteralAtom(NextLit))) + LitList = list_Cons(NextLit, LitList); + } + return LitList; + } + + /* Clause has no ground succedent literals, but > 1 non-ground */ + NextLit = clause_GetLiteral(Clause, clause_LastSuccedentLitIndex(Clause)); + VarOcc = term_VariableSymbols(clause_LiteralAtom(NextLit)); + LitList = list_List(NextLit); + length = clause_Length(Clause); + Change = TRUE; + + while (Change) { + Change = FALSE; + + for (i=clause_LastSuccedentLitIndex(Clause)-1; i>=clause_FirstLitIndex(); i--) { + + NextLit = clause_GetLiteral(Clause, i); + + if (!list_PointerMember(LitList, NextLit)) { + NextOcc = term_VariableSymbols(clause_LiteralAtom(NextLit)); + if (list_HasIntersection(VarOcc, NextOcc)) { + OldLength = list_Length(VarOcc); + VarOcc = list_NPointerUnion(VarOcc, NextOcc); + LitList = list_Cons(NextLit, LitList); + if (OldLength != list_Length(VarOcc)) + Change = TRUE; + } + else + list_Delete(NextOcc); + } + } + } + if (list_Length(LitList) == length) { + list_Delete(LitList); + LitList = list_Nil(); + } + Change = TRUE; /* Check whether not all succedent literals are used */ + for (i = clause_FirstSuccedentLitIndex(Clause); i < length && Change; i++) + if (!list_PointerMember(LitList,clause_GetLiteral(Clause, i))) + Change = FALSE; + if (Change) { + list_Delete(LitList); + LitList = list_Nil(); + } + list_Delete(VarOcc); + } + } + return LitList; +} + + +CLAUSE prfs_PerformSplitting(PROOFSEARCH Search, CLAUSE Clause) +/************************************************************** + INPUT: A proof search object and an unshared clause. + EFFECT: If <Clause> can be split it is splitted, the first + part of the split is returned and the + splitted clause is kept in the split stack. + Otherwise <Clause> remains unchanged and NULL is returned. + RETURNS: NULL if <Clause> is not splittable, the first split part otherwise. +***************************************************************/ +{ + CLAUSE Result; + + Result = (CLAUSE)NULL; + + if (clause_HasSolvedConstraint(Clause)) { + LIST LitList; + + LitList = prfs_GetSplitLiterals(Search, Clause); + + if (!list_Empty(LitList)) { + Result = prfs_DoSplitting(Search, Clause, LitList); + list_Delete(LitList); + } + } + + return Result; +} + + +void prfs_InstallFiniteMonadicPredicates(PROOFSEARCH Search, LIST Clauses, + LIST Predicates) +/************************************************************** + INPUT: A proof search object a list of clauses and a list + of monadic predicates. + RETURNS: Nothing. + EFFECT: The argument terms for <Predicates> that occur in + positive unit clauses are extracted from <Clauses> + and installed in <Search> as an assoc list. +***************************************************************/ +{ + LIST Pair, Scan, Result; + CLAUSE Clause; + TERM Atom; + + Result = list_Nil(); + + for (Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Clause = (CLAUSE)list_Car(Scan); + if (clause_Length(Clause) == 1 && + clause_NumOfSuccLits(Clause) == 1) { + Atom = clause_GetLiteralAtom(Clause,clause_FirstSuccedentLitIndex(Clause)); + if (list_PointerMember(Predicates, (POINTER)term_TopSymbol(Atom))) { + Pair = list_AssocListPair(Result, (POINTER)term_TopSymbol(Atom)); + if (Pair != list_PairNull()) + list_PairRplacSecond(Pair, list_Cons(term_Copy(term_FirstArgument(Atom)),list_PairSecond(Pair))); + else + Result = list_AssocCons(Result, (POINTER)term_TopSymbol(Atom), + list_List(term_Copy(term_FirstArgument(Atom)))); + } + } + } + + prfs_DeleteFinMonPreds(Search); + prfs_SetFinMonPreds(Search, Result); +} + + +NAT prfs_GetNumberOfInstances(PROOFSEARCH Search, LITERAL Literal, BOOL Usables) +/************************************************************** + INPUT: A proof search object, a literal, and a boolean flag. + RETURNS: The number of instances of the literal's atom. + EFFECT: +***************************************************************/ +{ + TERM Atom; + NAT NrOfInstances; + SHARED_INDEX WOIndex, UsIndex; + + Atom = clause_LiteralAtom(Literal); + WOIndex = prfs_WorkedOffSharingIndex(Search); + UsIndex = prfs_UsableSharingIndex(Search); + NrOfInstances = sharing_GetNumberOfInstances(Atom, WOIndex); + if (Usables) + NrOfInstances += sharing_GetNumberOfInstances(Atom, UsIndex); + + if (fol_IsEquality(Atom)) { + /* Exchange the subterms of the equation, and count the instances, too */ + Atom = term_Create(fol_Equality(), list_Reverse(term_ArgumentList(Atom))); + + NrOfInstances += sharing_GetNumberOfInstances(Atom, WOIndex); + if (Usables) + NrOfInstances += sharing_GetNumberOfInstances(Atom, UsIndex); + + list_Delete(term_ArgumentList(Atom)); + term_Free(Atom); + + /* If equation is oriented, consider instances of the greater side, too */ + Atom = clause_LiteralAtom(Literal); + if (clause_LiteralIsOrientedEquality(Literal)) { + NrOfInstances += sharing_GetNumberOfInstances(term_FirstArgument(Atom), + WOIndex); + if (Usables) + NrOfInstances += sharing_GetNumberOfInstances(term_FirstArgument(Atom), + UsIndex); + } + } + + return NrOfInstances; +} diff --git a/test/spass/search.h b/test/spass/search.h new file mode 100644 index 0000000000000000000000000000000000000000..c34eb8abf353c3413f163a8df34f65937738ae10 --- /dev/null +++ b/test/spass/search.h @@ -0,0 +1,522 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * REPRESENTATION OF PROOF SEARCH * */ +/* * * */ +/* * $Module: PROOF SEARCH * */ +/* * * */ +/* * Copyright (C) 1997, 1998, 1999, 2000 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _PROOFSEARCH_ +#define _PROOFSEARCH_ + +#include "clause.h" +#include "sort.h" + +/**************************************************************/ +/* Data Structures and Constants */ +/**************************************************************/ + +/* <blockedClauses>: list of (unshared) clauses containing the */ +/* "remainder" of the clause splitted at this */ +/* level and the negation of the first branch */ +/* if this branch created a ground clause. */ +/* The right clause has clause number 0, and */ +/* the negation clauses have number -1. */ +/* <deletedClauses>: list of (unshared) clauses made redundant */ +/* by a clause of this level. The split level */ +/* of these clauses may be above or below the */ +/* current level, but not equal to the current */ +/* level. */ +/* <father>: the unshared clause that was splitted. */ +typedef struct { + /* == 0 -> TOPLEVEL, 1,2,... */ + int splitlevel; + BOOL used; + LIST blockedClauses, deletedClauses; + CLAUSE father; +} *SPLIT, SPLIT_NODE; + + +typedef struct PROOFSEARCH_HELP { + LIST definitions; + LIST emptyclauses; + LIST usedemptyclauses; + LIST finmonpreds; + SHARED_INDEX woindex; + LIST wolist; + SHARED_INDEX usindex; + LIST uslist; + SORTTHEORY astatic; + SORTTHEORY adynamic; + SORTTHEORY dynamic; + SHARED_INDEX dpindex; + LIST dplist; + PRECEDENCE precedence; + FLAGSTORE store; + LIST stack; + int validlevel; + int lastbacktrack; + int splitcounter; + int keptclauses; + int derivedclauses; + int loops; + int backtracked; + NAT nontrivclausenumber; +} PROOFSEARCH_NODE,*PROOFSEARCH; + +/* There are two sets of clauses with their respective clause list: worked-off clauses */ +/* contained in <woindex>, <wolist> and usable clauses, contained in <usindex>,<uslist>. */ +/* The assoc list <finitepreds> is a list of pairs (<pred>.(<gterm1>,...,<gtermn>)) */ +/* where <pred> (monadic) has (at most) the extension <gterm1>,...,<gtermn> */ +/* Three sort theories: <astatic> is the static overall approximation, only available */ +/* in a non-equality setting, <adynamic> is the dynamic approximation only considering */ +/* maximal declarations, and <dynamic> is the (not approximated) dynamic sort theory of */ +/* all maximal declarations. Clauses that are no longer needed for the search, but for */ +/* proof documentation are stored in <dpindex>, <dplist>. If <dpindex> is NULL, then */ +/* this means that no proof documentation is required. */ +/* A search is also heavily influenced by the used <precedence> and flag values in */ +/* store. */ +/* The next components deal with splitting: the split stack, the current level */ +/* of splitting, the last backtrack level (for branch condensing) and the overall number */ +/* of splittings stored in <splitcounter>. */ +/* Finally some statistics is stored: the number of kept, derived clauses ... */ +/* and the clause number of some clause that implies a non-trivial domain . */ + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +static __inline__ LIST prfs_EmptyClauses(PROOFSEARCH Prf) +{ + return Prf->emptyclauses; +} + +static __inline__ void prfs_SetEmptyClauses(PROOFSEARCH Prf, LIST Clauses) +{ + Prf->emptyclauses = Clauses; +} + +static __inline__ LIST prfs_Definitions(PROOFSEARCH Prf) +{ + return Prf->definitions; +} + +static __inline__ void prfs_SetDefinitions(PROOFSEARCH Prf, LIST Definitions) +{ + Prf->definitions = Definitions; +} + +static __inline__ LIST prfs_UsedEmptyClauses(PROOFSEARCH Prf) +{ + return Prf->usedemptyclauses; +} + +static __inline__ void prfs_SetUsedEmptyClauses(PROOFSEARCH Prf, LIST Clauses) +{ + Prf->usedemptyclauses = Clauses; +} + + +static __inline__ LIST prfs_WorkedOffClauses(PROOFSEARCH Prf) +{ + return Prf->wolist; +} + +static __inline__ void prfs_SetWorkedOffClauses(PROOFSEARCH Prf, LIST Clauses) +{ + Prf->wolist = Clauses; +} + +static __inline__ SHARED_INDEX prfs_WorkedOffSharingIndex(PROOFSEARCH Prf) +{ + return Prf->woindex; +} + +static __inline__ LIST prfs_UsableClauses(PROOFSEARCH Prf) +{ + return Prf->uslist; +} + +static __inline__ void prfs_SetUsableClauses(PROOFSEARCH Prf, LIST Clauses) +{ + Prf->uslist = Clauses; +} + +static __inline__ SHARED_INDEX prfs_UsableSharingIndex(PROOFSEARCH Prf) +{ + return Prf->usindex; +} + +static __inline__ LIST prfs_DocProofClauses(PROOFSEARCH Prf) +{ + return Prf->dplist; +} + +static __inline__ void prfs_SetDocProofClauses(PROOFSEARCH Prf, LIST Clauses) +{ + Prf->dplist = Clauses; +} + +static __inline__ SHARED_INDEX prfs_DocProofSharingIndex(PROOFSEARCH Prf) +{ + return Prf->dpindex; +} + +static __inline__ void prfs_AddDocProofSharingIndex(PROOFSEARCH Prf) +{ + Prf->dpindex = sharing_IndexCreate(); +} + +static __inline__ LIST prfs_GetFinMonPreds(PROOFSEARCH Prf) +{ + return Prf->finmonpreds; +} + +static __inline__ void prfs_SetFinMonPreds(PROOFSEARCH Prf, LIST Preds) +{ + Prf->finmonpreds = Preds; +} + +static __inline__ void prfs_DeleteFinMonPreds(PROOFSEARCH Prf) +{ + list_DeleteAssocListWithValues(Prf->finmonpreds, + (void (*)(POINTER)) term_DeleteTermList); + prfs_SetFinMonPreds(Prf, list_Nil()); +} + +static __inline__ SORTTHEORY prfs_StaticSortTheory(PROOFSEARCH Prf) +{ + return Prf->astatic; +} + +static __inline__ void prfs_SetStaticSortTheory(PROOFSEARCH Prf, SORTTHEORY Theory) +{ + Prf->astatic = Theory; +} + +static __inline__ SORTTHEORY prfs_DynamicSortTheory(PROOFSEARCH Prf) +{ + return Prf->dynamic; +} + +static __inline__ void prfs_SetDynamicSortTheory(PROOFSEARCH Prf, SORTTHEORY Theory) +{ + Prf->dynamic = Theory; +} + +static __inline__ SORTTHEORY prfs_ApproximatedDynamicSortTheory(PROOFSEARCH Prf) +{ + return Prf->adynamic; +} + +static __inline__ void prfs_SetApproximatedDynamicSortTheory(PROOFSEARCH Prf, SORTTHEORY Theory) +{ + Prf->adynamic = Theory; +} + +static __inline__ PRECEDENCE prfs_Precedence(PROOFSEARCH Prf) +{ + return Prf->precedence; +} + +static __inline__ FLAGSTORE prfs_Store(PROOFSEARCH Prf) +{ + return Prf->store; +} + +static __inline__ BOOL prfs_SplitLevelCondition(NAT OriginLevel, NAT RedundantLevel, NAT BacktrackLevel) +{ + return (OriginLevel > RedundantLevel || OriginLevel > BacktrackLevel); +} + +static __inline__ BOOL prfs_IsClauseValid(CLAUSE C, int Level) +{ + return clause_SplitLevel(C) <= Level; +} + +static __inline__ SPLIT prfs_GetSplitOfLevel(int L, PROOFSEARCH Prf) +{ + LIST Scan; + Scan = Prf->stack; + while (!list_Empty(Scan) && + (((SPLIT)list_Car(Scan))->splitlevel != L)) + Scan = list_Cdr(Scan); + + return (SPLIT) list_Car(Scan); +} + +static __inline__ LIST prfs_SplitStack(PROOFSEARCH Prf) +{ + return Prf->stack; +} + +static __inline__ SPLIT prfs_SplitStackTop(PROOFSEARCH Prf) +{ + return (SPLIT) list_Car(Prf->stack); +} + +static __inline__ void prfs_SplitStackPop(PROOFSEARCH Prf) +{ + Prf->stack = list_Pop(Prf->stack); +} + +static __inline__ void prfs_SplitStackPush(PROOFSEARCH Prf, SPLIT S) +{ + Prf->stack = list_Cons(S, Prf->stack); +} + +static __inline__ BOOL prfs_SplitStackEmpty(PROOFSEARCH Prf) +{ + return list_StackEmpty(prfs_SplitStack(Prf)); +} + +static __inline__ int prfs_TopLevel(void) +{ + return 0; +} + +static __inline__ int prfs_ValidLevel(PROOFSEARCH Prf) +{ + return Prf->validlevel; +} + +static __inline__ void prfs_SetValidLevel(PROOFSEARCH Prf, int Value) +{ + Prf->validlevel = Value; +} + +static __inline__ void prfs_IncValidLevel(PROOFSEARCH Prf) +{ + (Prf->validlevel)++; +} + +static __inline__ void prfs_DecValidLevel(PROOFSEARCH Prf) +{ + (Prf->validlevel)--; +} + +static __inline__ int prfs_LastBacktrackLevel(PROOFSEARCH Prf) +{ + return Prf->lastbacktrack; +} + +static __inline__ void prfs_SetLastBacktrackLevel(PROOFSEARCH Prf, int Value) +{ + Prf->lastbacktrack = Value; +} + +static __inline__ int prfs_SplitCounter(PROOFSEARCH Prf) +{ + return Prf->splitcounter; +} + +static __inline__ void prfs_SetSplitCounter(PROOFSEARCH Prf, int c) +{ + Prf->splitcounter = c; +} + +static __inline__ void prfs_DecSplitCounter(PROOFSEARCH Prf) +{ + (Prf->splitcounter)--; +} + +static __inline__ int prfs_KeptClauses(PROOFSEARCH Prf) +{ + return Prf->keptclauses; +} + +static __inline__ void prfs_IncKeptClauses(PROOFSEARCH Prf) +{ + Prf->keptclauses++; +} + +static __inline__ int prfs_DerivedClauses(PROOFSEARCH Prf) +{ + return Prf->derivedclauses; +} + +static __inline__ void prfs_IncDerivedClauses(PROOFSEARCH Prf, int k) +{ + Prf->derivedclauses += k; +} + +static __inline__ int prfs_Loops(PROOFSEARCH Prf) +{ + return Prf->loops; +} + +static __inline__ void prfs_SetLoops(PROOFSEARCH Prf, int k) +{ + Prf->loops = k; +} + +static __inline__ void prfs_DecLoops(PROOFSEARCH Prf) +{ + Prf->loops--; +} + +static __inline__ int prfs_BacktrackedClauses(PROOFSEARCH Prf) +{ + return Prf->backtracked; +} + +static __inline__ void prfs_SetBacktrackedClauses(PROOFSEARCH Prf, int k) +{ + Prf->backtracked = k; +} + +static __inline__ void prfs_IncBacktrackedClauses(PROOFSEARCH Prf, int k) +{ + Prf->backtracked += k; +} + +static __inline__ NAT prfs_NonTrivClauseNumber(PROOFSEARCH Prf) +{ + return Prf->nontrivclausenumber; +} + +static __inline__ void prfs_SetNonTrivClauseNumber(PROOFSEARCH Prf, NAT Number) +{ + Prf->nontrivclausenumber = Number; +} + + +/**************************************************************/ +/* Functions for accessing SPLIT objects */ +/**************************************************************/ + +static __inline__ void prfs_SplitFree(SPLIT Sp) +{ + memory_Free(Sp, sizeof(SPLIT_NODE)); +} + +static __inline__ LIST prfs_SplitBlockedClauses(SPLIT S) +{ + return S->blockedClauses; +} + +static __inline__ void prfs_SplitAddBlockedClause(SPLIT S, CLAUSE C) +{ + S->blockedClauses = list_Cons(C,S->blockedClauses); +} + +static __inline__ void prfs_SplitSetBlockedClauses(SPLIT S, LIST L) +{ + S->blockedClauses = L; +} + +static __inline__ LIST prfs_SplitDeletedClauses(SPLIT S) +{ + return S->deletedClauses; +} + +static __inline__ void prfs_SplitSetDeletedClauses(SPLIT S, LIST L) +{ + S->deletedClauses = L; +} + +static __inline__ int prfs_SplitSplitLevel(SPLIT S) +{ + return S->splitlevel; +} + +static __inline__ BOOL prfs_SplitIsUsed(SPLIT S) +{ + return S->used; +} + +static __inline__ BOOL prfs_SplitIsUnused(SPLIT S) +{ + return !S->used; +} + +static __inline__ void prfs_SplitSetUsed(SPLIT S) +{ + S->used = TRUE; +} + +static __inline__ CLAUSE prfs_SplitFatherClause(SPLIT S) +{ + return S->father; +} + +static __inline__ void prfs_SplitSetFatherClause(SPLIT S, CLAUSE C) +{ + S->father = C; +} + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +PROOFSEARCH prfs_Create(void); +BOOL prfs_Check(PROOFSEARCH); +void prfs_CopyIndices(PROOFSEARCH, PROOFSEARCH); +void prfs_Delete(PROOFSEARCH); +void prfs_DeleteDocProof(PROOFSEARCH); +void prfs_Clean(PROOFSEARCH); +void prfs_Print(PROOFSEARCH); +void prfs_PrintSplit(SPLIT); +void prfs_PrintSplitStack(PROOFSEARCH); +void prfs_InsertWorkedOffClause(PROOFSEARCH,CLAUSE); +void prfs_InsertUsableClause(PROOFSEARCH,CLAUSE); +void prfs_InsertDocProofClause(PROOFSEARCH,CLAUSE); +void prfs_MoveUsableWorkedOff(PROOFSEARCH, CLAUSE); +void prfs_MoveWorkedOffDocProof(PROOFSEARCH, CLAUSE); +void prfs_MoveUsableDocProof(PROOFSEARCH, CLAUSE); +void prfs_ExtractWorkedOff(PROOFSEARCH, CLAUSE); +void prfs_DeleteWorkedOff(PROOFSEARCH, CLAUSE); +void prfs_ExtractUsable(PROOFSEARCH, CLAUSE); +void prfs_DeleteUsable(PROOFSEARCH, CLAUSE); +void prfs_ExtractDocProof(PROOFSEARCH, CLAUSE); +void prfs_MoveInvalidClausesDocProof(PROOFSEARCH); +void prfs_SwapIndexes(PROOFSEARCH); + +void prfs_InstallFiniteMonadicPredicates(PROOFSEARCH, LIST, LIST); + +CLAUSE prfs_PerformSplitting(PROOFSEARCH, CLAUSE); +CLAUSE prfs_DoSplitting(PROOFSEARCH, CLAUSE, LIST); +NAT prfs_GetNumberOfInstances(PROOFSEARCH, LITERAL, BOOL); + + +#endif diff --git a/test/spass/sharing.c b/test/spass/sharing.c new file mode 100644 index 0000000000000000000000000000000000000000..47f8b501793568db835f58f627ebfc2150a969cf --- /dev/null +++ b/test/spass/sharing.c @@ -0,0 +1,1143 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * STRUCTURE SHARING * */ +/* * * */ +/* * $Module: SHARING * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "sharing.h" + +/**************************************************************/ +/* Static Variables */ +/**************************************************************/ + +#ifdef CHECK +static BOOL sharing_DATABLOCKED; +#endif + +static LIST sharing_DATALIST = (LIST) NULL; + +#define sharing_STACKSIZE 500 +static LIST sharing_STACK[sharing_STACKSIZE]; +static LIST* sharing_STACKPOINTER = sharing_STACK; + +/**************************************************************/ +/* Prototypes for static functions used only in this module */ +/**************************************************************/ + +static BOOL sharing_IsNoMoreUsed(TERM); +static LIST sharing_InternGetDataList(TERM); + +static TERM sharing_InsertIntoSharing(TERM, SHARED_INDEX); +static void sharing_DeleteFromSharing(TERM, SHARED_INDEX); + +static void sharing_ResetTermStamp(TERM); + +static void sharing_PrintWithSuperterms(TERM); + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * PRIMITIVE SHARING FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +SHARED_INDEX sharing_IndexCreate(void) +/********************************************************** + INPUT: None. + RETURNS: A shared index, consisting of an Index, a Consttable + and a Vartable. + EFFECTS: Initializes the shared Index for the sharing_Vartable and the + sharing_Consttable with NULL-Pointers and an empty st_index. +**********************************************************/ +{ + SHARED_INDEX Result; + int i; + + Result = (SHARED_INDEX)memory_Malloc(sizeof(SHARED_INDEX_NODE)); + sharing_SetIndex(Result, st_IndexCreate()); + + for (i=0; (i < symbol_MaxVars()); i++) + sharing_SetVartableEntry(Result, i, NULL); + + for (i=0; (i < symbol_MaxConsts()); i++) + sharing_SetConsttableEntry(Result, i, NULL); + + sharing_SetStampID(Result, term_GetStampID()); + return Result; +} + + +void sharing_IndexDelete(SHARED_INDEX ShIndex) +/********************************************************** + INPUT: A shared Index. + RETURNS: None. + EFFECTS: Deletes the Index and frees the memory for the + structure including the Const- and Vartable. +**********************************************************/ +{ + st_IndexDelete(sharing_Index(ShIndex)); + + memory_Free(ShIndex, sizeof(SHARED_INDEX_NODE)); +} + + +void sharing_PushOnStack(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: None. + EFFECTS: Creates a Stack of Pointers to the + term and all of its subterms in their order in + the arglist (thus ordered by depth). + top of the stack is bottom term +**********************************************************/ +{ + LIST ArgList; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_PushOnStack: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + stack_Push(Term); + + ArgList = term_ArgumentList(Term); + + while (!list_Empty(ArgList)){ + sharing_PushOnStack(list_Car(ArgList)); + ArgList = list_Cdr(ArgList); + } +} + + +void sharing_PushReverseOnStack(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: None. + EFFECTS: Creates a Stack of Pointers to the + term and all of its subterms, except variables in their order in + the arglist (thus ordered by depth). + top of the stack is top term +**********************************************************/ +{ + LIST ArgList; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_PushReverseOnStack: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if (!term_IsVariable(Term)) { + + ArgList = term_ArgumentList(Term); + + while (!list_Empty(ArgList)){ + sharing_PushReverseOnStack(list_Car(ArgList)); + ArgList = list_Cdr(ArgList); + } + + stack_Push(Term); + } +} + +void sharing_PushReverseOnStackExcept(TERM Term, LIST DontTermList) +/********************************************************** + INPUT: A term and an exception list. + RETURNS: None. + EFFECTS: Creates a Stack of Pointers to the + term and all of its subterms that are not contained + or below the terms in DontTermList in their order in + the arglist (thus ordered by depth). + top of the stack is top term +**********************************************************/ +{ + LIST ArgList; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_PushReverseOnStack: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if (!term_IsVariable(Term) && !term_ListContainsTerm(DontTermList, Term)) { + ArgList = term_ArgumentList(Term); + + while (!list_Empty(ArgList)){ + sharing_PushReverseOnStackExcept(list_Car(ArgList), DontTermList); + ArgList = list_Cdr(ArgList); + } + + stack_Push(Term); + } +} + +void sharing_PushOnStackNoStamps(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: None. + EFFECTS: Creates a Stack of Pointers to the + term and all of its subterms that are not stamped + or below stamped terms. + top of the stack is top term. +**********************************************************/ +{ + LIST ArgList; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_PushReverseOnStackNoStamps: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if (!term_IsVariable(Term) && !term_HasTermStamp(Term)) { + + stack_Push(Term); + + ArgList = term_ArgumentList(Term); + + while (!list_Empty(ArgList)){ + sharing_PushOnStackNoStamps(list_Car(ArgList)); + ArgList = list_Cdr(ArgList); + } + } +} + + +void sharing_PushListOnStack(LIST TermList) +/********************************************************** + INPUT: A list of terms. + RETURNS: None. + EFFECTS: Creates a Stack of Pointers to the + terms in <TermList> and all of subterms in their order in + the arglist (thus ordered by depth). +**********************************************************/ +{ + while (!list_Empty(TermList)) { + sharing_PushOnStack(list_Car(TermList)); + TermList = list_Cdr(TermList); + } +} + + +void sharing_PushListReverseOnStack(LIST TermList) +/********************************************************** + INPUT: A list of terms. + RETURNS: None. + EFFECTS: Puts all terms in Termlist and their superterms + in their order in the arglist (thus ordered by depth) + on the stack. + On top of the stack are subterms. +**********************************************************/ +{ + while (!list_Empty(TermList)) { + sharing_PushReverseOnStack(list_Car(TermList)); + TermList = list_Cdr(TermList); + } +} + +void sharing_PushListReverseOnStackExcept(LIST TermList, LIST DontPushList) +/********************************************************** + INPUT: Two lists of terms. + RETURNS: None. + EFFECTS: Puts all terms in Termlist except those contained in + DontPushList and their superterms + in their order in the arglist (thus ordered by depth) + on the stack. + On top of the stack are subterms. +**********************************************************/ +{ + while (!list_Empty(TermList)) { + sharing_PushReverseOnStackExcept(list_Car(TermList), DontPushList); + TermList = list_Cdr(TermList); + } +} + +void sharing_PushListOnStackNoStamps(LIST TermList) +/********************************************************** + INPUT: A list of terms. + RETURNS: None. + EFFECTS: Puts all terms in Termlist on the stack. + On top of the stack are subterms. +**********************************************************/ +{ + while (!list_Empty(TermList)) { + sharing_PushOnStackNoStamps(list_Car(TermList)); + TermList = list_Cdr(TermList); + } +} + + +static BOOL sharing_IsNoMoreUsed(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: TRUE, if the Term has no superterms, + FALSE, else. +**********************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_IsNoMoreUsed: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + return (list_Empty(term_SupertermList(Term))); +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * FUNCTIONS FOR INSERTION AND DELETION * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * 1) FUNCTIONS FOR INSERTION * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +TERM sharing_Insert(POINTER Data, TERM Atom, SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A data element, it's unshared atom and a SharedIndex. + RETURNS: The shared term inserted into the SharedIndex. + CAUTION: The superterm slot of <Atom> is destructively used! + MEMORY: The term 'Atom' still exists, memory needed for + the shared version is allocated. +**********************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(Atom) || (!sharing_IsNoMoreUsed(Atom))){ + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_Insert: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + Atom = sharing_InsertIntoSharing(Atom, SharedIndex); + + term_RplacSupertermList(Atom, list_Cons(Data, term_SupertermList(Atom))); + + return(Atom); +} + + +static TERM sharing_InsertIntoSharing(TERM Term, SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A term and a shared index. + RETURNS: A copy of 'Term' which is inserted into the Sharing + and the "SharedIndex". + MEMORY: The unshared version isn't freed, needed memory + is allocated. +**********************************************************/ +{ + int B_Stack; + TERM InsTerm; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_InsertIntoSharing: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + B_Stack = stack_Bottom(); + sharing_PushOnStack(Term); + InsTerm = stack_Top(); /* not necessary initialization ... */ + + while (! stack_Empty(B_Stack)){ + InsTerm = stack_PopResult(); + + if (term_IsVariable(InsTerm)){ + if (!sharing_IsSharedVar(InsTerm, SharedIndex)) { + + sharing_SetVartableEntry(SharedIndex, sharing_VariableIndex(InsTerm), + term_Create(term_TopSymbol(InsTerm), + list_Nil())); + + st_EntryCreate(sharing_Index(SharedIndex), + sharing_VartableEntry(SharedIndex, + sharing_VariableIndex(InsTerm)), + sharing_VartableEntry(SharedIndex, + sharing_VariableIndex(InsTerm)), + cont_LeftContext()); + } + + /* The NULL-Pointer in the Vartable is replaced by a copy of the */ + /* InsTerm, which is referenced by the InsTerms SharedTermCopy. */ + /* A complex T still has to be insert. into its Args superlists. */ + /* The unshared Term isn't yet in the 'SharedIndex' and thus is */ + /* inserted, too. */ + + + sharing_RememberSharedTermCopy(InsTerm, + sharing_VartableEntry(SharedIndex, sharing_VariableIndex(InsTerm))); + + }else if (term_IsConstant(InsTerm)){ + if (!sharing_IsSharedConst(InsTerm, SharedIndex)) { + sharing_SetConsttableEntry(SharedIndex, sharing_ConstantIndex(InsTerm), + term_Create(term_TopSymbol(InsTerm), + list_Nil())); + + st_EntryCreate(sharing_Index(SharedIndex), + sharing_ConsttableEntry(SharedIndex, sharing_ConstantIndex(InsTerm)), + sharing_ConsttableEntry(SharedIndex, sharing_ConstantIndex(InsTerm)), + cont_LeftContext()); + } + + /* The NULL-Pointer in the Consttable is replaced by a copy of the */ + /* InsTerm, which is referenced by the InsTerms SharedTermCopy. */ + /* A complex T still has to be insert. into its Args superlists. */ + /* The unshared Term isn't yet in the 'SharedIndex' and thus is */ + /* inserted, too. */ + + sharing_RememberSharedTermCopy(InsTerm, + sharing_ConsttableEntry(SharedIndex, sharing_ConstantIndex(InsTerm))); + + }else{ /* term_IsComplex(InsTerm) */ + /* -> owns subterms which now have copies in Sharing. */ + + TERM SharedDuplicate; + LIST HelpList; + BOOL DuplCandHasSameArgs; + + SharedDuplicate = (TERM)NULL; + HelpList = + term_SupertermList(sharing_SharedTermCopy(term_FirstArgument(InsTerm))); + if (list_Empty(HelpList)){ + SharedDuplicate = term_Create(term_TopSymbol(InsTerm), list_Nil()); + DuplCandHasSameArgs = FALSE; + } + else{ + DuplCandHasSameArgs = FALSE; + while (!DuplCandHasSameArgs && !list_Empty(HelpList)){ + SharedDuplicate = (TERM) list_First(HelpList); + + if (term_TopSymbol(SharedDuplicate) == term_TopSymbol(InsTerm)){ + LIST OrigHelpArgList, DuplHelpArgList; + + OrigHelpArgList = term_ArgumentList(InsTerm); + DuplHelpArgList = term_ArgumentList(SharedDuplicate); + while (!list_Empty(OrigHelpArgList) && + (DuplCandHasSameArgs = + (sharing_SharedTermCopy(list_First(OrigHelpArgList)) == + list_First(DuplHelpArgList)))){ + DuplHelpArgList = list_Cdr(DuplHelpArgList); + OrigHelpArgList = list_Cdr(OrigHelpArgList); + } + } + HelpList = list_Cdr(HelpList); + } + if (!DuplCandHasSameArgs) + SharedDuplicate = term_Create(term_TopSymbol(InsTerm), list_Nil()); + } /* end of else fuer Behandlung von InsTerm mit shared FirstArg. */ + + if (!DuplCandHasSameArgs){ + /* Falls neue Kopie gemacht wurde, wird diese hier "eingeshared": */ + + for (HelpList = term_ArgumentList(InsTerm); !list_Empty(HelpList); + HelpList = list_Cdr(HelpList)){ + TERM SharedArg; + + SharedArg = sharing_SharedTermCopy((TERM)list_First(HelpList)); + + term_RplacArgumentList(SharedDuplicate, + list_Cons(SharedArg, + term_ArgumentList(SharedDuplicate))); + + term_RplacSupertermList(SharedArg, + list_Cons(SharedDuplicate, + term_SupertermList(SharedArg))); + } + term_RplacArgumentList(SharedDuplicate, + list_NReverse(term_ArgumentList(SharedDuplicate))); + + /* Now a newly generated term can be inserted into the 'SharedIndex' ! */ + + st_EntryCreate(sharing_Index(SharedIndex), + SharedDuplicate, + SharedDuplicate, + cont_LeftContext()); + + } + sharing_RememberSharedTermCopy(InsTerm, + SharedDuplicate); + } + } + + return(sharing_SharedTermCopy(InsTerm)); +} + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * 2) FUNCTIONS FOR DELETION * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +void sharing_Delete(POINTER Data, TERM Atom, SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A data element, its atom and an index. + RETURNS: Nothing. + MEMORY: Destructive, deletes 'Atom' from Sharing and frees + memory that's no more needed. +***********************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(Atom)){ + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_Delete: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + term_RplacSupertermList(Atom, + list_PointerDeleteElement(term_SupertermList(Atom), Data)); + + if (sharing_IsNoMoreUsed(Atom)) + sharing_DeleteFromSharing(Atom, SharedIndex); + +} + + +static void sharing_DeleteFromSharing(TERM Term, SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A term and a SharedIndex + RETURNS: Nothing + MEMORY: 'Term' is removed from the Sharing, only correct + if 'Term' is unshared in sharing (real subterms + may be shared, off course). +***********************************************************/ +{ + BOOL IsIndexed; +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_DeleteFromSharing: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + IsIndexed = st_EntryDelete(sharing_Index(SharedIndex), Term, Term, cont_LeftContext()); + +#ifdef CHECK + if (!IsIndexed) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_DeleteFromSharing: Input not indexed.\n"); + misc_FinishErrorReport(); + } +#endif + + if (term_IsComplex(Term)){ + LIST Args; + + Args = term_ArgumentList(Term); + + while (!list_Empty(Args)){ + TERM NextArg; + LIST Help; + + /* This block frees the terms arglists memory. */ + Help = Args; + NextArg = (TERM) list_First(Args); + Args = list_Cdr(Args); + list_Free(Help); + + term_RplacSupertermList(NextArg, + list_PointerDeleteOneElement(term_SupertermList(NextArg), Term)); + if (sharing_IsNoMoreUsed(NextArg)) + sharing_DeleteFromSharing(NextArg, SharedIndex); + } + + } else if (term_IsConstant(Term)) { + sharing_SetConsttableEntry(SharedIndex, sharing_ConstantIndex(Term), NULL); + } else { + sharing_SetVartableEntry(SharedIndex, sharing_VariableIndex(Term), NULL); + } + list_Delete(term_SupertermList(Term)); + term_Free(Term); +} + + +/**************************************************************/ +/* Functions to access unshared data via the shared term. */ +/**************************************************************/ + +LIST sharing_GetDataList(TERM Term, SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A shared term and the shared index it belongs to. + RETURNS: The list of data connected to all superterms of Term, + e.g. the list of all literals containing Term. + EFFECT: Allocates memory for the returned list. + CAUTION: Works recursive! +**********************************************************/ +{ + LIST Result = list_Nil(); +#ifdef CHECK + if (!term_IsTerm(Term) || (SharedIndex == NULL)){ + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_GetDataList: Illegal input.\n"); + misc_FinishErrorReport(); + } + /* What if the term doesn't belong to this shared index ?????? */ + +#endif + + if (term_StampOverflow(sharing_StampID(SharedIndex))) + sharing_ResetAllTermStamps(SharedIndex); + + term_StartStamp(); + + Result = sharing_InternGetDataList(Term); + + term_StopStamp(); + + return Result; +} + + +static LIST sharing_InternGetDataList(TERM Term) +/********************************************************** + INPUT: A shared term. + RETURNS: The list of data connected to all superterms of Term + EFFECT: Allocates memory for the returned list. +********************************************************/ +{ + if (term_IsAtom(Term)) + /* We are at top level of the superterm "tree", */ + /* so the recursion stops here */ + return list_Copy(term_AtomsLiterals(Term)); + else{ + LIST SuperList; + LIST DataList = list_Nil(); + + for (SuperList = term_SupertermList(Term); !list_Empty(SuperList); + SuperList = list_Cdr(SuperList)) { + TERM superterm = (TERM) list_Car(SuperList); + if (!term_AlreadyVisited(superterm)) { + DataList = list_Nconc(sharing_InternGetDataList(superterm), DataList); + term_SetTermStamp(superterm); + } + } + return DataList; + } +} + + +void sharing_StartDataIterator(TERM Term, SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A shared term and the shared index it belongs to. + RETURNS: Nothing. + EFFECT: Prepares the data iterator for Term. + After this call you can access single data items + for Term with function sharing_GetNextData. +********************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(Term) || (SharedIndex == NULL)){ + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_StartDataIterator: Illegal input.\n"); + misc_FinishErrorReport(); + } + if (sharing_DATABLOCKED) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_StartDataIterator: Data iterator already used.\n"); + misc_FinishErrorReport(); + } + sharing_DATABLOCKED = TRUE; +#endif + + if (term_StampOverflow(sharing_StampID(SharedIndex))) + sharing_ResetAllTermStamps(SharedIndex); + term_StartStamp(); + + /* Init stack */ + sharing_STACKPOINTER = sharing_STACK; /* Pop all items */ + while (!term_IsAtom(Term)) { + /* Push superterm list on stack */ + *(sharing_STACKPOINTER++) = term_SupertermList(Term); + Term = list_Car(term_SupertermList(Term)); + } + + sharing_DATALIST = term_AtomsLiterals(Term); +} + + +POINTER sharing_GetNextData(void) +/********************************************************** + INPUT: None + RETURNS: A single data item connected to the term specified + in the previous call of sharing_StartDataIterator. + NULL is returned, if all data items were accessed before. + EFFECT: In contrast to function sharing_GetDataList + no memory is allocated. +********************************************************/ +{ + POINTER Result = NULL; + LIST superlist; + +#ifdef CHECK + if (!sharing_DATABLOCKED) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_GetNextData: Iterator wasn't started.\n"); + misc_FinishErrorReport(); + } +#endif + + if (!list_Empty(sharing_DATALIST)) { + Result = list_Car(sharing_DATALIST); + sharing_DATALIST = list_Cdr(sharing_DATALIST); + } else { + superlist = NULL; + while ((sharing_STACKPOINTER > sharing_STACK) && /* stack not empty */ + list_Empty(superlist)) { + /* change between backtracking and expansion */ + do { /* Backtracking */ + superlist = *(--sharing_STACKPOINTER); /* PopResult */ + term_SetTermStamp(list_Car(superlist)); + do + superlist = list_Cdr(superlist); + while (!list_Empty(superlist) && + term_AlreadyVisited(list_Car(superlist))); + } while ((sharing_STACKPOINTER>sharing_STACK) && list_Empty(superlist)); + while (!list_Empty(superlist) && + !term_IsAtom(list_Car(superlist))) { /* Expansion */ + *(sharing_STACKPOINTER++) = superlist; + superlist = term_SupertermList(list_Car(superlist)); + /* Search next unvisited term */ + while (!list_Empty(superlist) && + term_AlreadyVisited(list_Car(superlist))) + superlist = list_Cdr(superlist); + } + } + if (!list_Empty(superlist)) { + *(sharing_STACKPOINTER++) = superlist; + sharing_DATALIST = term_AtomsLiterals(list_Car(superlist)); + Result = list_Car(sharing_DATALIST); + sharing_DATALIST = list_Cdr(sharing_DATALIST); + } + } /* else */ + return Result; +} + + +void sharing_StopDataIterator(void) +/********************************************************** + INPUT: None. + RETURNS: Nothing. + EFFECT: The data iterator is stopped for the term you specified + in the corresponding call of sharing_StartDataIterator. +********************************************************/ +{ +#ifdef CHECK + if (!sharing_DATABLOCKED) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_StopDataIterator: Iterator wasn't started.\n"); + misc_FinishErrorReport(); + } + sharing_DATABLOCKED = FALSE; +#endif + sharing_DATALIST = list_Nil(); + term_StopStamp(); +} + + +LIST sharing_NAtomDataList(TERM Atom) +/********************************************************** + INPUT: A shared term. + RETURNS: A List of data connected with 'Term' or superterms. + EFFECT: No memory Allocation + CAUTION: THE RETURNED LIST MUST NOT CHANGE +**********************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(Atom) || !term_IsAtom(Atom)){ + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_NAtomDataList: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + return(term_AtomsLiterals(Atom)); +} + + +LIST sharing_GetAllSuperTerms(SHARED_INDEX Index) +/********************************************************** + INPUT: A shared Index. + RETURNS: A List of all Data in the shared Index. + EFFECT: The term stamp is used. +**********************************************************/ +{ + int i; + LIST Result = list_Nil(); + TERM term; + + if (term_StampOverflow(sharing_StampID(Index))) + sharing_ResetAllTermStamps(Index); + term_StartStamp(); + + for (i = 0; i < symbol_MaxVars(); i++) { + term = sharing_VartableEntry(Index,i); + if (term != NULL) + Result = list_Nconc(sharing_InternGetDataList(term), Result); + } + + for (i = 0; i < symbol_MaxConsts(); i++) { + term = sharing_ConsttableEntry(Index,i); + if (term != NULL) + Result = list_Nconc(sharing_InternGetDataList(term), Result); + } + + term_StopStamp(); + + return Result; +} + + +void sharing_ResetAllTermStamps(SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A shared index. + RETURNS: Nothing. + EFFECT: The stamps of all terms in the shared index are reset. +**********************************************************/ +{ + TERM term; + int i; + + /* Reset stamp for all variables and their superterms */ + for (i = 0; i < symbol_MaxVars(); i++) { + term = sharing_VartableEntry(SharedIndex, i); + if (term != NULL) + sharing_ResetTermStamp(term); + } + + /* Reset stamp for all constants and their superterms */ + for (i = 0; i < symbol_MaxConsts(); i++){ + term = sharing_ConsttableEntry(SharedIndex, i); + if (term != NULL) + sharing_ResetTermStamp(term); + } +} + + +static void sharing_ResetTermStamp(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: Nothing. + EFFECT: The stamps of Term and all its superterms are reset. +**********************************************************/ +{ + LIST SuperList; + TERM SuperTerm; + + if (!term_IsAtom(Term)) { + for (SuperList = term_SupertermList(Term); !list_Empty(SuperList); + SuperList = list_Cdr(SuperList)) { + SuperTerm = (TERM) list_Car(SuperList); + if (!term_StampAlreadyReset(SuperTerm)) { + sharing_ResetTermStamp(SuperTerm); + term_ResetTermStamp(SuperTerm); + } + } + } +} + + +NAT sharing_GetNumberOfOccurances(TERM Term) +/************************************************************** + INPUT: A shared (!) term. + RETURNS: How many literals contain <Term>. + Note that literals containing <Term> <n> times are counted + <n> times. +***************************************************************/ +{ + if (term_IsAtom(Term)) + /* Stop recursion */ + return list_Length(term_AtomsLiterals(Term)); + else { + LIST Scan; + NAT Result; + + Result = 0; + for (Scan = term_SupertermList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) + Result += sharing_GetNumberOfOccurances(list_Car(Scan)); + + return Result; + } +} + + +NAT sharing_GetNumberOfInstances(TERM Term, SHARED_INDEX Index) +/************************************************************** + INPUT: A (!) shared term and a shared index. The term has to be + part of the index. + RETURNS: How many literals within the index contain an instance of <Term>. + Note that literals containing <n> instances of <Term> + are counted <n> times. +***************************************************************/ +{ + NAT Result; + TERM Instance; + + Result = 0; + Instance = st_ExistInstance(cont_LeftContext(), sharing_Index(Index), Term); + while (Instance != NULL) { + Result += sharing_GetNumberOfOccurances(Instance); + Instance = st_NextCandidate(); + } + return Result; +} + + +/**************************************************************/ +/* Output functions for the sharing structure. */ +/**************************************************************/ + +void sharing_PrintVartable(SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A shared index. + RETURNS: Nothing. + EFFECT: Prints the Vartable entries to stdout +**********************************************************/ +{ + int i; + + for (i = 0; i < symbol_MaxVars(); i++){ + if (sharing_VartableEntry(SharedIndex, i) != NULL){ + printf("\n X%d : ", i); + + term_Print(sharing_VartableEntry(SharedIndex, i)); + } + } +} + + +void sharing_PrintConsttable(SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A shared index. + RETURNS: Nothing. + EFFECT: Prints the Consttable entries to stdout +**********************************************************/ +{ + int i; + + for (i = 0; i < symbol_MaxConsts(); i++){ + if (sharing_ConsttableEntry(SharedIndex, i) != NULL){ + printf("\n c%d : ", i); + + term_Print(sharing_ConsttableEntry(SharedIndex, i)); + } + } +} + + +void sharing_PrintSharingConstterms1(SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A shared index. + RETURNS: Nothing. + EFFECT: Prints all terms from the Consttable and their + direct superterms to stdout +**********************************************************/ +{ + TERM term; + int i; + + for (i = 0; i < symbol_MaxConsts(); i++) { + term = sharing_ConsttableEntry(SharedIndex, i); + if (term != NULL){ + printf("\n c%d : ", i); + term_Print(term); + puts(" has the direct superterms : "); + term_TermListPrint(term_SupertermList(term)); + } + } +} + + +void sharing_PrintSharingVarterms1(SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A shared index. + RETURNS: Nothing. + EFFECT: Prints all terms from the Vartable and their + superterms to stdout +**********************************************************/ +{ + TERM term; + int i; + + for (i = 0; i < symbol_MaxVars(); i++) { + term = sharing_VartableEntry(SharedIndex, i); + if (term != NULL){ + printf("\n x%d : ", i); + term_Print(term); + puts(" has the direct superterms : "); + term_TermListPrint(term_SupertermList(term)); + } + } +} + + +static void sharing_PrintWithSuperterms(TERM Term) +/********************************************************** + INPUT: A Term + RETURNS: Nothing. + EFFECT: Prints all Superterms of 'Term' from the sharing + to stdout. +**********************************************************/ +{ + + LIST HelpList; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sharing_PrintWithSuperterms: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if (term_IsAtom(Term)) { + term_Print(Term); + putchar('\n'); + } + else{ + term_Print(Term); + HelpList = term_SupertermList(Term); + if (!list_Empty(HelpList)){ + putchar('['); + term_TermListPrint(HelpList); + puts("]"); + while (!list_Empty(HelpList)){ + sharing_PrintWithSuperterms(list_Car(HelpList)); + HelpList = list_Cdr(HelpList); + } + } + } +} + + +void sharing_PrintSharing(SHARED_INDEX SharedIndex) +/********************************************************** + INPUT: A shared Index. + EFFECT: Prints the sharing to standard.out. +**********************************************************/ +{ + int i; + + for (i = 0; i < symbol_MaxConsts(); i++){ + if (sharing_ConsttableEntry(SharedIndex, i) != NULL){ + sharing_PrintWithSuperterms(sharing_ConsttableEntry(SharedIndex, i)); + puts("\n"); + } + } + puts("------------------------"); + for (i = 0; i < symbol_MaxVars(); i++){ + if (sharing_VartableEntry(SharedIndex, i) != NULL){ + sharing_PrintWithSuperterms(sharing_VartableEntry(SharedIndex, i)); + puts("\n"); + } + } +} + + +void sharing_PrintSameLevelTerms(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: Nothing. + EFFECT: Prints all terms, that share any of 'Term's args to + standard.out. +**********************************************************/ +{ + LIST HelpList; + + HelpList = term_ArgumentList(Term); + + while (!list_Empty(HelpList)){ + if (!list_Empty(term_SupertermList(list_First(HelpList)))) + term_TermListPrint(term_SupertermList(list_First(HelpList))); + + HelpList = list_Cdr(HelpList); + } +} + +void sharing_PrintStack(void) +/********************************************************** + INPUT: None. + RETURNS: Nothing. + EFFECT: Prints the internal sharing stack for iterative + queries. Only for debugging purposes. +**********************************************************/ +{ + TERM term; + LIST* ptr = sharing_STACKPOINTER; + + while (ptr > sharing_STACK) { + ptr--; + term = list_Car(*ptr); + term_Print(term); + putchar('\n'); + } +} + + diff --git a/test/spass/sharing.h b/test/spass/sharing.h new file mode 100644 index 0000000000000000000000000000000000000000..d4f5d7e1dd6d2fb2d98e30b9c556da5f61756b41 --- /dev/null +++ b/test/spass/sharing.h @@ -0,0 +1,245 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * STRUCTURE SHARING * */ +/* * * */ +/* * $Module: SHARING * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _SHARING_ +#define _SHARING_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "term.h" +#include "st.h" + +/**************************************************************/ +/* Data Structures and Constants */ +/**************************************************************/ + +/* Symbol Tables; constants are just positive */ +/* integers and variables negative integers. */ +/* For constants and vars is a special symbol */ +/* table available, containing the sharing */ +/* info, i.e. a POINTER to the term structure, if */ +/* the symbol is already inserted in the sharing */ +/* structure, a NULL Pointer else. */ + +typedef TERM VARTABLE[symbol__MAXVARIABLES]; + +typedef TERM CONSTTABLE[symbol__MAXSIGNATURE]; + +typedef struct { + st_INDEX index; + VARTABLE vartable; + CONSTTABLE consttable; + NAT stampId; +} SHARED_INDEX_NODE, *SHARED_INDEX; + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +static __inline__ st_INDEX sharing_Index(SHARED_INDEX ShIndex) +{ + return ShIndex->index; +} + +static __inline__ void sharing_SetIndex(SHARED_INDEX ShIndex, st_INDEX ST) +{ + ShIndex->index = ST; +} + +static __inline__ const TERM* sharing_Vartable(SHARED_INDEX ShIndex) +{ + return ShIndex->vartable; +} + +static __inline__ const TERM* sharing_Consttable(SHARED_INDEX ShIndex) +{ + return ShIndex->consttable; +} + +static __inline__ NAT sharing_StampID(SHARED_INDEX ShIndex) +{ + return ShIndex->stampId; +} + +static __inline__ void sharing_SetStampID(SHARED_INDEX ShIndex, NAT Stamp) +{ + ShIndex->stampId = Stamp; +} + +static __inline__ TERM sharing_VartableEntry(SHARED_INDEX ShIndex, NAT Index) +{ + return ShIndex->vartable[Index]; +} + +static __inline__ void sharing_SetVartableEntry(SHARED_INDEX ShIndex, + NAT Index, TERM Term) +{ + ShIndex->vartable[Index] = Term; +} + +static __inline__ TERM sharing_ConsttableEntry(SHARED_INDEX ShIndex, + NAT Index) +{ + return ShIndex->consttable[Index]; +} + +static __inline__ void sharing_SetConsttableEntry(SHARED_INDEX ShIndex, + NAT Index, TERM Term) +{ + ShIndex->consttable[Index] = Term; +} + +static __inline__ TERM sharing_GetVarFromSymbol(SYMBOL S, SHARED_INDEX ShIndex) +{ + return sharing_VartableEntry(ShIndex, symbol_VarIndex(S)); +} + +static __inline__ int sharing_VariableIndex(TERM Term) +{ + return symbol_VarIndex(term_TopSymbol(Term)); +} + +static __inline__ int sharing_ConstantIndex(TERM Term) +{ + return symbol_Index(term_TopSymbol(Term)); +} + +static __inline__ BOOL sharing_IsSharedVar(TERM T, SHARED_INDEX ShIndex) +/* RETURNS: True if there's already an entry for the variable T */ +/* in the Vartable of the shared index ShIndex. */ +{ + return sharing_VartableEntry(ShIndex, sharing_VariableIndex(T)) != NULL; +} + +static __inline__ BOOL sharing_IsSharedConst(TERM T, SHARED_INDEX ShIndex) +/* True if there's already an entry for the constant T */ +/* in the Consttable of the shared index ShIndex. */ +{ + return sharing_ConsttableEntry(ShIndex, sharing_ConstantIndex(T)) != NULL; +} + +static __inline__ BOOL sharing_IsNotReallyShared(TERM Term) +/* Der einzige Superterm ist der in dem ich loesche */ +{ + return list_Length(term_SupertermList(Term)) <= 1; +} + +static __inline__ void sharing_RememberSharedTermCopy(TERM Term, TERM Copy) +/* The unshared term Term has now a link to its shared copy */ +{ + term_RplacSuperterm(Term, Copy); +} + +static __inline__ TERM sharing_SharedTermCopy(TERM Term) +/* Return the shared copy of the unshared term Term */ +{ + return term_Superterm(Term); +} + + +/**************************************************************/ +/* Functions for Creation and Deletion of a SHARED_INDEX */ +/**************************************************************/ + +SHARED_INDEX sharing_IndexCreate(void); +void sharing_IndexDelete(SHARED_INDEX); + +/**************************************************************/ +/* Functions on term insertion and deletion. */ +/**************************************************************/ + +TERM sharing_Insert(POINTER, TERM, SHARED_INDEX); +void sharing_Delete(POINTER, TERM, SHARED_INDEX); + +void sharing_PushOnStack(TERM); +void sharing_PushReverseOnStack(TERM); +void sharing_PushOnStackNoStamps(TERM); +void sharing_PushListOnStack(LIST); +void sharing_PushListReverseOnStack(LIST); +void sharing_PushListReverseOnStackExcept(LIST, LIST); +void sharing_PushListOnStackNoStamps(LIST); + +/**************************************************************/ +/* Functions to access unshared data by the shared terms. */ +/**************************************************************/ + +LIST sharing_GetDataList(TERM, SHARED_INDEX); + +void sharing_StartDataIterator(TERM, SHARED_INDEX); +POINTER sharing_GetNextData(void); +void sharing_StopDataIterator(void); + +LIST sharing_NAtomDataList(TERM); +LIST sharing_GetAllSuperTerms(SHARED_INDEX); + +void sharing_ResetAllTermStamps(SHARED_INDEX); + +NAT sharing_GetNumberOfOccurances(TERM); +NAT sharing_GetNumberOfInstances(TERM, SHARED_INDEX); + +/**************************************************************/ +/* Output functions */ +/**************************************************************/ + +void sharing_PrintVartable(SHARED_INDEX); +void sharing_PrintConsttable(SHARED_INDEX); +void sharing_PrintSharing(SHARED_INDEX); + +/**************************************************************/ +/* Debugging Functions */ +/**************************************************************/ + +void sharing_PrintStack(void); +void sharing_PrintSharingConstterms1(SHARED_INDEX); +void sharing_PrintSharingVarterms1(SHARED_INDEX); +void sharing_PrintSameLevelTerms(TERM); + + +#endif + diff --git a/test/spass/small_problem.dfg b/test/spass/small_problem.dfg new file mode 100644 index 0000000000000000000000000000000000000000..f0b1a6d1b1445e428f61f4c967ca992470793085 --- /dev/null +++ b/test/spass/small_problem.dfg @@ -0,0 +1,154 @@ +%------------------------------------------------------------------------------ +% File : SET002+4 : TPTP v3.1.0. Released v2.2.0. +% Domain : Set Theory (Naive) +% Problem : Idempotency of union +% Version : [Pas99] axioms. +% English : + +% Refs : [Pas99] Pastre (1999), Email to G. Sutcliffe +% Source : [Pas99] +% Names : + +% Status : Theorem +% Rating : 0.36 v3.1.0, 0.56 v2.7.0, 0.33 v2.6.0, 0.57 v2.5.0, 0.50 v2.4.0, 0.25 v2.3.0, 0.00 v2.2.1 +% Syntax : Number of formulae : 12 ( 2 unit) +% Number of atoms : 30 ( 3 equality) +% Maximal formula depth : 7 ( 5 average) +% Number of connectives : 20 ( 2 ~ ; 2 |; 4 &) +% ( 10 <=>; 2 =>; 0 <=) +% ( 0 <~>; 0 ~|; 0 ~&) +% Number of predicates : 4 ( 0 propositional; 2-2 arity) +% Number of functors : 9 ( 1 constant; 0-2 arity) +% Number of variables : 29 ( 0 singleton; 28 !; 1 ?) +% Maximal term depth : 2 ( 1 average) + +% Comments : +% : tptp2X -f dfg -t rm_equality:rstfp SET002+4.p +%------------------------------------------------------------------------------ + +begin_problem(TPTP_Problem). + +list_of_descriptions. +name({*[ File : SET002+4 : TPTP v3.1.0. Released v2.2.0.],[ Names :]*}). +author({*[ Source : [Pas99]]*}). +status(unknown). +description({*[ Refs : [Pas99] Pastre (1999), Email to G. Sutcliffe]*}). +end_of_list. + +list_of_symbols. +functions[(difference,2), (empty_set,0), (intersection,2), (power_set,1), (product,1), (singleton,1), (sum,1), (union,2), (unordered_pair,2)]. +predicates[(equal_set,2), (member,2), (subset,2)]. +end_of_list. + +list_of_formulae(axioms). + +formula( + forall([A,B], + equiv( + subset(A,B), + forall([X], + implies( + member(X,A), + member(X,B))))), +subset ). + +formula( + forall([A,B], + equiv( + equal_set(A,B), + and( + subset(A,B), + subset(B,A)))), +equal_set ). + +formula( + forall([X,A], + equiv( + member(X,power_set(A)), + subset(X,A))), +power_set ). + +formula( + forall([X,A,B], + equiv( + member(X,intersection(A,B)), + and( + member(X,A), + member(X,B)))), +intersection ). + +formula( + forall([X,A,B], + equiv( + member(X,union(A,B)), + or( + member(X,A), + member(X,B)))), +union ). + +formula( + forall([X], + not( + member(X,empty_set))), +empty_set ). + +formula( + forall([B,A,E], + equiv( + member(B,difference(E,A)), + and( + member(B,E), + not( + member(B,A))))), +difference ). + +formula( + forall([X,A], + equiv( + member(X,singleton(A)), + equal(X,A))), +singleton ). + +formula( + forall([X,A,B], + equiv( + member(X,unordered_pair(A,B)), + or( + equal(X,A), + equal(X,B)))), +unordered_pair ). + +formula( + forall([X,A], + equiv( + member(X,sum(A)), + exists([Y], + and( + member(Y,A), + member(X,Y))))), +sum ). + +formula( + forall([X,A], + equiv( + member(X,product(A)), + forall([Y], + implies( + member(Y,A), + member(X,Y))))), +product ). + +end_of_list. + +%----NOTE WELL: conjecture has been negated +list_of_formulae(conjectures). + +formula( %(conjecture) + forall([A], + equal_set(union(A,A),A)), +thI14 ). + +end_of_list. + +end_problem. +%------------------------------------------------------------------------------ diff --git a/test/spass/sort.c b/test/spass/sort.c new file mode 100644 index 0000000000000000000000000000000000000000..e109ef1323b8d3cf42b0c44ab677ef89ac1de596 --- /dev/null +++ b/test/spass/sort.c @@ -0,0 +1,1974 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SORTED REASONING * */ +/* * * */ +/* * $Module: SORT * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "sort.h" + +/**************************************************************/ +/* Global Variables */ +/**************************************************************/ + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * HIGH LEVEL FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +void sort_Delete(SORT Sort) +/************************************************************** + INPUT: A sort. + RETURNS: Nothing. + MEMORY: The memory of the sort is freed. +***************************************************************/ +{ + list_Delete(Sort); +} + +BOOL sort_Eq(SORT S1, SORT S2) +/************************************************************** + INPUT: Two sorts. + RETURNS: TRUE iff the sorts <S1> and <S2> are the same base + sort intersection +***************************************************************/ +{ + LIST Scan1,Scan2; + BOOL Found; + +#ifdef CHECK + if (!sort_IsSort(S1) || !sort_IsSort(S2)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sort_Eq :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if (list_Length(S1) != list_Length(S2)) + return FALSE; + + for (Scan1=S1; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { + Found = FALSE; + for (Scan2=S2; !list_Empty(Scan2) && !Found; Scan2=list_Cdr(Scan2)) + Found = sort_NodeEqual(list_Car(Scan1),list_Car(Scan2)); + if (!Found) + return FALSE; + } + + return TRUE; +} + + +LIST sort_GetSymbolsFromSort(SORT Sort) +/************************************************************** + INPUT: A sort. + RETURNS: The list of sort symbols.. +***************************************************************/ +{ + LIST result = list_Nil(); + + for ( ; !list_Empty(Sort); Sort = list_Cdr(Sort)) + result = list_Cons((POINTER)sort_NodeSymbol(list_Car(Sort)), result); + + return result; +} + +BOOL sort_ContainsSymbol(SORT Sort, SYMBOL Symbol) +/************************************************************** + INPUT: A sort and a symbol. + RETURNS: TRUE, if the sort contains the symbol, FALSE otherwise. +***************************************************************/ +{ + for ( ; !list_Empty(Sort); Sort = list_Cdr(Sort)) + if (symbol_Equal(sort_NodeSymbol(list_Car(Sort)), Symbol)) + return TRUE; + + return FALSE; +} + +BOOL sort_IsSort(SORT Sort) +/************************************************************** + INPUT: A sort. + RETURNS: TRUE, if the sort contains not more than one node. +***************************************************************/ +{ + LIST Scan1,Scan2; + + for (Scan1=Sort ; !list_Empty(Scan1); Scan1 = list_Cdr(Scan1)) + for (Scan2=list_Cdr(Scan1) ; !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) + if (sort_NodeEqual(list_Car(Scan1),list_Car(Scan2))) + return FALSE; + + return TRUE; +} + +BOOL sort_TheorySortEqual(SORTTHEORY Theory, SORT Sort1, SORT Sort2) +/************************************************************** + INPUT: + RETURNS: +***************************************************************/ +{ + LIST Scan; + + if (list_Length(Sort1) != list_Length(Sort2)) + return FALSE; + + sort_TheoryIncrementMark(Theory); + + for (Scan=Sort1; !list_Empty(Scan); Scan=list_Cdr(Scan)) + sort_PutNodeExtraTrue(Theory,list_Car(Scan)); + for (Scan=Sort2; !list_Empty(Scan); Scan=list_Cdr(Scan)) + if (!sort_NodeExtraValue(Theory,list_Car(Scan))) + return FALSE; + + return TRUE; +} + +static BOOL sort_TheorySortMember(SORTTHEORY Theory, LIST List, SORT Sort) +/************************************************************** + INPUT: + RETURNS: +***************************************************************/ +{ + while (!list_Empty(List)) { + if (sort_TheorySortEqual(Theory,list_Car(List),Sort)) + return TRUE; + List = list_Cdr(List); + } + return FALSE; +} + + +void sort_DeleteSortPair(SOJU Pair) +/************************************************************** + INPUT: + RETURNS: Nothing. +***************************************************************/ +{ + sort_DeleteOne(sort_PairSort(Pair)); + sort_ConditionDelete(sort_PairCondition(Pair)); + list_PairFree(Pair); +} + + + +static void sort_ConditionPrint(CONDITION Cond) +/************************************************************** + INPUT: + RETURNS: Nothing. +***************************************************************/ +{ + LIST Scan; + + symbol_Print(sort_ConditionVar(Cond)); + for (Scan=sort_ConditionConstraint(Cond);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + putchar(','); + term_PrintPrefix(list_Car(Scan)); + } + for (Scan=sort_ConditionAntecedent(Cond);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + putchar(','); + term_PrintPrefix(list_Car(Scan)); + } + for (Scan=sort_ConditionSuccedent(Cond);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + putchar(','); + term_PrintPrefix(list_Car(Scan)); + } + for (Scan=sort_ConditionClauses(Cond);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + printf(",%d",clause_Number(list_Car(Scan))); + } +} + +static void sort_LinkPrint(SLINK Link) +/************************************************************** + INPUT: + RETURNS: Nothing. +***************************************************************/ +{ + LIST Scan; + + fputs("Input: (", stdout); + for (Scan=sort_LinkInput(Link);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + symbol_Print(sort_NodeSymbol(list_Car(Scan))); + if (!list_Empty(list_Cdr(Scan))) + putchar(','); + } + fputs(") Output: ", stdout); + symbol_Print(sort_NodeSymbol(sort_LinkOutput(Link))); + fputs(" C: (", stdout); + for (Scan=sort_LinkConstraint(Link);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + term_PrintPrefix(list_Car(Scan)); + if (!list_Empty(list_Cdr(Scan))) + putchar(','); + } + fputs(") A: (", stdout); + for (Scan=sort_LinkAntecedent(Link);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + term_PrintPrefix(list_Car(Scan)); + if (!list_Empty(list_Cdr(Scan))) + putchar(','); + } + fputs(") S: (", stdout); + for (Scan=sort_LinkSuccedent(Link);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + term_PrintPrefix(list_Car(Scan)); + if (!list_Empty(list_Cdr(Scan))) + putchar(','); + } + printf(") Clause: %d Card: %d Fire: %d Var: ", clause_Number(sort_LinkClause(Link)), sort_LinkCard(Link), + sort_LinkFire(Link)); + symbol_Print(sort_LinkVar(Link)); +} + + + +void sort_PairPrint(SOJU Pair) +/************************************************************** + INPUT: + RETURNS: Nothing. +***************************************************************/ +{ + sort_Print(sort_PairSort(Pair)); + fputs(":[", stdout); + sort_ConditionPrint(sort_PairCondition(Pair)); + putchar(']'); +} + + +static NODE sort_NodeCreate(SYMBOL S) +/************************************************************** + INPUT: A sort symbol. + RETURNS: A new initialized sort node for the symbol <S>. +***************************************************************/ +{ + NODE Result; + + Result = (NODE)memory_Malloc(sizeof(NODE_NODE)); + + sort_PutNodeLinks(Result, list_Nil()); + sort_PutNodeConditions(Result, list_Nil()); + sort_PutNodeMark(Result, 0); + sort_PutNodeStart(Result, 0); + sort_PutNodeExtra(Result, 0); + sort_PutNodeSymbol(Result, S); + + return Result; +} + +BOOL sort_NodeIsTop(SORTTHEORY Theory, NODE Node) +/************************************************************** + INPUT: A sort theory and a node. + RETURNS: TRUE if the Node is declared to be equivalent to the + top sort. +***************************************************************/ +{ + LIST Scan; + SLINK Link; + + for (Scan=sort_TheorySuborigcls(Theory);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Link = (SLINK)list_Third(list_Car(Scan)); + if (list_Empty(sort_LinkInput(Link)) && Node == sort_LinkOutput(Link)) + return TRUE; + } + return FALSE; +} + + +static SLINK sort_TheoryLinkCreate(SORTTHEORY Theory, CLAUSE Origin, + CLAUSE Clause, LITERAL Lit) +/************************************************************** + INPUT: A sort theory, a clause its origin and a subsort declaration + literal in the clause + RETURNS: A new link in <Theory> origin <Clause> and subsort declaration <Lit> +***************************************************************/ +{ + SLINK Result; + SYMBOL Output,Var,Max; + int i; + LIST Input, Antecedent, Succedent, Constraint; + TERM Term; + + Result = (SLINK)memory_Malloc(sizeof(SLINK_NODE)); + + Output = term_TopSymbol(clause_LiteralSignedAtom(Lit)); + Var = term_TopSymbol(term_FirstArgument(clause_LiteralSignedAtom(Lit))); + Input = Antecedent = Succedent = Constraint = list_Nil(); + Max = clause_MaxVar(Clause); + term_StartMaxRenaming(Max); + Max = symbol_CreateStandardVariable(); + + for (i = clause_FirstConstraintLitIndex(Clause); + i <= clause_LastConstraintLitIndex(Clause); i++) + if (symbol_Equal(Var,term_TopSymbol(term_FirstArgument(clause_GetLiteralAtom(Clause,i))))) + Input = list_Cons(sort_TheoryNode(Theory,term_TopSymbol(clause_GetLiteralAtom(Clause,i))), + Input); + else { + Term = term_Copy(clause_GetLiteralTerm(Clause,i)); + term_ExchangeVariable(Term,Var,Max); + Constraint = list_Cons(Term,Constraint); + } + + for (i = clause_FirstAntecedentLitIndex(Clause); + i <= clause_LastAntecedentLitIndex(Clause); i++) { + Term = term_Copy(clause_GetLiteralTerm(Clause,i)); + term_ExchangeVariable(Term,Var,Max); + Antecedent = list_Cons(Term,Antecedent); + } + + for (i = clause_FirstSuccedentLitIndex(Clause); + i <= clause_LastSuccedentLitIndex(Clause); i++) + if (clause_GetLiteral(Clause,i) != Lit) { + Term = term_Copy(clause_GetLiteralTerm(Clause,i)); + term_ExchangeVariable(Term,Var,Max); + Succedent = list_Cons(Term,Succedent); + } + + + sort_PutLinkInput(Result,Input); + sort_PutLinkOutput(Result,sort_TheoryNode(Theory,Output)); + sort_PutLinkVar(Result,Max); + sort_PutLinkConstraint(Result,Constraint); + sort_PutLinkAntecedent(Result,Antecedent); + sort_PutLinkSuccedent(Result,Succedent); + sort_PutLinkCard(Result,list_Length(Input)); + sort_LinkResetFire(Result); + sort_PutLinkClause(Result,Origin); + + while (!list_Empty(Input)) { + sort_PutNodeLinks(list_Car(Input),list_Cons(Result,sort_NodeLinks(list_Car(Input)))); + Input = list_Cdr(Input); + } + + return Result; +} + + +void sort_Init(void) +/************************************************************** + INPUT: None. + RETURNS: None. + SUMMARY: Initializes the sort Module. + EFFECTS: Initializes global variables, i.e. the BASESORT-Array. + CAUTION: MUST BE CALLED BEFORE ANY OTHER sort-FUNCTION. +***************************************************************/ +{ + return; +} + + +void sort_Print(SORT Sort) +/************************************************************** + INPUT: + RETURNS: Nothing. +***************************************************************/ +{ + putchar('('); + + while (!list_Empty(Sort)) { + symbol_Print(sort_NodeSymbol(list_Car(Sort))); + Sort = list_Cdr(Sort); + if (!list_Empty(Sort)) + putchar(','); + } + putchar(')'); +} + + +void sort_Free(void) +/************************************************************** + INPUT: None. + RETURNS: Nothing. + SUMMARY: Frees the sort Module. +***************************************************************/ +{ + return; +} + +SORTTHEORY sort_TheoryCreate(void) +/************************************************************** + INPUT: None. + RETURNS: A new sort theory. + EFFECT: A new sort theory is created and initialized. +***************************************************************/ +{ + SORTTHEORY Result; + int i; + SIGNATURE Entry; + SYMBOL Symbol; + + Result = (SORTTHEORY)memory_Malloc(sizeof(SORTTHEORY_NODE)); + + for (i = 1; i < symbol_ACTINDEX; i++) { + Result->basesorttable[i] = (NODE)NULL; + Entry = symbol_Signature(i); + if (Entry != NULL) { + Symbol = Entry->info; + if (symbol_IsPredicate(Symbol) && Entry->arity == 1) + Result->basesorttable[i] = sort_NodeCreate(Symbol); + } + } + + Result->index = st_IndexCreate(); + Result->suborigcls = list_Nil(); + Result->termorigcls = list_Nil(); + Result->mark = 0; + + return Result; +} + +void sort_TheoryPrint(SORTTHEORY Theory) +/************************************************************** + INPUT: A sort theory + RETURNS: None. + EFFECT: Prints the sort theory to stdout. +***************************************************************/ +{ + LIST Scan; + + if (Theory == (SORTTHEORY)NULL) { + fputs(" Empty Theory", stdout); + return; + } + + fputs("\n Subsort Clauses:", stdout); + for (Scan=sort_TheorySuborigcls(Theory);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + fputs("\n\t\t Clause:", stdout); + clause_Print(list_Second(list_Car(Scan))); + fputs("\n\t\t Link: ", stdout); + sort_LinkPrint(list_Third(list_Car(Scan))); + } + fputs("\n Term Declaration Clauses:", stdout); + for (Scan=sort_TheoryTermorigcls(Theory);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + fputs("\n\t\t Clause:", stdout); + clause_Print(list_Second(list_Car(Scan))); + } + +} + +void sort_TheoryDelete(SORTTHEORY Theory) +/************************************************************** + INPUT: A sort theory + RETURNS: None. + EFFECT: The complete sort theory is deleted. +***************************************************************/ +{ + if (Theory != (SORTTHEORY)NULL) { + int i; + LIST Scan,Tuple; + TERM Term, Atom; + + for (Scan=Theory->suborigcls;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Tuple = (LIST)list_Car(Scan); + sort_LinkDelete(list_Third(Tuple)); + clause_Delete(list_Second(Tuple)); + list_Delete(Tuple); + } + list_Delete(Theory->suborigcls); + for (Scan=Theory->termorigcls;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Tuple = (LIST)list_Car(Scan); + Term = (TERM)list_Third(Tuple); + Atom = (TERM)list_Car(term_SupertermList(Term)); + st_EntryDelete(Theory->index,Term,Term,cont_LeftContext()); + st_EntryDelete(Theory->index,Atom,Atom,cont_LeftContext()); + list_Delete(term_SupertermList(Atom)); + list_Delete(term_SupertermList(Term)); + term_RplacSupertermList(Term, list_Nil()); + term_RplacSupertermList(Atom, list_Nil()); + clause_Delete(list_Second(Tuple)); + list_Delete(Tuple); + } + list_Delete(Theory->termorigcls); + st_IndexDelete(Theory->index); + + for (i=1;i<symbol_ACTINDEX;i++) + if (Theory->basesorttable[i] != (NODE)NULL) + sort_NodeDelete(Theory->basesorttable[i]); + + memory_Free(Theory,sizeof(SORTTHEORY_NODE)); + } +} + +void sort_TheoryInsertClause(SORTTHEORY Theory, CLAUSE Origin, CLAUSE Clause, LITERAL L) +/************************************************************** + INPUT: A sort theory, two clauses and a declaration of the second clause. + <Origin> is the original clause and <Clause> is a possibly approximated + copy of <Origin>. + RETURNS: None. + EFFECT: Inserts <Clause> with declaration <L> into the sort theory. +***************************************************************/ +{ + TERM Term, Atom; + + Term = term_FirstArgument(clause_LiteralSignedAtom(L)); + + if (term_IsVariable(Term)) { + SLINK Link; + Link = sort_TheoryLinkCreate(Theory,Origin,Clause,L); + Theory->suborigcls = list_Cons(list_Cons(Origin,list_Cons(clause_Copy(Clause),list_List(Link))), + Theory->suborigcls); + } + + /* Since currently Sort Resolution and Empty Sort require the subsort declaration clauses */ + /* also subsort clauses are introduced into the sort theory index */ + + Atom = clause_LiteralSignedAtom(L); + term_RplacSupertermList(Atom, list_List(L)); + term_RplacSupertermList(Term, list_List(Atom)); /* Must be empty before this operation */ + st_EntryCreate(Theory->index,Term,Term,cont_LeftContext()); + st_EntryCreate(Theory->index,Atom,Atom,cont_LeftContext()); + Theory->termorigcls = list_Cons(list_Cons(Origin,list_Cons(Clause,list_List(Term))), + Theory->termorigcls); +} + +void sort_TheoryDeleteClause(SORTTHEORY Theory, CLAUSE Origin) +/************************************************************** + INPUT: A sort theory and a clause possibly inserted several times in the theory. + RETURNS: None. + EFFECT: <Origin> is deleted from the sort theory, but not deleted itself. +***************************************************************/ +{ + TERM Term,Atom; + LIST Scan,Tuple; + + for (Scan=Theory->suborigcls;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Tuple = list_Car(Scan); + if ((CLAUSE)list_First(Tuple) == Origin) { + list_Rplaca(Scan,NULL); + sort_LinkDelete(list_Third(Tuple)); + clause_Delete(list_Second(Tuple)); + list_Delete(Tuple); + } + } + Theory->suborigcls = list_PointerDeleteElement(Theory->suborigcls,NULL); + for (Scan=Theory->termorigcls;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Tuple = list_Car(Scan); + if ((CLAUSE)list_First(Tuple) == Origin) { + list_Rplaca(Scan,NULL); + Term = (TERM)list_Third(Tuple); + Atom = (TERM)list_Car(term_SupertermList(Term)); + st_EntryDelete(Theory->index,Term,Term,cont_LeftContext()); + st_EntryDelete(Theory->index,Atom,Atom,cont_LeftContext()); + list_Delete(term_SupertermList(Atom)); + list_Delete(term_SupertermList(Term)); + term_RplacSupertermList(Term, list_Nil()); + term_RplacSupertermList(Atom, list_Nil()); + clause_Delete(list_Second(Tuple)); + list_Delete(Tuple); + } + } + Theory->termorigcls = list_PointerDeleteElement(Theory->termorigcls,NULL); +} + +CONDITION sort_ConditionCreate(SYMBOL Var, LIST Constr, LIST Ante, LIST Succ, LIST Clauses) +/************************************************************** + INPUT: A variable, a list of constraint literals, antecedent literals, succedent literals + and a list of clauses. + RETURNS: The condition created from these arguments. + MEMORY: It is assumed that all literals are unshared whereas the clauses are shared. +***************************************************************/ +{ + CONDITION Result; + + Result = (CONDITION)memory_Malloc(sizeof(CONDITION_NODE)); + + sort_ConditionPutVar(Result, Var); + sort_ConditionPutConstraint(Result, Constr); + sort_ConditionPutAntecedent(Result, Ante); + sort_ConditionPutSuccedent(Result, Succ); + sort_ConditionPutClauses(Result, Clauses); + + return Result; +} + +CONDITION sort_ConditionNormalize(CONDITION Cond) +/************************************************************** + INPUT: A condition. + RETURNS: The normalized condition, i.e., the variables for the various + literals are normalized starting with the minimal variable. + EFFECT: Destructive. +***************************************************************/ +{ + LIST Scan; + SYMBOL Old,New; + + term_StartMinRenaming(); + for (Scan=sort_ConditionConstraint(Cond);!list_Empty(Scan);Scan=list_Cdr(Scan)) + term_Rename(list_Car(Scan)); + for (Scan=sort_ConditionAntecedent(Cond);!list_Empty(Scan);Scan=list_Cdr(Scan)) + term_Rename(list_Car(Scan)); + for (Scan=sort_ConditionSuccedent(Cond);!list_Empty(Scan);Scan=list_Cdr(Scan)) + term_Rename(list_Car(Scan)); + New = symbol_CreateStandardVariable(); + Old = term_GetRenamedVarSymbol(sort_ConditionVar(Cond)); + for (Scan=sort_ConditionConstraint(Cond);!list_Empty(Scan);Scan=list_Cdr(Scan)) + term_ExchangeVariable(list_Car(Scan),Old,New); + for (Scan=sort_ConditionAntecedent(Cond);!list_Empty(Scan);Scan=list_Cdr(Scan)) + term_ExchangeVariable(list_Car(Scan),Old,New); + for (Scan=sort_ConditionSuccedent(Cond);!list_Empty(Scan);Scan=list_Cdr(Scan)) + term_ExchangeVariable(list_Car(Scan),Old,New); + + sort_ConditionPutVar(Cond,New); + + return Cond; +} + +CONDITION sort_ConditionCreateNoResidues(LIST Clauses) +/************************************************************** + INPUT: A list of clauses. + RETURNS: The condition created just from the clauses. +***************************************************************/ +{ + CONDITION Result; + + Result = (CONDITION)memory_Malloc(sizeof(CONDITION_NODE)); + + sort_ConditionPutVar(Result, symbol_FirstVariable()); + sort_ConditionPutConstraint(Result, list_Nil()); + sort_ConditionPutAntecedent(Result, list_Nil()); + sort_ConditionPutSuccedent(Result, list_Nil()); + sort_ConditionPutClauses(Result, Clauses); + + return Result; +} + +CONDITION sort_ExtendConditionByLink(CONDITION Cond, SLINK Link) +/************************************************************** + INPUT: A condition and a link. + RETURNS: <Cond> extended by the clause, antecedent, constraint and succedent + literals of <Link> + EFFECT: <Cond> is destructively extended with <Link>. +***************************************************************/ +{ + LIST Lits,Antecedent,Succedent,Constraint; + SYMBOL Old,New; + + + term_StartMaxRenaming(sort_ConditionVar(Cond)); + Constraint = term_CopyTermList(sort_LinkConstraint(Link)); + Antecedent = term_CopyTermList(sort_LinkAntecedent(Link)); + Succedent = term_CopyTermList(sort_LinkSuccedent(Link)); + for (Lits=Constraint;!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + for (Lits=Antecedent;!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + for (Lits=Succedent;!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + Old = term_GetRenamedVarSymbol(sort_LinkVar(Link)); + New = symbol_CreateStandardVariable(); + for (Lits=Constraint;!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=Antecedent;!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=Succedent;!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + Old = sort_ConditionVar(Cond); + for (Lits=sort_ConditionConstraint(Cond);!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=sort_ConditionAntecedent(Cond);!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=sort_ConditionSuccedent(Cond);!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + sort_ConditionPutConstraint(Cond,list_Nconc(sort_ConditionConstraint(Cond),Constraint)); + sort_ConditionPutAntecedent(Cond,list_Nconc(sort_ConditionAntecedent(Cond),Antecedent)); + sort_ConditionPutSuccedent(Cond,list_Nconc(sort_ConditionSuccedent(Cond),Succedent)); + sort_ConditionPutClauses(Cond,list_Cons(sort_LinkClause(Link),sort_ConditionClauses(Cond))); + sort_ConditionPutVar(Cond,New); + sort_ConditionNormalize(Cond); + + return Cond; + +} + +CONDITION sort_ExtendConditionByCondition(CONDITION Cond, CONDITION Update) +/************************************************************** + INPUT: Two conditions. + RETURNS: <Cond> extended by the clauses, antecedent, constraint and succedent + literals of <Update> + EFFECT: <Cond> is destructively extended by <Update>. +***************************************************************/ +{ + LIST Lits,Antecedent,Succedent,Constraint; + SYMBOL Old,New; + + term_StartMaxRenaming(sort_ConditionVar(Cond)); + Constraint = term_CopyTermList(sort_ConditionConstraint(Update)); + Antecedent = term_CopyTermList(sort_ConditionAntecedent(Update)); + Succedent = term_CopyTermList(sort_ConditionSuccedent(Update)); + for (Lits=Constraint;!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + for (Lits=Antecedent;!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + for (Lits=Succedent;!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + Old = term_GetRenamedVarSymbol(sort_ConditionVar(Update)); + New = symbol_CreateStandardVariable(); + for (Lits=Constraint; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=Antecedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=Succedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + Old = sort_ConditionVar(Cond); + for (Lits=sort_ConditionConstraint(Cond);!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=sort_ConditionAntecedent(Cond);!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=sort_ConditionSuccedent(Cond);!list_Empty(Lits);Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + sort_ConditionPutConstraint(Cond,list_Nconc(sort_ConditionConstraint(Cond),Constraint)); + sort_ConditionPutAntecedent(Cond,list_Nconc(sort_ConditionAntecedent(Cond),Antecedent)); + sort_ConditionPutSuccedent(Cond,list_Nconc(sort_ConditionSuccedent(Cond),Succedent)); + sort_ConditionPutClauses(Cond,list_Nconc(list_Copy(sort_ConditionClauses(Update)), + sort_ConditionClauses(Cond))); + sort_ConditionPutVar(Cond,New); + sort_ConditionNormalize(Cond); + + return Cond; +} + +LIST sort_ExtendConditions(LIST Conditions, SLINK Link) +/************************************************************** + INPUT: A list of conditions and a link. + RETURNS: A new list of conditions augmented by the conditions in <Link>. +***************************************************************/ +{ + LIST Result,Scan,Antecedent,Succedent,Constraint; + CONDITION Cond; + + Result = list_Nil(); + + for (Scan=Conditions;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Cond = (CONDITION)list_Car(Scan); + Constraint = term_CopyTermList(sort_ConditionConstraint(Cond)); + Antecedent = term_CopyTermList(sort_ConditionAntecedent(Cond)); + Succedent = term_CopyTermList(sort_ConditionSuccedent(Cond)); + if (sort_LinkNoResidues(Link)) + Result = list_Cons(sort_ConditionCreate(sort_ConditionVar(Cond),Constraint,Antecedent, + Succedent,list_Cons(sort_LinkClause(Link), + list_Copy(sort_ConditionClauses(Cond)))), + Result); + else { + SYMBOL New,Old; + LIST NewAntecedent,NewSuccedent,NewConstraint,Lits; + term_StartMaxRenaming(sort_ConditionVar(Cond)); + NewConstraint = term_CopyTermList(sort_LinkConstraint(Link)); + NewAntecedent = term_CopyTermList(sort_LinkAntecedent(Link)); + NewSuccedent = term_CopyTermList(sort_LinkSuccedent(Link)); + for (Lits=NewConstraint; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + for (Lits=NewAntecedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + for (Lits=NewSuccedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + Old = term_GetRenamedVarSymbol(sort_LinkVar(Link)); + New = symbol_CreateStandardVariable(); + for (Lits=NewConstraint; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=NewAntecedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=NewSuccedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + Old = sort_ConditionVar(Cond); + for (Lits=Constraint; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=Antecedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=Succedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + Result = list_Cons(sort_ConditionNormalize(sort_ConditionCreate(New,list_Nconc(Constraint,NewConstraint), + list_Nconc(Antecedent,NewAntecedent), + list_Nconc(Succedent,NewSuccedent), + list_Cons(sort_LinkClause(Link), + list_Copy(sort_ConditionClauses(Cond))))), + Result); + } + } + return Result; +} + +CONDITION sort_ConditionsUnion(LIST Conditions) +/************************************************************** + INPUT: A list of conditions. + RETURNS: A new condition that is the union of all input conditions. +***************************************************************/ +{ + LIST Scan,Antecedent,Succedent,Constraint; + CONDITION Cond; + SYMBOL Act,New,Old; + LIST NewAntecedent,NewSuccedent,NewConstraint,NewClauses,Lits; + + if (list_Empty(Conditions)) + return sort_ConditionCreate(symbol_FirstVariable(),list_Nil(),list_Nil(),list_Nil(), + list_Nil()); + else { + Cond = (CONDITION)list_Car(Conditions); + Conditions = list_Cdr(Conditions); + Act = sort_ConditionVar(Cond); + NewConstraint = term_CopyTermList(sort_ConditionConstraint(Cond)); + NewAntecedent = term_CopyTermList(sort_ConditionAntecedent(Cond)); + NewSuccedent = term_CopyTermList(sort_ConditionSuccedent(Cond)); + NewClauses = list_Copy(sort_ConditionClauses(Cond)); + } + + for (Scan=Conditions;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Cond = (CONDITION)list_Car(Scan); + if (!sort_ConditionNoResidues(Cond)) { + Constraint = term_CopyTermList(sort_ConditionConstraint(Cond)); + Antecedent = term_CopyTermList(sort_ConditionAntecedent(Cond)); + Succedent = term_CopyTermList(sort_ConditionSuccedent(Cond)); + + term_StartMaxRenaming(Act); + for (Lits=Constraint; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + for (Lits=Antecedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + for (Lits=Succedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_Rename(list_Car(Lits)); + Old = term_GetRenamedVarSymbol(sort_ConditionVar(Cond)); + New = symbol_CreateStandardVariable(); + for (Lits=Constraint; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=Antecedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=Succedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Old,New); + for (Lits=NewConstraint; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Act,New); + for (Lits=NewAntecedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Act,New); + for (Lits=NewSuccedent; !list_Empty(Lits); Lits=list_Cdr(Lits)) + term_ExchangeVariable(list_Car(Lits),Act,New); + Act = New; + NewConstraint = list_Nconc(Constraint,NewConstraint); + NewAntecedent = list_Nconc(Antecedent,NewAntecedent); + NewSuccedent = list_Nconc(Succedent,NewSuccedent); + } + NewClauses = list_Nconc(list_Copy(sort_ConditionClauses(Cond)),NewClauses); + } + + return sort_ConditionNormalize(sort_ConditionCreate(Act,NewConstraint,NewAntecedent,NewSuccedent,NewClauses)); +} + +void sort_ConditionDelete(CONDITION C) +/************************************************************** + INPUT: A condition. + RETURNS: Nothing. + MEMORY: The condition and all literals and lists are deleted. +***************************************************************/ +{ + if (C!= (CONDITION)NULL) { + term_DeleteTermList(sort_ConditionConstraint(C)); + term_DeleteTermList(sort_ConditionAntecedent(C)); + term_DeleteTermList(sort_ConditionSuccedent(C)); + list_Delete(sort_ConditionClauses(C)); + + sort_ConditionFree(C); + } +} + + +CONDITION sort_ConditionCopy(CONDITION C) +/************************************************************** + INPUT: A condition. + RETURNS: A copy of the condition. +***************************************************************/ +{ + return sort_ConditionCreate(sort_ConditionVar(C), + term_CopyTermList(sort_ConditionConstraint(C)), + term_CopyTermList(sort_ConditionAntecedent(C)), + term_CopyTermList(sort_ConditionSuccedent(C)), + list_Copy(sort_ConditionClauses(C))); +} + + + +BOOL sort_IsBaseSortSymbol(SYMBOL Symbol) +/********************************************************* + INPUT: A Symbol. + RETURNS: The boolean value TRUE, if 'Symbol' is a + basesortsymbol, FALSE else. +*******************************************************/ +{ +#ifdef CHECK + if (!symbol_IsSymbol(Symbol)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sort_IsBaseSymbol :"); + misc_ErrorReport(" Illegal input. Input not a symbol.\n"); + misc_FinishErrorReport(); + } +#endif + + return(symbol_IsPredicate(Symbol) && symbol_Arity(Symbol) == 1); +} + + +SORT sort_TheorySortOfSymbol(SORTTHEORY Theory, SYMBOL Symbol) +/********************************************************* + INPUT: A sort theory and a base sort symbol. + RETURNS: The Basesort of 'Symbol'. +*******************************************************/ +{ +#ifdef CHECK + if (!sort_IsBaseSortSymbol(Symbol)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sort_TheorySortOfSymbol :"); + misc_ErrorReport(" Illegal input. Input not a symbol.\n"); + misc_FinishErrorReport(); + } +#endif + + return (list_List(sort_TheoryNode(Theory, Symbol))); +} + + +static void sort_EvalSubsortNoResidues(SORTTHEORY Theory, LIST Nodes) +/********************************************************* + INPUT: A sort theory and a list of nodes from this theory. + RETURNS: None. + EFFECT: Starting from the nodes in <Nodes> the subsort + graph is exploited as long as links fire and + new nodes become true. Only links without residues + are considered. +*******************************************************/ +{ + NODE Node,Head; + LIST Scan,Help,Clauses; + SLINK Link; + + while (!list_Empty(Nodes)) { + Node = (NODE)list_Car(Nodes); + Scan = Nodes; + Nodes = list_Cdr(Nodes); + list_Free(Scan); + + for (Scan = sort_NodeLinks(Node); + !list_Empty(Scan); + Scan = list_Cdr(Scan)) { + Link = (SLINK)list_Car(Scan); + if (sort_LinkNoResidues(Link) && sort_LinkDecrementFire(Link) == 0) { + Head = sort_LinkOutput(Link); + if (!sort_NodeValue(Theory, Head)) { + Clauses = list_List(sort_LinkClause(Link)); + for (Help=sort_LinkInput(Link);!list_Empty(Help);Help=list_Cdr(Help)) + if (!list_Empty(sort_NodeConditions(list_Car(Help)))) + Clauses = + list_Nconc(list_Copy(sort_ConditionClauses( + list_Car(sort_NodeConditions(list_Car(Help))))),Clauses); + sort_DeleteConditionList(sort_NodeConditions(Head)); + sort_PutNodeConditions(Head,list_List(sort_ConditionCreateNoResidues(Clauses))); + sort_PutNodeTrue(Theory, Head); + Nodes = list_Cons(Head,Nodes); + } + } + } + } +} + + +static BOOL sort_TestSubsortSpecial(SORTTHEORY Theory, LIST Nodes, LIST Goal) +/********************************************************* + INPUT: A sort theory and a list of nodes from this theory and + a list of goal nodes. + RETURNS: TRUE if we can walk from at least one node of <Nodes> over + a previously evaluated sort structure. +*******************************************************/ +{ + NODE Node,Head; + LIST Scan; + SLINK Link; + + while (!list_Empty(Nodes)) { + Node = (NODE)list_NCar(&Nodes); + if (list_PointerMember(Goal,Node)) { + list_Delete(Nodes); + return TRUE; + } + for (Scan = sort_NodeLinks(Node);!list_Empty(Scan);Scan = list_Cdr(Scan)) { + Link = (SLINK)list_Car(Scan); + if (sort_LinkFire(Link) == 0) { + Head = sort_LinkOutput(Link); + Nodes = list_Cons(Head,Nodes); + } + } + } + return FALSE; +} + +static void sort_EvalSubsortSpecial(SORTTHEORY Theory, LIST Nodes) +/********************************************************* + INPUT: A sort theory and a list of nodes from this theory. + RETURNS: None. + EFFECT: Starting from the nodes in <Nodes> the subsort + graph is exploited as long as links fire and + new nodes become true. Only links without residues + are considered. +*******************************************************/ +{ + NODE Node,Head; + LIST Scan; + SLINK Link; + + while (!list_Empty(Nodes)) { + Node = (NODE)list_NCar(&Nodes); + for (Scan = sort_NodeLinks(Node);!list_Empty(Scan);Scan = list_Cdr(Scan)) { + Link = (SLINK)list_Car(Scan); + if (sort_LinkDecrementFire(Link) == 0) { + Head = sort_LinkOutput(Link); + if (!sort_NodeValue(Theory, Head)) { + sort_PutNodeTrue(Theory, Head); + Nodes = list_Cons(Head,Nodes); + } + } + } + } +} + +static void sort_EvalSubsort(SORTTHEORY Theory, LIST Nodes) +/********************************************************* + INPUT: A sort theory and a list of nodes from this theory. + RETURNS: None. + EFFECT: Starting from the nodes in <Nodes> the subsort + graph is exploited as long as links fire and + new nodes become true. + Only ONE condition for each node becoming + valid is established. +*******************************************************/ +{ + NODE Node,Head; + LIST Scan,Help; + SLINK Link; + CONDITION Cond; + + while (!list_Empty(Nodes)) { + Node = (NODE)list_Car(Nodes); + Scan = Nodes; + Nodes = list_Cdr(Nodes); + list_Free(Scan); + + for (Scan = sort_NodeLinks(Node); + !list_Empty(Scan); + Scan = list_Cdr(Scan)) { + Link = (SLINK)list_Car(Scan); + if (sort_LinkDecrementFire(Link) == 0) { + Head = sort_LinkOutput(Link); + if (!sort_NodeValue(Theory, Head)) { + Cond = sort_ConditionCreate(symbol_FirstVariable(),list_Nil(),list_Nil(),list_Nil(),list_Nil()); + for (Help=sort_LinkInput(Link);!list_Empty(Help);Help=list_Cdr(Help)) + if (!list_Empty(sort_NodeConditions(list_Car(Help)))) + Cond = sort_ExtendConditionByCondition(Cond,list_Car(sort_NodeConditions(list_Car(Help)))); + sort_ExtendConditionByLink(Cond,Link); + sort_DeleteConditionList(sort_NodeConditions(Head)); + sort_PutNodeConditions(Head,list_List(Cond)); + sort_PutNodeTrue(Theory, Head); + Nodes = list_Cons(Head,Nodes); + } + } + } + } +} + + +CONDITION sort_TheoryIsSubsortOfNoResidues(SORTTHEORY Theory, SORT Sort1, SORT Sort2) +/********************************************************* + INPUT: A sort theory and two sorts. + RETURNS: A condition if <Sort1> is a subsort of <Sort2> and NULL otherwise. +*******************************************************/ +{ + LIST Scan,Clauses; + SLINK Link; + NODE Node; + SORT Top; + +#ifdef CHECK + if (!sort_IsSort(Sort1) || !sort_IsSort(Sort2)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sort_TheoryIsSubsortOfNoResidues :"); + misc_ErrorReport(" Illegal sort input.\n"); + misc_FinishErrorReport(); + } +#endif + + sort_TheoryIncrementMark(Theory); + + /*fputs("\n Subsort Test: ", stdout); + sort_Print(Sort1); + putchar(' '); + sort_Print(Sort2);*/ + + for (Scan=sort_TheorySuborigcls(Theory);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Link = (SLINK)list_Third(list_Car(Scan)); + sort_LinkResetFire(Link); + } + + for (Scan=Sort1;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Node = (NODE)list_Car(Scan); + sort_DeleteConditionList(sort_NodeConditions(Node)); + sort_PutNodeConditions(Node,list_List(sort_ConditionCreate(symbol_FirstVariable(), + list_Nil(),list_Nil(),list_Nil(),list_Nil()))); + sort_PutNodeTrue(Theory, Node); + } + + Top = sort_TopSort(); + for (Scan=sort_TheorySuborigcls(Theory);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Link = (SLINK)list_Third(list_Car(Scan)); + if (list_Empty(sort_LinkInput(Link)) && sort_LinkNoResidues(Link)) { + Node = sort_LinkOutput(Link); + Top = sort_AddBaseNode(Top,Node); + sort_DeleteConditionList(sort_NodeConditions(Node)); + sort_PutNodeConditions(Node,list_List(sort_ConditionCreateNoResidues(list_List(sort_LinkClause(Link))))); + sort_PutNodeTrue(Theory,Node); + } + } + + sort_EvalSubsortNoResidues(Theory,sort_Intersect(Top,sort_Copy(Sort1))); + Top = sort_TopSort(); + + Clauses = list_Nil(); + + for (Scan=Sort2;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Node = (NODE)list_Car(Scan); + if (!sort_NodeValue(Theory,Node)) { + /*puts(" FALSE");*/ + list_Delete(Clauses); + return NULL; + } + else + if (!list_Empty(sort_NodeConditions(Node))) + Clauses = list_Nconc(list_Copy(sort_ConditionClauses(list_Car(sort_NodeConditions(Node)))), + Clauses); + } + /*printf(" TRUE %lu\n",(unsigned long)Clauses);*/ + return sort_ConditionCreateNoResidues(Clauses); +} + +BOOL sort_TheoryIsSubsortOf(SORTTHEORY Theory, SORT Sort1, SORT Sort2) +/********************************************************* + INPUT: A sort theory and two sorts. + RETURNS: TRUE if <Sort1> is a subsort of <Sort2> and NULL otherwise. +*******************************************************/ +{ + LIST Scan; + SLINK Link; + NODE Node; + + sort_TheoryIncrementMark(Theory); + + /*fputs("\n Subsort Test: ", stdout); + sort_Print(Sort1); + putchar(' '); + sort_Print(Sort2);*/ + + for (Scan=sort_TheorySuborigcls(Theory);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Link = (SLINK)list_Third(list_Car(Scan)); + sort_LinkResetFire(Link); + } + + for (Scan=Sort1;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Node = (NODE)list_Car(Scan); + sort_PutNodeTrue(Theory, Node); + } + + sort_EvalSubsortSpecial(Theory,sort_Copy(Sort1)); + + for (Scan=Sort2;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Node = (NODE)list_Car(Scan); + if (!sort_NodeValue(Theory,Node)) + return FALSE; + } + + return TRUE; + +} + +BOOL sort_TheoryIsSubsortOfExtra(SORTTHEORY Theory, SORT Extra, SORT Sort1, SORT Sort2) +/********************************************************* + INPUT: A sort theory and three sorts. + RETURNS: TRUE if <Sort1> is a subsort of <Sort2> and <Extra> is + useful for that purpose +*******************************************************/ +{ + LIST Scan; + SLINK Link; + NODE Node; + + sort_TheoryIncrementMark(Theory); + + /*fputs("\n Subsort Test: ", stdout); + sort_Print(Sort1); + putchar(' '); + sort_Print(Sort2);*/ + + for (Scan=sort_TheorySuborigcls(Theory);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Link = (SLINK)list_Third(list_Car(Scan)); + sort_LinkResetFire(Link); + } + + for (Scan=Sort1;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Node = (NODE)list_Car(Scan); + sort_PutNodeTrue(Theory, Node); + } + + sort_EvalSubsortSpecial(Theory,sort_Copy(Sort1)); + + for (Scan=Sort2;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Node = (NODE)list_Car(Scan); + if (!sort_NodeValue(Theory,Node)) + return FALSE; + } + + return sort_TestSubsortSpecial(Theory,sort_Copy(Extra),Sort2); + +} + +LIST sort_TheoryComputeAllSubsortHits(SORTTHEORY Theory, SORT Sort1, SORT Sort2) +/********************************************************* + INPUT: A sort theory and two sorts. + RETURNS: All possible sorts that are subsets of <Sort1> that are subsorts + of <Sort2> together with all conditions. +*******************************************************/ +{ + LIST Scan,Result,Search,Scan2,Visited; + SLINK Link; + NODE Node; + SOJU Cand; + BOOL Valid,ValidStart; + NAT StartMark; + + sort_TheoryIncrementMark(Theory); + StartMark = sort_TheoryMark(Theory); + + /*fputs("\n Exhaustive Subsort Test: ", stdout); + sort_Print(Sort1); + putchar(' '); + sort_Print(Sort2);*/ + + for (Scan=sort_TheorySuborigcls(Theory);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Link = (SLINK)list_Third(list_Car(Scan)); + sort_LinkResetFire(Link); + } + + for (Scan=Sort1;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Node = (NODE)list_Car(Scan); + sort_DeleteConditionList(sort_NodeConditions(Node)); + sort_PutNodeConditions(Node,list_List(sort_ConditionCreate(symbol_FirstVariable(), + list_Nil(),list_Nil(),list_Nil(),list_Nil()))); + sort_PutNodeTrue(Theory, Node); + sort_PutNodeStartTrue(Theory,Node); + } + + sort_EvalSubsort(Theory,sort_Copy(Sort1)); + + for (Scan=Sort2;!list_Empty(Scan);Scan=list_Cdr(Scan)) {/* Subsort condition must hold */ + Node = (NODE)list_Car(Scan); + if (!sort_NodeValue(Theory,Node)) + return list_Nil(); + } + + Result = list_Nil(); + Search = list_List(sort_PairCreate(sort_Copy(Sort2),sort_ConditionCreateNoResidues(list_Nil()))); + Visited = list_Nil(); + fputs("\n\n Starting Soju Search:", stdout); + + while (!list_Empty(Search)) { + Cand = (SOJU)list_Car(Search); + Scan = Search; + Search = list_Cdr(Search); + list_Free(Scan); + putchar('\n'); + sort_PairPrint(Cand); + + if (!sort_TheorySortMember(Theory,Visited,sort_PairSort(Cand))) { + Visited = list_Cons(sort_Copy(sort_PairSort(Cand)),Visited); + ValidStart = TRUE; + Valid = TRUE; + for (Scan=sort_PairSort(Cand);!list_Empty(Scan) && (ValidStart || Valid);Scan=list_Cdr(Scan)) { + Node = (NODE)list_Car(Scan); + if (sort_NodeMark(Node) != StartMark) { + Valid = FALSE; + ValidStart = FALSE; + } + else + if (sort_NodeStart(Node) != StartMark) + ValidStart = FALSE; + } + if (Valid) { + if (ValidStart) + Result = list_Cons(sort_PairCopy(Cand),Result); + + for (Scan=sort_PairSort(Cand);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + Node = (NODE)list_Car(Scan); + for (Scan2=sort_TheorySuborigcls(Theory);!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) { + Link = (SLINK)list_Third(list_Car(Scan2)); + if (sort_LinkOutput(Link) == Node && !list_Empty(sort_LinkInput(Link))) + Search = list_Cons(sort_PairCreate(list_PointerDeleteDuplicates(sort_Intersect(sort_DeleteBaseNode(sort_Copy(sort_PairSort(Cand)),Node),sort_Copy(sort_LinkInput(Link)))), + sort_ExtendConditionByLink(sort_ConditionCopy(sort_PairCondition(Cand)),Link)), + Search); + } + } + } + sort_PairDelete(Cand); + } + } + list_DeleteWithElement(Visited,(void (*)(POINTER)) sort_Delete); + + return Result; +} + +static SORT sort_VarSort(SORTTHEORY Theory, SYMBOL Var, CLAUSE Clause, int i) +/********************************************************* + INPUT: A variable symbol, a clause and a literal index in the clause. + RETURNS: The sort of <Var> with respect to the sort constraint + literals (possibly in the antecedent) + in <Clause> except literal <i> that is not considered. + MEMORY: Both Sorts are destroyed. +*******************************************************/ +{ + SORT Result; + int j; + TERM Atom; + + Result = sort_TopSort(); + + for (j=clause_FirstConstraintLitIndex(Clause);j<=clause_LastAntecedentLitIndex(Clause);j++) + if (j != i) { + Atom = clause_LiteralAtom(clause_GetLiteral(Clause,j)); + if (symbol_IsBaseSort(term_TopSymbol(Atom)) && + term_TopSymbol(term_FirstArgument(Atom)) == Var) + Result = sort_Intersect(Result,sort_TheorySortOfSymbol(Theory,term_TopSymbol(Atom))); + } + + return Result; +} + + +static BOOL sort_MatchNoResidues(SORTTHEORY Theory, TERM Term1, TERM Term2, CLAUSE Clause, LIST* Clauses) +/********************************************************* + INPUT: A sort theory, two terms, a clause and list of clauses + as an additional return parameter. + RETURNS: TRUE iff there exists a well-sorted matcher from <Term1> to <Term2> + The sorts of variables in <Term1> is determined by the sort constraint in <Clause> + The sorts of subterms of <Term2> are assumed to be already computed and stored. +*******************************************************/ +{ + int l; + SUBST subst,scan; + SORT varsort; + LIST NewClauses; + SOJU Pair; + CONDITION Cond; + + l = clause_Length(Clause); + NewClauses = list_Nil(); + + cont_StartBinding(); + unify_Match(cont_LeftContext(),Term1,Term2); + subst = subst_ExtractMatcher(); + cont_BackTrack(); + + /*putchar('\n'); term_Print(Term1);fputs("->",stdout); + term_Print(Term2);putchar(':');subst_Print(subst); + putchar('\n');*/ + for (scan=subst;!subst_Empty(scan);scan=subst_Next(scan)) { + varsort = sort_VarSort(Theory,subst_Dom(scan),Clause,l); + Pair = hash_Get(subst_Cod(scan)); + if ((Cond = sort_TheoryIsSubsortOfNoResidues(Theory,sort_PairSort(Pair),varsort)) == NULL) { + sort_DeleteOne(varsort); + list_Delete(NewClauses); + subst_Free(subst); + return FALSE; + } else { + NewClauses = list_Nconc(NewClauses, + list_Copy(sort_ConditionClauses(sort_PairCondition(Pair)))); + NewClauses = list_Nconc(NewClauses,sort_ConditionClauses(Cond)); + sort_ConditionPutClauses(Cond,list_Nil()); + sort_ConditionDelete(Cond); + } + + sort_DeleteOne(varsort); + } + + subst_Free(subst); + *Clauses = list_Nconc(NewClauses,*Clauses); + return TRUE; +} + + +static SOJU sort_ComputeSortInternNoResidues(SORTTHEORY Theory, TERM Term, + CLAUSE Clause, int i, + FLAGSTORE Flags, + PRECEDENCE Precedence) +/********************************************************* + INPUT: A Term, a sort theory representing a set of + clauses, a clause wrt that variable sorts are + computed, where the literal <i> is discarded, + a flag store and a precedence. + The sorts of 'Term's args have to be known. + RETURNS: The sort of 'Term' wrt. the sort theory of the + clause set. Be careful, the Sort-entries of + 'Term' and its subterms are changed. +*******************************************************/ +{ + SORT Sort; + LIST HelpList, Scan, Clauses; + TERM QueryTerm; + + Sort = sort_TopSort(); + Clauses = list_Nil(); + + if (term_IsVariable(Term)) + Sort = sort_VarSort(Theory,term_TopSymbol(Term),Clause,i); + else { + HelpList = st_GetGen(cont_LeftContext(), sort_TheoryIndex(Theory), Term); + for (Scan=HelpList;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + SYMBOL Top; + LITERAL ActLit; + TERM Atom; + CLAUSE ActClause; + + QueryTerm = (TERM)list_First(Scan); + + if (!term_IsVariable(QueryTerm)) { /* Currently also subort declarations are in the index ...*/ + Atom = (TERM)list_First(term_SupertermList(QueryTerm)); + Top = term_TopSymbol(Atom); + ActLit = (LITERAL)list_First(term_SupertermList(Atom)); + ActClause = clause_LiteralOwningClause(ActLit); + if (clause_IsSortTheoryClause(ActClause, Flags, Precedence) && + sort_MatchNoResidues(Theory,QueryTerm,Term, ActClause,&Clauses) && + !sort_ContainsSymbol(Sort,Top)) { + Sort = sort_Intersect(Sort,sort_TheorySortOfSymbol(Theory,Top)); + Clauses = list_Cons(ActClause,Clauses); + } + } + } + list_Delete(HelpList); + } + return (sort_PairCreate(Sort,sort_ConditionCreateNoResidues(Clauses))); +} + + +SOJU sort_ComputeSortNoResidues(SORTTHEORY Theory, TERM Term, CLAUSE Clause, + int i, FLAGSTORE Flags, PRECEDENCE Precedence) +/********************************************************* + INPUT: A Term and an Index representing a set of + clauses, a clause to access + variable-sort-information where the literal <i> + is discarded, a flag store and a precedence. + RETURNS: The sort of 'Term' wrt. the sort theory of the + clause set and the clauses used for this + computation. + Be careful, the Sort-entries of + 'Term' and its subterms are changed, if they + already existed. +*******************************************************/ +{ + int SubtermStack; + SOJU SortPair; + + SortPair = (SOJU)NULL; + SubtermStack = stack_Bottom(); + sharing_PushOnStack(Term); + + + while (!stack_Empty(SubtermStack)){ + Term = stack_PopResult(); + + if (!(SortPair = (SOJU)hash_Get(Term))) { + SortPair = sort_ComputeSortInternNoResidues(Theory,Term,Clause,i, + Flags, Precedence); + /*fputs("\n Computed:",stdout);term_Print(Term); + putchar(':');sort_PairPrint(SortPair);putchar('\n');*/ + hash_Put(Term,SortPair); + } + } + + SortPair = sort_PairCopy(SortPair); + hash_ResetWithValue((void (*)(POINTER)) sort_DeleteSortPair); + + return(SortPair); +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * Creating and Analyzing Sort Theories * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +static BOOL sort_SortTheoryIsTrivial(SORTTHEORY Theory, LIST Clauses) +/********************************************************* + INPUT: A sort theory and a list of clauses that generated the theory. + RETURNS: TRUE iff all considered base sorts are top. +*******************************************************/ +{ + LIST Sorts; + CLAUSE Clause; + int i,n; + CONDITION Cond; + + Sorts = list_Nil(); + + /* fputs("\n\nAnalyzing Theory:", stdout); */ + + while (!list_Empty(Clauses)) { + Clause = (CLAUSE)list_Car(Clauses); + n = clause_Length(Clause); + Clauses = list_Cdr(Clauses); + + /* fputs("\n\t", stdout);clause_Print(Clause); */ + + for (i=clause_FirstConstraintLitIndex(Clause); i<n; i++) + Sorts = list_Cons((POINTER)term_TopSymbol(clause_LiteralAtom( + clause_GetLiteral(Clause,i))), Sorts); + + Sorts = list_PointerDeleteDuplicates(Sorts); + } + + Clauses = Sorts; + while (!list_Empty(Clauses)) { + list_Rplaca(Clauses,sort_TheorySortOfSymbol(Theory,(SYMBOL)list_Car(Clauses))); + Clauses = list_Cdr(Clauses); + } + + n = list_Length(Sorts); + i = 0; + Clauses = Sorts; + + /* printf("\n\t There are %d different sorts.",n); */ + + while (!list_Empty(Clauses)) { + if ((Cond = sort_TheoryIsSubsortOfNoResidues(Theory,sort_TopSort(),list_Car(Clauses)))) { + sort_ConditionDelete(Cond); + i++; + } + sort_DeleteOne(list_Car(Clauses)); + Clauses = list_Cdr(Clauses); + } + + list_Delete(Sorts); + + return (i == n); /* All sorts are trivial */ +} + + +static LIST sort_ApproxPseudoLinear(LIST Constraint, TERM Head, SYMBOL Var) +/************************************************************** + INPUT: A list of constraint literals, the head literal term + and a variable maximal for all variables. + RETURNS: The new list of constraint literals. + EFFECT: The succedent literal is made pseudo-linear. + The function is DESTRUCTIVE. +***************************************************************/ +{ + TERM Atom; + LIST RenVars,Scan1,Scan2,Lits; + SYMBOL OldVar, NewVar; + + RenVars = term_RenamePseudoLinear(Head,Var); + Lits = list_Nil(); + + for (Scan1=RenVars;!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { + OldVar = (SYMBOL)list_PairFirst(list_Car(Scan1)); + NewVar = (SYMBOL)list_PairSecond(list_Car(Scan1)); + list_PairFree(list_Car(Scan1)); + for (Scan2=Constraint;!list_Empty(Scan2);Scan2=list_Cdr(Scan2)) { + Atom = (TERM)list_Car(Constraint); + if (symbol_Equal(term_TopSymbol(term_FirstArgument(Atom)),OldVar)) + Lits = list_Cons(term_Create(term_TopSymbol(Atom), + list_List(term_Create(NewVar,list_Nil()))), Lits); + } + } + list_Delete(RenVars); + + Lits = list_Nconc(Constraint,Lits); + + return Lits; +} + + +static LIST sort_ApproxHornClauses(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause to make special horn clauses from, a flag + store and a precedence. + RETURNS: The list of clauses according to the rule + ClauseDeletion. + MEMORY: Allocates memory for the clauses and the list. +***************************************************************/ +{ + LIST Result, NewConstraint,NewSuccedent; + CLAUSE NewClause; + LITERAL LitK; + int i,length,j,lc,pli; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sort_ApproxHornClauses :"); + misc_ErrorReport(" Illegal input. Input not a clause.\n"); + misc_FinishErrorReport(); + } +#endif + + Result = list_Nil(); + + if (clause_HasOnlyVarsInConstraint(Clause, Flags, Precedence) && + clause_HasSortInSuccedent(Clause, Flags, Precedence)) { + length = clause_Length(Clause); + + for (i = clause_FirstSuccedentLitIndex(Clause); i < length; i++) { + LitK = clause_GetLiteral(Clause, i); + + if (symbol_Arity(term_TopSymbol(clause_LiteralSignedAtom(LitK))) == 1) { + pli = i; + NewSuccedent = list_List(term_Copy(clause_LiteralSignedAtom(LitK))); + NewConstraint = list_Nil(); + lc = clause_LastConstraintLitIndex(Clause); + + for (j = clause_FirstLitIndex(); j <= lc; j++) + if (clause_LitsHaveCommonVar(LitK, clause_GetLiteral(Clause, j))) + NewConstraint = list_Cons(term_Copy(clause_LiteralAtom( + clause_GetLiteral(Clause, j))), NewConstraint); + + if (!list_Empty(NewConstraint)) + NewConstraint = sort_ApproxPseudoLinear(NewConstraint, + list_Car(NewSuccedent), + clause_MaxVar(Clause)); + + NewClause = clause_Create(NewConstraint, list_Nil(), NewSuccedent, + Flags, Precedence); + clause_SetSplitLevel(NewClause, 0); + clause_SetFlag(NewClause,WORKEDOFF); + clause_SetFromClauseDeletion(NewClause); + clause_SetParentClauses(NewClause, list_List((POINTER)clause_Number(Clause))); + clause_AddParentLiteral(NewClause, pli); + + list_Delete(NewConstraint); + list_Delete(NewSuccedent); + Result = list_Cons(NewClause, Result); + } + } + } + return(Result); +} + +LIST sort_ApproxMaxDeclClauses(CLAUSE Clause, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A declaration clause to make special horn clauses + from, a flag store and a precedence. + RETURNS: The list of Horn clauses that are pseudo-linear declaration + clauses generated from maximal declarations in <Clause> + MEMORY: Allocates memory for the clauses and the list. +***************************************************************/ +{ + LIST Result, NewConstraint,NewSuccedent; + CLAUSE NewClause; + LITERAL LitK; + int i,length,j,lc,pli; + +#ifdef CHECK + if (!clause_IsClause(Clause, Flags, Precedence) || + !clause_IsDeclarationClause(Clause)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In sort_ApproxMaxDeclClauses :"); + misc_ErrorReport(" Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + Result = list_Nil(); + length = clause_Length(Clause); + + for (i = clause_FirstSuccedentLitIndex(Clause); i < length; i++) { + LitK = clause_GetLiteral(Clause, i); + + if (clause_LiteralIsMaximal(LitK) && + symbol_IsBaseSort(term_TopSymbol(clause_LiteralSignedAtom(LitK)))) { + pli = i; + NewSuccedent = list_List(term_Copy(clause_LiteralSignedAtom(LitK))); + NewConstraint = list_Nil(); + lc = clause_LastConstraintLitIndex(Clause); + + for (j = clause_FirstLitIndex(); j <= lc; j++) + if (clause_LitsHaveCommonVar(LitK, clause_GetLiteral(Clause, j))) + NewConstraint = list_Cons(term_Copy(clause_LiteralAtom(clause_GetLiteral(Clause, j))), + NewConstraint); + + if (!list_Empty(NewConstraint)) + NewConstraint = sort_ApproxPseudoLinear(NewConstraint, + list_Car(NewSuccedent), + clause_MaxVar(Clause)); + + NewClause = clause_Create(NewConstraint, list_Nil(), NewSuccedent, + Flags, Precedence); + clause_SetSplitLevel(NewClause, 0); + clause_SetFlag(NewClause,WORKEDOFF); + clause_SetFromClauseDeletion(NewClause); + clause_SetParentClauses(NewClause, list_List(Clause)); /* The clause itself is added! */ + clause_AddParentLiteral(NewClause, pli); + + list_Delete(NewConstraint); + list_Delete(NewSuccedent); + Result = list_Cons(NewClause, Result); + } + } + return(Result); +} + + +static LIST sort_ApproxClauses(LIST Clauses, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A list of top level clauses, a flag store and a + precedence. + RETURNS: A list of approximated clauses from <Clauses> which must + be used for sort deletion. + EFFECT: None. +***************************************************************/ +{ + LIST Result,ApproxClauses; + CLAUSE ActClause; + + Result = list_Nil(); + + while (!list_Empty(Clauses)) { + ActClause = (CLAUSE)list_Car(Clauses); + ApproxClauses = sort_ApproxHornClauses(ActClause, Flags, Precedence); + Result = list_Nconc(ApproxClauses,Result); + Clauses = list_Cdr(Clauses); + } + + return Result; +} + +LIST sort_EliminateSubsumedClauses(LIST Clauses) +/********************************************************* + INPUT: A list of clauses. + RETURNS: <Clauses> without subsumed clauses. +*******************************************************/ +{ + LIST RedundantClauses,Iter,Scan; + BOOL Kept; + + RedundantClauses = list_Nil(); + for (Scan = Clauses; !list_Empty(Scan);Scan=list_Cdr(Scan)) { + Kept = TRUE; + for (Iter = Clauses;!list_Empty(Iter) && Kept; Iter = list_Cdr(Iter)) + if (list_Car(Iter) != list_Car(Scan) && + !list_PointerMember(RedundantClauses,list_Car(Iter)) && + subs_Subsumes(list_Car(Iter),list_Car(Scan),subs_NoException(),subs_NoException())) { + Kept = FALSE; + RedundantClauses = list_Cons(list_Car(Scan),RedundantClauses); + } + } + Clauses = list_NPointerDifference(Clauses,RedundantClauses); + clause_DeleteClauseList(RedundantClauses); + return Clauses; +} + + +SORTTHEORY sort_ApproxStaticSortTheory(LIST Clauses, FLAGSTORE Flags, + PRECEDENCE Precedence) +/********************************************************* + INPUT: A list of clauses, a flag store and a + precedence. + RETURNS: NULL if the approximated sort theory is trivial, + the approximated sort theory otherwise. +*******************************************************/ +{ + LIST Scan,ApproxClauses; + CLAUSE Clause; + SORTTHEORY Result; + + Result = sort_TheoryCreate(); + ApproxClauses = sort_ApproxClauses(Clauses, Flags, Precedence); + ApproxClauses = sort_EliminateSubsumedClauses(ApproxClauses); + + /*fputs("\n\n Approx Sort Theory:", stdout); + for (Scan = ApproxClauses; !list_Empty(Scan);Scan=list_Cdr(Scan)) { + fputs("\n\t",stdout); clause_Print(list_Car(Scan)); + }*/ + + for (Scan = ApproxClauses; !list_Empty(Scan);Scan=list_Cdr(Scan)) { + Clause = (CLAUSE)list_Car(Scan); + sort_TheoryInsertClause(Result,Clause,Clause, + clause_GetLiteral(Clause,clause_FirstSuccedentLitIndex(Clause))); + } + + if (sort_SortTheoryIsTrivial(Result,ApproxClauses)) { + sort_TheoryDelete(Result); + Result = (SORTTHEORY)NULL; + } + + + if (flag_GetFlagValue(Flags, flag_DOCSST)) { + fputs("\n\n Approx Sort Theory:", stdout); + if (Result) { + puts("\n"); + sort_TheoryPrint(Result); + } + else + fputs(" trivial.", stdout); + } + list_Delete(ApproxClauses); + + return Result; +} + + +SORTTHEORY sort_ApproxDynamicSortTheory(LIST Clauses) +/********************************************************* + INPUT: A list of clauses. + RETURNS: The approximated dynamic sort theory for <Clauses> + Only maximal declarations are considered. +*******************************************************/ +{ + return (SORTTHEORY)NULL; +} + +STR sort_AnalyzeSortStructure(LIST Clauses, FLAGSTORE Flags, + PRECEDENCE Precedence) +/********************************************************* + INPUT: A list of clauses, a flag store and a + precedence. + RETURNS: SORTEQMANY if all positive equations are many + sorted. + SORTEQDEC if all positive equations are sort + decreasing. + SORTEQNONE otherwise. + For the check, the static sort theory is + considered. +*******************************************************/ +{ + SORTTHEORY Theory; + LIST Scan; + CLAUSE Clause,Copy; + int i,l; + TERM Atom,Left,Right; + SOJU SojuLeft,SojuRight; + CONDITION Cond; + BOOL ManySorted, Decreasing; + + Theory = sort_TheoryCreate(); + ManySorted = TRUE; + Decreasing = TRUE; + + for (Scan=Clauses;!list_Empty(Scan);Scan=list_Cdr(Scan)) { + /* Extract static sort theory */ + Clause = (CLAUSE)list_Car(Scan); + if (clause_IsPotentialSortTheoryClause(Clause, Flags, Precedence)) { + Copy = clause_Copy(Clause); + symbol_AddProperty(term_TopSymbol(clause_GetLiteralTerm(Copy, + clause_FirstSuccedentLitIndex(Copy))), + DECLSORT); + list_Delete(clause_ParentClauses(Copy)); + clause_SetParentClauses(Copy,list_Nil()); + list_Delete(clause_ParentLiterals(Copy)); + clause_SetParentLiterals(Copy,list_Nil()); + clause_SetNumber(Copy,clause_Number(Clause)); + clause_SetSortConstraint(Copy,FALSE, Flags, Precedence); + sort_TheoryInsertClause(Theory,Clause,Copy, + clause_GetLiteral(Copy,clause_FirstSuccedentLitIndex(Copy))); + } + } + + /*putchar('\n'); + sort_TheoryPrint(Theory); + putchar('\n');*/ + + for (Scan=Clauses;!list_Empty(Scan) && Decreasing;Scan=list_Cdr(Scan)) { + Clause = (CLAUSE)list_Car(Scan); + l = clause_Length(Clause); + for (i=clause_FirstSuccedentLitIndex(Clause);i<l && Decreasing;i++) { + Atom = clause_GetLiteralTerm(Clause,i); + if (fol_IsEquality(Atom)) { + Left = term_FirstArgument(Atom); + Right = term_SecondArgument(Atom); + SojuLeft = sort_ComputeSortNoResidues(Theory, Left, Clause, i, + Flags, Precedence); + SojuRight = sort_ComputeSortNoResidues(Theory, Right,Clause, i, + Flags, Precedence); + if (sort_IsTopSort(sort_PairSort(SojuRight)) || sort_IsTopSort(sort_PairSort(SojuLeft))) { + /*fputs("\nNon decreasing equation ",stdout); term_PrintPrefix(Atom); + fputs(" in clause: ",stdout);clause_Print(Clause);putchar('\n');*/ + ManySorted = FALSE; + Decreasing = FALSE; + } + else { + if (!sort_Eq(sort_PairSort(SojuRight), sort_PairSort(SojuLeft))) { + ManySorted = FALSE; + Cond = sort_TheoryIsSubsortOfNoResidues(Theory, sort_PairSort(SojuRight), + sort_PairSort(SojuLeft)); + if (Cond && !clause_LiteralIsOrientedEquality(clause_GetLiteral(Clause,i))) { + sort_ConditionDelete(Cond); + Cond = sort_TheoryIsSubsortOfNoResidues(Theory, sort_PairSort(SojuLeft), + sort_PairSort(SojuRight)); + } + if (Cond) + sort_ConditionDelete(Cond); + else { + /*fputs("\nNon decreasing equation ",stdout); term_PrintPrefix(Atom); + fputs(" in clause: ",stdout);clause_Print(Clause);putchar('\n');*/ + Decreasing = FALSE; + } + } + } + sort_PairDelete(SojuLeft); + sort_PairDelete(SojuRight); + } + } + } + sort_TheoryDelete(Theory); + if (ManySorted) + return SORTEQMANY; + if (Decreasing) + return SORTEQDECR; + + return SORTEQNONE; +} + diff --git a/test/spass/sort.h b/test/spass/sort.h new file mode 100644 index 0000000000000000000000000000000000000000..83bc5472dd1b093c0b58cde2d4cfb3a73ea3d14b --- /dev/null +++ b/test/spass/sort.h @@ -0,0 +1,598 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SORTED REASONING * */ +/* * * */ +/* * $Module: SORT * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _SORT_ +#define _SORT_ + +#include "clause.h" +#include "unify.h" +#include "hash.h" +#include "subsumption.h" + + +/**************************************************************/ +/* Data Structures and Constants */ +/**************************************************************/ + +/* Objects of type SORT are used to store the sort information */ +/* for terms. SORT is a list of NODE's */ + +typedef LIST SORT; +/* List of sort nodes */ + +typedef LIST SOJU; +/* Pair: First Component Sort, Second Component Condition */ + +typedef enum {SORTEQNONE=1, SORTEQDECR=2, SORTEQMANY=3} STR; +/* The overall result of an sort theory analysis with respect to equations */ + +typedef struct CONDITION_HELP { + SYMBOL var; + LIST constraint; + LIST antecedent; + LIST succedent; + LIST clauses; +} CONDITION_NODE,*CONDITION; + +/* This data structure collects the conditions from conditioned subsort clauses */ +/* The constraint, antecedent, succedent lists contain lists of atoms used to */ +/* derive the subsort relationship that come from clauses. */ + + +typedef struct NODE_HELP { + LIST links; + NAT mark; + NAT start; + NAT extra; + LIST conditions; + SYMBOL symbol; +} NODE_NODE,*NODE; + +/* This is a node from the subsort graph with outgoing links the represented */ +/* sort symbol and a mark indicating whether the node is already visited,i.e, */ +/* it is TRUE. Whereas start indicates whether the node was put true right */ +/* from the beginning. Conditions contains a list of conditions needed to set */ +/* the node true. */ + +typedef struct SLINK_HELP { + LIST input; + NODE output; + int card; + int fire; + LIST constraint; + LIST antecedent; + LIST succedent; + SYMBOL var; + CLAUSE clause; +} SLINK_NODE,*SLINK; + +/* This is a link in the subsort graph, with a list of input nodes that have */ +/* to become true in order to fire the link and set the output node TRUE */ +/* constraint, antecedent, succedent literals are the extra literals of */ +/* <clause> and <var> is the subsort variable. It is always assumed that the */ +/* subsort variable is the maximal variable with respect to the constraint, */ +/* antecedent and succedent literals. */ + +typedef struct SORTTHEORY_HELP { + st_INDEX index; + NODE basesorttable[symbol__MAXSIGNATURE]; + LIST suborigcls; + LIST termorigcls; + NAT mark; +} SORTTHEORY_NODE,*SORTTHEORY; + +/* The index contains the term declarations mapped to their possibly */ +/* approximated term declarations of inserted clauses. The subsort declarations*/ +/* are handled by a specific graph initiated over the base sorts. There is */ +/* one node in the graph for every base sort (basesorttable) and links */ +/* correspond to subsort declaration clauses */ +/* The mark is used in the subsort graph to detect already visited nodes. */ +/* The lists suborigcls and termorigcls map original clauses to sort theory */ +/* clauses to links/terms respectively. They contain triples of this kind */ + + + +/**************************************************************/ +/* Extern */ +/**************************************************************/ + +void sort_ConditionDelete(CONDITION); +CONDITION sort_ConditionCopy(CONDITION); + + +/**************************************************************/ +/* Macros */ +/**************************************************************/ + +static __inline__ SORT sort_TopSort(void) +{ + return list_Nil(); +} + +static __inline__ BOOL sort_IsTopSort(SORT S) +{ + return list_Empty(S); +} + +static __inline__ SORT sort_Copy(SORT S) +{ + return list_Copy(S); +} + +static __inline__ void sort_DeleteOne(SORT S) +{ + list_Delete(S); +} + +static __inline__ SORT sort_Intersect(SORT S1, SORT S2) +{ + return list_Nconc(S1, S2); +} + +static __inline__ SORT sort_DeleteBaseNode(SORT S, NODE N) +{ + return list_PointerDeleteElement(S,N); +} + +static __inline__ SORT sort_AddBaseNode(SORT S, NODE N) +{ + return list_Cons(N,S); +} + +static __inline__ void sort_NodeFree(NODE N) +{ + memory_Free(N,sizeof(NODE_NODE)); +} + +static __inline__ BOOL sort_NodeEqual(NODE N1, NODE N2) +{ + return (N1 == N2); +} + +static __inline__ void sort_DeleteConditionList(LIST List) +{ + list_DeleteWithElement(List, (void (*)(POINTER)) sort_ConditionDelete); +} + +static __inline__ void sort_NodeDelete(NODE N) +{ + list_Delete(N->links); + N->links = list_Nil(); + sort_DeleteConditionList(N->conditions); + N->conditions = list_Nil(); + sort_NodeFree(N); +} + +static __inline__ LIST sort_NodeLinks(NODE N) +{ + return N->links; +} + +static __inline__ BOOL sort_NodeValue(SORTTHEORY S, NODE N) +{ + return (N->mark == S->mark); +} + +static __inline__ BOOL sort_NodeExtraValue(SORTTHEORY S, NODE N) +{ + return (N->extra == S->mark); +} + +static __inline__ BOOL sort_NodeStartValue(SORTTHEORY S, NODE N) +{ + return (N->start == S->mark); +} + +static __inline__ NAT sort_NodeMark(NODE N) +{ + return N->mark; +} + +static __inline__ NAT sort_NodeStart(NODE N) +{ + return N->start; +} + +static __inline__ SYMBOL sort_NodeSymbol(NODE N) +{ + return N->symbol; +} + +static __inline__ LIST sort_NodeConditions(NODE N) +{ + return N->conditions; +} + +static __inline__ void sort_PutNodeMark(NODE N, NAT M) +{ + N->mark = M; +} + +static __inline__ void sort_PutNodeExtra(NODE N, NAT M) +{ + N->extra = M; +} + +static __inline__ void sort_PutNodeStart(NODE N, NAT S) +{ + N->start = S; +} + +static __inline__ void sort_PutNodeSymbol(NODE N, SYMBOL S) +{ + N->symbol = S; +} + +static __inline__ void sort_PutNodeLinks(NODE N, LIST C) +{ + N->links = C; +} + +static __inline__ void sort_PutNodeConditions(NODE N, LIST C) +{ + N->conditions = C; +} + +static __inline__ void sort_PutNodeTrue(SORTTHEORY S, NODE N) +{ + N->mark = S->mark; +} + +static __inline__ void sort_PutNodeExtraTrue(SORTTHEORY S, NODE N) +{ + N->extra = S->mark; +} + +static __inline__ void sort_PutNodeStartTrue(SORTTHEORY S, NODE N) +{ + N->start = S->mark; +} + +static __inline__ LIST sort_LinkInput(SLINK S) +{ + return S->input; +} + +static __inline__ NODE sort_LinkOutput(SLINK S) +{ + return S->output; +} + +static __inline__ int sort_LinkFire(SLINK S) +{ + return S->fire; +} + +static __inline__ int sort_LinkVar(SLINK S) +{ + return S->var; +} + +static __inline__ LIST sort_LinkConstraint(SLINK S) +{ + return S->constraint; +} + +static __inline__ LIST sort_LinkAntecedent(SLINK S) +{ + return S->antecedent; +} + +static __inline__ LIST sort_LinkSuccedent(SLINK S) +{ + return S->succedent; +} + +static __inline__ CLAUSE sort_LinkClause(SLINK S) +{ + return S->clause; +} + +static __inline__ int sort_LinkCard(SLINK S) +{ + return S->card; +} + +static __inline__ void sort_PutLinkInput(SLINK S, LIST T) +{ + S->input = T; +} + +static __inline__ void sort_PutLinkVar(SLINK S, SYMBOL V) +{ + S->var = V; +} + +static __inline__ void sort_PutLinkConstraint(SLINK S, LIST T) +{ + S->constraint = T; +} + +static __inline__ void sort_PutLinkAntecedent(SLINK S, LIST T) +{ + S->antecedent = T; +} + +static __inline__ void sort_PutLinkSuccedent(SLINK S, LIST T) +{ + S->succedent = T; +} + +static __inline__ void sort_PutLinkOutput(SLINK S,NODE H) +{ + S->output = H; +} + +static __inline__ void sort_PutLinkClause(SLINK S, CLAUSE C) +{ + S->clause = C; +} + +static __inline__ void sort_PutLinkCard(SLINK S,int L) +{ + S->card = L; +} + +static __inline__ void sort_LinkResetFire(SLINK S) { + S->fire = S->card; +} + +static __inline__ int sort_LinkDecrementFire(SLINK S) +{ + --(S->fire); + return S->fire; +} + +static __inline__ void sort_LinkFree(SLINK S) +{ + memory_Free(S,sizeof(SLINK_NODE)); +} + +static __inline__ void sort_LinkDelete(SLINK S) +{ + LIST Scan; + for (Scan=sort_LinkInput(S); !list_Empty(Scan); Scan=list_Cdr(Scan)) + sort_PutNodeLinks(list_Car(Scan),list_PointerDeleteElement(sort_NodeLinks(list_Car(Scan)),S)); + list_Delete(sort_LinkInput(S)); + term_DeleteTermList(sort_LinkConstraint(S)); + term_DeleteTermList(sort_LinkAntecedent(S)); + term_DeleteTermList(sort_LinkSuccedent(S)); + sort_LinkFree(S); +} + +static __inline__ SYMBOL sort_ConditionVar(CONDITION C) +{ + return C->var; +} + +static __inline__ LIST sort_ConditionConstraint(CONDITION C) +{ + return C->constraint; +} + +static __inline__ LIST sort_ConditionAntecedent(CONDITION C) +{ + return C->antecedent; +} + +static __inline__ LIST sort_ConditionSuccedent(CONDITION C) +{ + return C->succedent; +} + +static __inline__ LIST sort_ConditionClauses(CONDITION C) +{ + return C->clauses; +} + +static __inline__ void sort_ConditionPutVar(CONDITION C, SYMBOL Var) +{ + C->var = Var; +} + +static __inline__ void sort_ConditionPutConstraint(CONDITION C, LIST Constr) +{ + C->constraint = Constr; +} + +static __inline__ void sort_ConditionPutAntecedent(CONDITION C, LIST Ante) +{ + C->antecedent = Ante; +} + +static __inline__ void sort_ConditionPutSuccedent(CONDITION C, LIST Succ) +{ + C->succedent = Succ; +} + +static __inline__ void sort_ConditionPutClauses(CONDITION C, LIST Clauses) +{ + C->clauses = Clauses; +} + +static __inline__ void sort_ConditionFree(CONDITION C) +{ + memory_Free(C, sizeof(CONDITION_NODE)); +} + +static __inline__ BOOL sort_ConditionNoResidues(CONDITION C) +{ + return (list_Empty(sort_ConditionConstraint(C)) && + list_Empty(sort_ConditionAntecedent(C)) && + list_Empty(sort_ConditionSuccedent(C))); +} + + + +static __inline__ BOOL sort_LinkNoResidues(SLINK S) +{ + return (list_Empty(sort_LinkConstraint(S)) && + list_Empty(sort_LinkAntecedent(S)) && + list_Empty(sort_LinkSuccedent(S))); +} + +static __inline__ BOOL sort_HasEqualSort(SORT S1, SORT S2) +{ + return S1 == S2; +} + + +static __inline__ POINTER sort_PairSort(LIST Pair) +{ + return list_PairFirst(Pair); +} + +static __inline__ POINTER sort_PairCondition(LIST Pair) +{ + return list_PairSecond(Pair); +} + +static __inline__ LIST sort_PairCreate(SORT S , CONDITION Just) +{ + return list_PairCreate((POINTER)S, Just); +} + +static __inline__ void sort_PairFree(LIST Pair) +{ + list_PairFree(Pair); +} + +static __inline__ void sort_PairDelete(LIST Pair) +{ + sort_DeleteOne(sort_PairSort(Pair)); + sort_ConditionDelete(sort_PairCondition(Pair)); + list_PairFree(Pair); +} + +static __inline__ LIST sort_PairCopy(LIST Pair) +{ + return sort_PairCreate(sort_Copy(sort_PairSort(Pair)), + sort_ConditionCopy(sort_PairCondition(Pair))); +} + +static __inline__ NODE sort_TheoryNode(SORTTHEORY Theory, SYMBOL S) +{ + return Theory->basesorttable[symbol_Index(S)]; +} + +static __inline__ NAT sort_TheoryMark(SORTTHEORY Theory) +{ + return Theory->mark; +} + +static __inline__ LIST sort_TheorySuborigcls(SORTTHEORY Theory) +{ + return Theory->suborigcls; +} + +static __inline__ LIST sort_TheoryTermorigcls(SORTTHEORY Theory) +{ + return Theory->termorigcls; +} + +static __inline__ void sort_TheoryIncrementMark(SORTTHEORY Theory) +{ + if (Theory->mark == NAT_MAX) { + int i; + NODE Node; + for (i = 0; i < symbol__MAXSIGNATURE; i++) { + Node = Theory->basesorttable[i]; + Node->mark = 0; + Node->extra = 0; + Node->start = 0; + } + Theory->mark = 0; + } + ++(Theory->mark); +} + +static __inline__ st_INDEX sort_TheoryIndex(SORTTHEORY Theory) +{ + return Theory->index; +} + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +void sort_Init(void); +void sort_Free(void); + +void sort_Delete(SORT); +BOOL sort_Eq(SORT, SORT); +void sort_DeleteSortPair(SOJU); + +void sort_Print(SORT); +void sort_PairPrint(SOJU); + +LIST sort_GetSymbolsFromSort(SORT); +BOOL sort_ContainsSymbol(SORT, SYMBOL); +BOOL sort_IsSort(SORT); + + +SORTTHEORY sort_ApproxStaticSortTheory(LIST, FLAGSTORE, PRECEDENCE); +SORTTHEORY sort_ApproxDynamicSortTheory(LIST); + + +SORTTHEORY sort_TheoryCreate(void); +void sort_TheoryDelete(SORTTHEORY); +void sort_TheoryPrint(SORTTHEORY); +void sort_TheoryInsertClause(SORTTHEORY, CLAUSE, CLAUSE, LITERAL); +void sort_TheoryDeleteClause(SORTTHEORY, CLAUSE); +SORT sort_TheorySortOfSymbol(SORTTHEORY, SYMBOL); +BOOL sort_TheorySortEqual(SORTTHEORY,SORT,SORT); +CONDITION sort_TheoryIsSubsortOfNoResidues(SORTTHEORY, SORT, SORT); +BOOL sort_TheoryIsSubsortOf(SORTTHEORY, SORT, SORT); +BOOL sort_TheoryIsSubsortOfExtra(SORTTHEORY , SORT , SORT , SORT); +LIST sort_TheoryComputeAllSubsortHits(SORTTHEORY, SORT, SORT); +SOJU sort_ComputeSortNoResidues(SORTTHEORY,TERM, CLAUSE, int, FLAGSTORE, PRECEDENCE); +LIST sort_ApproxMaxDeclClauses(CLAUSE, FLAGSTORE, PRECEDENCE); +STR sort_AnalyzeSortStructure(LIST, FLAGSTORE, PRECEDENCE); + + +#endif diff --git a/test/spass/st.c b/test/spass/st.c new file mode 100644 index 0000000000000000000000000000000000000000..5f591ef22ba55982d6672514bf1abe03a937bc87 --- /dev/null +++ b/test/spass/st.c @@ -0,0 +1,1691 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * ST INDEXING * */ +/* * * */ +/* * $Module: ST * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "st.h" + + +/**************************************************************/ +/* Local Variables */ +/**************************************************************/ + +static st_RETRIEVAL_TYPE st_CURRENT_RETRIEVAL; +static st_WHERE_TYPE st_WHICH_CONTEXTS; +static CONTEXT st_INDEX_CONTEXT; +static st_MINMAX st_EXIST_MINMAX; + +/**************************************************************/ +/* Global Variables */ +/**************************************************************/ + +ST_STACK st_STACK; +int st_STACKPOINTER; +int st_STACKSAVE; + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CREATION OF INDEX * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +st_INDEX st_IndexCreate(void) +/************************************************************** + INPUT: None. + RETURNS: A pointer to a new St-Index. + SUMMARY: Creates a new St-index. +***************************************************************/ +{ + st_INDEX StIndex; + + StIndex = st_Get(); + StIndex->subnodes = list_Nil(); + StIndex->entries = list_Nil(); + StIndex->subst = subst_Nil(); + st_SetMax(StIndex, 0); + st_SetMin(StIndex, 0); + + return StIndex; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CREATION OF INDEX NODES * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +static st_INDEX st_NodeAddLeaf(SUBST Subst, st_MINMAX MinMax, POINTER Pointer) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + st_INDEX NewLeaf; + + NewLeaf = st_Get(); + NewLeaf->subnodes = list_Nil(); + NewLeaf->entries = list_List(Pointer); + NewLeaf->subst = Subst; + st_SetMax(NewLeaf, MinMax); + st_SetMin(NewLeaf, MinMax); + + return NewLeaf; +} + + +static void st_NodeAddInner(st_INDEX StIndex, SUBST SubstOld, SUBST SubstNew, + SUBST ComGen, st_MINMAX MinMax, POINTER Pointer) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + st_INDEX OldIndexNode; + + OldIndexNode = st_Get(); + OldIndexNode->subst = SubstOld; + OldIndexNode->entries = StIndex->entries; + OldIndexNode->subnodes = StIndex->subnodes; + st_SetMax(OldIndexNode, st_Max(StIndex)); + st_SetMin(OldIndexNode, st_Min(StIndex)); + + subst_Delete(StIndex->subst); + + StIndex->subst = ComGen; + StIndex->entries = list_Nil(); + StIndex->subnodes = list_Cons(st_NodeAddLeaf(SubstNew, MinMax, Pointer), + list_List(OldIndexNode)); + + if (st_Max(StIndex) < MinMax) + st_SetMax(StIndex, MinMax); + else if (st_Min(StIndex) > MinMax) + st_SetMin(StIndex, MinMax); +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * MERGING OF INDEX NODES * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +static void st_NodeMergeWithSon(st_INDEX StIndex) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + st_INDEX SubNode; + + SubNode = (st_INDEX)list_Car(StIndex->subnodes); + + list_Delete(StIndex->subnodes); + + StIndex->subst = subst_Merge(SubNode->subst, StIndex->subst); + StIndex->entries = SubNode->entries; + StIndex->subnodes = SubNode->subnodes; + st_SetMax(StIndex, st_Max(SubNode)); + st_SetMin(StIndex, st_Min(SubNode)); + + subst_Delete(SubNode->subst); + + st_Free(SubNode); +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * VARIABLE HANDLING FOR TERMS AND SUBSTS. * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +static void st_CloseUsedVariables(const CONTEXT Context, LIST NodeList) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + for (; list_Exist(NodeList); NodeList = list_Cdr(NodeList)) { + SUBST Subst; + + for (Subst = ((st_INDEX)list_Car(NodeList))->subst; + subst_Exist(Subst); + Subst = subst_Next(Subst)) + if (!cont_VarIsUsed(Context, subst_Dom(Subst))) + cont_CreateClosedBinding(Context, subst_Dom(Subst)); + + if (!st_IsLeaf((st_INDEX)list_Car(NodeList))) + st_CloseUsedVariables(Context, ((st_INDEX)list_Car(NodeList))->subnodes); + } +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * HEURISTICS FOR INSERTION OF TERMS AND SUBSTS. * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +static st_INDEX st_FirstVariant(const CONTEXT Context, LIST Subnodes, st_INDEX* BestNonVariant) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + st_INDEX EmptyVariant; + + for (EmptyVariant = NULL, *BestNonVariant = NULL; + list_Exist(Subnodes); + Subnodes = list_Cdr(Subnodes)) { + st_INDEX CurrentNode; + + CurrentNode = (st_INDEX)list_Car(Subnodes); + + cont_StartBinding(); + + if (subst_Variation(Context, CurrentNode->subst)) { + if (subst_Exist(CurrentNode->subst)) { + subst_CloseVariables(Context, CurrentNode->subst); + + return CurrentNode; + } else + EmptyVariant = CurrentNode; + + } else if (*BestNonVariant == NULL) + if (subst_MatchTops(Context, CurrentNode->subst)) + *BestNonVariant = CurrentNode; + + cont_BackTrack(); + } + + return EmptyVariant; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INSERTION OF TERMS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +void st_EntryCreate(st_INDEX StIndex, POINTER Pointer, TERM Term, const CONTEXT Context) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + st_INDEX Current; + st_INDEX BestNonVariant; + SYMBOL FirstDomain; + st_MINMAX MinMax; + + cont_Check(); + + MinMax = term_ComputeSize(Term); + + /* CREATE INITIAL BINDING AND INITIALIZE LOCAL VARIABLES */ + FirstDomain = cont_NextIndexVariable(Context); + cont_CreateBinding(Context, FirstDomain, Context, Term); + + Current = StIndex; + + if (st_Max(Current) < MinMax) + st_SetMax(Current, MinMax); + else if (st_Min(Current) > MinMax) + st_SetMin(Current, MinMax); + + /* FIND "LAST" VARIATION */ + while (!st_IsLeaf(Current) && + (Current = st_FirstVariant(Context, Current->subnodes, &BestNonVariant))) { + if (st_Max(Current) < MinMax) + st_SetMax(Current, MinMax); + else if (st_Min(Current) > MinMax) + st_SetMin(Current, MinMax); + + StIndex = Current; + } + + if (cont_BindingsSinceLastStart()==0 && Current && st_IsLeaf(Current)) { + + /* INSERT ENTRY EQUAL MODULO RENAMING */ + Current->entries = list_Cons(Pointer, Current->entries); + + } else if (BestNonVariant) { + + /* CREATE INNER NODE AND A NEW LEAF */ + SUBST ComGen, SubstOld, SubstNew; + + if (!st_IsLeaf(BestNonVariant)) + st_CloseUsedVariables(Context, BestNonVariant->subnodes); + + ComGen = subst_ComGen(Context, BestNonVariant->subst, &SubstOld, &SubstNew); + + st_NodeAddInner(BestNonVariant, + SubstOld, + subst_CloseOpenVariables(SubstNew), + ComGen, + MinMax, + Pointer); + + } else + + /* ADD A SINGLE LEAF NODE TO FATHER */ + StIndex->subnodes = + list_Cons(st_NodeAddLeaf(subst_CloseOpenVariables(subst_Nil()), MinMax, + Pointer), + StIndex->subnodes); + + cont_Reset(); +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * DELETION OF INDEX * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +void st_IndexDelete(st_INDEX StIndex) +/************************************************************** + INPUT: A pointer to an existing St-Index. + SUMMARY: Deletes the whole index structure. +***************************************************************/ +{ + if (StIndex == NULL) + return; + else if (st_IsLeaf(StIndex)) + list_Delete(StIndex->entries); + else + /* Recursion */ + list_DeleteWithElement(StIndex->subnodes, (void (*)(POINTER))st_IndexDelete); + + subst_Delete(StIndex->subst); + st_Free(StIndex); +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * DELETION OF ENTRY FOR TERMS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +static st_INDEX st_EntryDeleteHelp(const CONTEXT Context, st_INDEX StIndex, POINTER Pointer, + BOOL* Found) +/************************************************************** + INPUT: The root of an abstraction tree (StIndex), a + pointer to a specific entry of the tree and + a query term. + RETURNS: Nothing. + SUMMARY: Uses Term in order to find Pointer in the tree. + EFFECTS: Will delete nodes of StIndex. +***************************************************************/ +{ + if (st_IsLeaf(StIndex)) { + + *Found = list_DeleteFromList(&(StIndex->entries), Pointer); + + if (list_Exist(StIndex->entries)) + return StIndex; + else { + subst_Delete(StIndex->subst); + st_Free(StIndex); + + return NULL; + } + + } else { + + LIST Subnodes; + + for (Subnodes = StIndex->subnodes; + list_Exist(Subnodes); + Subnodes = list_Cdr(Subnodes)) { + st_INDEX CurrentNode; + + CurrentNode = (st_INDEX)list_Car(Subnodes); + + cont_StartBinding(); + + if (subst_Variation(Context, CurrentNode->subst)) { + list_Rplaca(Subnodes, st_EntryDeleteHelp(Context, + CurrentNode, + Pointer, + Found)); + if (*Found) { + if (list_DeleteFromList(&(StIndex->subnodes), NULL)) + if (list_Empty(list_Cdr(StIndex->subnodes))) { + /* 'StIndex' has one subnode only. */ + st_NodeMergeWithSon(StIndex); + + return StIndex; + } + + /* Assertion: 'StIndex' is an inner node. */ + + CurrentNode = (st_INDEX)list_Car(StIndex->subnodes); + st_SetMax(StIndex, st_Max(CurrentNode)); + st_SetMin(StIndex, st_Min(CurrentNode)); + + for (Subnodes = list_Cdr(StIndex->subnodes); + list_Exist(Subnodes); + Subnodes = list_Cdr(Subnodes)) { + CurrentNode = (st_INDEX)list_Car(Subnodes); + + if (st_Max(CurrentNode) > st_Max(StIndex)) + st_SetMax(StIndex, st_Max(CurrentNode)); + + if (st_Min(CurrentNode) < st_Min(StIndex)) + st_SetMin(StIndex, st_Min(CurrentNode)); + } + + return StIndex; + } + } + + cont_BackTrack(); + } + + return StIndex; + } +} + + +BOOL st_EntryDelete(st_INDEX StIndex, POINTER Pointer, TERM Term, const CONTEXT Context) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + BOOL Found; + LIST Subnodes; + SYMBOL FirstDomain; + + cont_Check(); + + FirstDomain = symbol_FirstIndexVariable(); + cont_CreateBinding(Context, FirstDomain, Context, Term); + + for (Found = FALSE, Subnodes = StIndex->subnodes; + list_Exist(Subnodes); + Subnodes = list_Cdr(Subnodes)) { + st_INDEX CurrentNode; + + CurrentNode = (st_INDEX)list_Car(Subnodes); + + cont_StartBinding(); + + if (subst_Variation(Context, CurrentNode->subst)) { + list_Rplaca(Subnodes, st_EntryDeleteHelp(Context, CurrentNode, Pointer, &Found)); + + if (Found) { + StIndex->subnodes = list_PointerDeleteElement(StIndex->subnodes, NULL); + + if (list_Exist(StIndex->subnodes)) { + CurrentNode = (st_INDEX)list_Car(StIndex->subnodes); + st_SetMax(StIndex, st_Max(CurrentNode)); + st_SetMin(StIndex, st_Min(CurrentNode)); + + for (Subnodes = list_Cdr(StIndex->subnodes); + list_Exist(Subnodes); + Subnodes = list_Cdr(Subnodes)) { + CurrentNode = (st_INDEX)list_Car(Subnodes); + + if (st_Max(CurrentNode) > st_Max(StIndex)) + st_SetMax(StIndex, st_Max(CurrentNode)); + + if (st_Min(CurrentNode) < st_Min(StIndex)) + st_SetMin(StIndex, st_Min(CurrentNode)); + } + } else { + st_SetMax(StIndex, 0); + st_SetMin(StIndex, 0); + } + + break; + } + } + + cont_BackTrack(); + } + + cont_Reset(); + + return Found; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * RETRIEVAL FOR TERMS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +static LIST st_TraverseTreeUnifier(CONTEXT IndexContext, st_INDEX StIndex) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + int Save; + LIST Result, CurrentList; + st_INDEX CurrentNode; + + /* PREPARE TRAVERSAL */ + Save = stack_Bottom(); + + Result = list_Nil(); + CurrentList = StIndex->subnodes; + + cont_StartBinding(); + + for (;;) { + + /* BACKTRACK A BIG STEP */ + if (list_Empty(CurrentList)) { + cont_StopAndBackTrack(); + + if (stack_Empty(Save)) + return Result; + + CurrentList = stack_PopResult(); + } + + /* DESCENDING */ + for (CurrentNode = (st_INDEX)list_Car(CurrentList); + subst_Unify(IndexContext, CurrentNode->subst); + CurrentList = CurrentNode->subnodes, + CurrentNode = (st_INDEX)list_Car(CurrentList)) + if (st_IsLeaf(CurrentNode)) { + Result = list_Append(CurrentNode->entries, Result); + break; + } else if (list_Exist(list_Cdr(CurrentList))) { + stack_Push(list_Cdr(CurrentList)); + cont_StartBinding(); + } else + cont_StopAndStartBinding(); + + /* BACKTRACK LEAF OR INNER NODE */ + CurrentList = list_Cdr(CurrentList); + cont_BackTrackAndStart(); + } +} + + +static LIST st_TraverseTreeGen(CONTEXT IndexContext, st_INDEX StIndex) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + int Save; + LIST Result, CurrentList; + st_INDEX CurrentNode; + + /* PREPARE TRAVERSAL */ + Save = stack_Bottom(); + + Result = list_Nil(); + CurrentList = StIndex->subnodes; + + cont_StartBinding(); + + for (;;) { + + /* BACKTRACK A BIG STEP */ + if (list_Empty(CurrentList)) { + cont_StopAndBackTrack(); + + if (stack_Empty(Save)) + return Result; + + CurrentList = stack_PopResult(); + } + + /* DESCENDING */ + for (CurrentNode = (st_INDEX)list_Car(CurrentList); + subst_Match(IndexContext, CurrentNode->subst); + CurrentList = CurrentNode->subnodes, + CurrentNode = (st_INDEX)list_Car(CurrentList)) + if (st_IsLeaf(CurrentNode)) { + Result = list_Append(CurrentNode->entries, Result); + break; + } else if (list_Cdr(CurrentList)) { + stack_Push(list_Cdr(CurrentList)); + cont_StartBinding(); + } else + cont_StopAndStartBinding(); + + /* BACKTRACK LEAF OR INNER NODE */ + CurrentList = list_Cdr(CurrentList); + cont_BackTrackAndStart(); + } +} + + +static LIST st_TraverseTreeInstance(CONTEXT IndexContext, st_INDEX StIndex) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + int Save; + LIST Result, CurrentList; + st_INDEX CurrentNode; + + /* PREPARE TRAVERSAL */ + Save = stack_Bottom(); + + Result = list_Nil(); + CurrentList = StIndex->subnodes; + + cont_StartBinding(); + + for (;;) { + + /* BACKTRACK A BIG STEP */ + if (list_Empty(CurrentList)) { + cont_StopAndBackTrack(); + + if (stack_Empty(Save)) + return Result; + + CurrentList = stack_PopResult(); + } + + /* DESCENDING */ + for (CurrentNode = (st_INDEX)list_Car(CurrentList); + subst_MatchReverse(IndexContext, CurrentNode->subst); + CurrentList = CurrentNode->subnodes, + CurrentNode = (st_INDEX)list_Car(CurrentList)) + if (st_IsLeaf(CurrentNode)) { + Result = list_Append(CurrentNode->entries, Result); + break; + } else if (list_Cdr(CurrentList)) { + stack_Push(list_Cdr(CurrentList)); + cont_StartBinding(); + } else + cont_StopAndStartBinding(); + + /* BACKTRACK LEAF OR INNER NODE */ + CurrentList = list_Cdr(CurrentList); + cont_BackTrackAndStart(); + } +} + + +static LIST st_TraverseTreeGenPreTest(CONTEXT IndexContext, + st_INDEX StIndex, + st_MINMAX MinMax) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + int Save; + LIST Result, CurrentList; + st_INDEX CurrentNode; + + /* PREPARE TRAVERSAL */ + Save = stack_Bottom(); + + Result = list_Nil(); + CurrentList = StIndex->subnodes; + + cont_StartBinding(); + + for (;;) { + + /* BACKTRACK A BIG STEP */ + if (list_Empty(CurrentList)) { + cont_StopAndBackTrack(); + + if (stack_Empty(Save)) + return Result; + + CurrentList = stack_PopResult(); + } + + /* DESCENDING */ + for (CurrentNode = (st_INDEX)list_Car(CurrentList); + (MinMax >= st_Min(CurrentNode)) && + subst_Match(IndexContext, CurrentNode->subst); + CurrentList = CurrentNode->subnodes, + CurrentNode = (st_INDEX)list_Car(CurrentList)) + if (st_IsLeaf(CurrentNode)) { + Result = list_Append(CurrentNode->entries, Result); + break; + } else if (list_Cdr(CurrentList)) { + stack_Push(list_Cdr(CurrentList)); + cont_StartBinding(); + } else + cont_StopAndStartBinding(); + + /* BACKTRACK LEAF OR INNER NODE */ + CurrentList = list_Cdr(CurrentList); + cont_BackTrackAndStart(); + } +} + + +static LIST st_TraverseTreeInstancePreTest(CONTEXT IndexContext, st_INDEX StIndex, st_MINMAX MinMax) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + int Save; + LIST Result, CurrentList; + st_INDEX CurrentNode; + + /* PREPARE TRAVERSAL */ + Save = stack_Bottom(); + + Result = list_Nil(); + CurrentList = StIndex->subnodes; + + cont_StartBinding(); + + for (;;) { + + /* BACKTRACK A BIG STEP */ + if (list_Empty(CurrentList)) { + cont_StopAndBackTrack(); + + if (stack_Empty(Save)) + return Result; + + CurrentList = stack_PopResult(); + } + + /* DESCENDING */ + for (CurrentNode = (st_INDEX)list_Car(CurrentList); + (MinMax <= st_Max(CurrentNode)) && + subst_MatchReverse(IndexContext, CurrentNode->subst); + CurrentList = CurrentNode->subnodes, + CurrentNode = (st_INDEX)list_Car(CurrentList)) + if (st_IsLeaf(CurrentNode)) { + Result = list_Append(CurrentNode->entries, Result); + break; + } else if (list_Cdr(CurrentList)) { + stack_Push(list_Cdr(CurrentList)); + cont_StartBinding(); + } else + cont_StopAndStartBinding(); + + /* BACKTRACK LEAF OR INNER NODE */ + CurrentList = list_Cdr(CurrentList); + cont_BackTrackAndStart(); + } +} + + +LIST st_GetUnifier(CONTEXT IndexContext, st_INDEX StIndex, CONTEXT TermContext, TERM Term) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + LIST Result; + SYMBOL FirstDomain; + + cont_Check(); + + FirstDomain = symbol_FirstIndexVariable(); + cont_CreateBinding(IndexContext, FirstDomain, TermContext, Term); + + Result = st_TraverseTreeUnifier(IndexContext, StIndex); + + cont_Reset(); + + return Result; +} + + +LIST st_GetGen(CONTEXT IndexContext, st_INDEX StIndex, TERM Term) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + LIST Result; + SYMBOL FirstDomain; + + cont_Check(); + + FirstDomain = symbol_FirstIndexVariable(); + cont_CreateBinding(IndexContext, FirstDomain, cont_InstanceContext(), Term); + + Result = st_TraverseTreeGen(IndexContext, StIndex); + + cont_Reset(); + + return Result; +} + + +LIST st_GetGenPreTest(CONTEXT IndexContext, st_INDEX StIndex, TERM Term) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + LIST Result; + SYMBOL FirstDomain; + + cont_Check(); + + FirstDomain = symbol_FirstIndexVariable(); + cont_CreateBinding(IndexContext, FirstDomain, cont_InstanceContext(), Term); + + Result = st_TraverseTreeGenPreTest(IndexContext, StIndex, term_ComputeSize(Term)); + + cont_Reset(); + + return Result; +} + + +LIST st_GetInstance(CONTEXT IndexContext, st_INDEX StIndex, TERM Term) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + LIST Result; + SYMBOL FirstDomain; + + cont_Check(); + + FirstDomain = symbol_FirstIndexVariable(); + cont_CreateBinding(IndexContext, FirstDomain, IndexContext, Term); + + Result = st_TraverseTreeInstance(IndexContext, StIndex); + + cont_Reset(); + + return Result; +} + + +LIST st_GetInstancePreTest(CONTEXT IndexContext, st_INDEX StIndex, TERM Term) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + LIST Result; + SYMBOL FirstDomain; + + cont_Check(); + + FirstDomain = symbol_FirstIndexVariable(); + cont_CreateBinding(IndexContext, FirstDomain, IndexContext, Term); + + Result = st_TraverseTreeInstancePreTest(IndexContext, StIndex, term_ComputeSize(Term)); + + cont_Reset(); + + return Result; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INCREMENTAL RETRIEVAL * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +static POINTER st_TraverseForExistUnifier(CONTEXT IndexContext) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + LIST CurrentList; + st_INDEX CurrentNode; + + /* Caution: In case an entry is found + the procedure returns immediately + without backtracking the current bindings. */ + + CurrentList = list_Nil(); + + for (;;) { + + /* BACKTRACK A BIG STEP */ + if (list_Empty(CurrentList)) { + cont_StopAndBackTrack(); + + if (st_StackEmpty(st_STACKSAVE)) + return NULL; + + CurrentList = st_StackPopResult(); + } + + /* DESCENDING */ + for (CurrentNode = (st_INDEX)list_Car(CurrentList); + subst_Unify(IndexContext, CurrentNode->subst); + CurrentList = CurrentNode->subnodes, + CurrentNode = (st_INDEX)list_Car(CurrentList)) { + if (list_Exist(list_Cdr(CurrentList))) { + st_StackPush(list_Cdr(CurrentList)); + cont_StartBinding(); + } else + cont_StopAndStartBinding(); + + if (st_IsLeaf(CurrentNode)) { + st_StackPush(list_Cdr(CurrentNode->entries)); + return list_Car(CurrentNode->entries); + } + } + + /* BACKTRACK LEAF OR INNER NODE */ + CurrentList = list_Cdr(CurrentList); + cont_BackTrackAndStart(); + } +} + + +static POINTER st_TraverseForExistGen(CONTEXT IndexContext) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + LIST CurrentList; + st_INDEX CurrentNode; + + /* Caution: In case an entry is found + the procedure returns immediately + without backtracking the current bindings. */ + + CurrentList = list_Nil(); + + for (;;) { + + /* BACKTRACK A BIG STEP */ + if (list_Empty(CurrentList)) { + cont_StopAndBackTrack(); + + if (st_StackEmpty(st_STACKSAVE)) + return NULL; + + CurrentList = st_StackPopResult(); + } + + /* DESCENDING */ + for (CurrentNode = (st_INDEX)list_Car(CurrentList); + subst_Match(IndexContext, CurrentNode->subst); + CurrentList = CurrentNode->subnodes, + CurrentNode = (st_INDEX)list_Car(CurrentList)) { + if (list_Exist(list_Cdr(CurrentList))) { + st_StackPush(list_Cdr(CurrentList)); + cont_StartBinding(); + } else + cont_StopAndStartBinding(); + + if (st_IsLeaf(CurrentNode)) { + st_StackPush(list_Cdr(CurrentNode->entries)); + return list_Car(CurrentNode->entries); + } + } + + /* BACKTRACK LEAF OR INNER NODE */ + CurrentList = list_Cdr(CurrentList); + cont_BackTrackAndStart(); + } +} + + +static POINTER st_TraverseForExistGenPreTest(CONTEXT IndexContext) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + LIST CurrentList; + st_INDEX CurrentNode; + + /* Caution: In case an entry is found + the procedure returns immediately + without backtracking the current bindings. */ + + CurrentList = list_Nil(); + + for (;;) { + + /* BACKTRACK A BIG STEP */ + if (list_Empty(CurrentList)) { + cont_StopAndBackTrack(); + + if (st_StackEmpty(st_STACKSAVE)) + return NULL; + + CurrentList = st_StackPopResult(); + } + + /* DESCENDING */ + for (CurrentNode = (st_INDEX)list_Car(CurrentList); + (st_EXIST_MINMAX >= st_Min(CurrentNode)) && + subst_Match(IndexContext, CurrentNode->subst); + CurrentList = CurrentNode->subnodes, + CurrentNode = (st_INDEX)list_Car(CurrentList)) { + if (list_Exist(list_Cdr(CurrentList))) { + st_StackPush(list_Cdr(CurrentList)); + cont_StartBinding(); + } else + cont_StopAndStartBinding(); + + if (st_IsLeaf(CurrentNode)) { + st_StackPush(list_Cdr(CurrentNode->entries)); + return list_Car(CurrentNode->entries); + } + } + + /* BACKTRACK LEAF OR INNER NODE */ + CurrentList = list_Cdr(CurrentList); + cont_BackTrackAndStart(); + } +} + + +static POINTER st_TraverseForExistInstance(CONTEXT IndexContext) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + LIST CurrentList; + st_INDEX CurrentNode; + + /* Caution: In case an entry is found + the procedure returns immediately + without backtracking the current bindings. */ + + CurrentList = list_Nil(); + + for (;;) { + + /* BACKTRACK A BIG STEP */ + if (list_Empty(CurrentList)) { + cont_StopAndBackTrack(); + + if (st_StackEmpty(st_STACKSAVE)) + return NULL; + + CurrentList = st_StackPopResult(); + } + + /* DESCENDING */ + for (CurrentNode = (st_INDEX)list_Car(CurrentList); + subst_MatchReverse(IndexContext, CurrentNode->subst); + CurrentList = CurrentNode->subnodes, + CurrentNode = (st_INDEX)list_Car(CurrentList)) { + if (list_Exist(list_Cdr(CurrentList))) { + st_StackPush(list_Cdr(CurrentList)); + cont_StartBinding(); + } else + cont_StopAndStartBinding(); + + if (st_IsLeaf(CurrentNode)) { + st_StackPush(list_Cdr(CurrentNode->entries)); + return list_Car(CurrentNode->entries); + } + } + + /* BACKTRACK LEAF OR INNER NODE */ + CurrentList = list_Cdr(CurrentList); + cont_BackTrackAndStart(); + } +} + + +static POINTER st_TraverseForExistInstancePreTest(CONTEXT IndexContext) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + LIST CurrentList; + st_INDEX CurrentNode; + + /* Caution: In case an entry is found + the procedure returns immediately + without backtracking the current bindings. */ + + CurrentList = list_Nil(); + + for (;;) { + + /* BACKTRACK A BIG STEP */ + if (list_Empty(CurrentList)) { + cont_StopAndBackTrack(); + + if (st_StackEmpty(st_STACKSAVE)) + return NULL; + + CurrentList = st_StackPopResult(); + } + + /* DESCENDING */ + for (CurrentNode = (st_INDEX)list_Car(CurrentList); + (st_EXIST_MINMAX <= st_Max(CurrentNode)) && + subst_MatchReverse(IndexContext, CurrentNode->subst); + CurrentList = CurrentNode->subnodes, + CurrentNode = (st_INDEX)list_Car(CurrentList)) { + if (list_Exist(list_Cdr(CurrentList))) { + st_StackPush(list_Cdr(CurrentList)); + cont_StartBinding(); + } else + cont_StopAndStartBinding(); + + if (st_IsLeaf(CurrentNode)) { + st_StackPush(list_Cdr(CurrentNode->entries)); + return list_Car(CurrentNode->entries); + } + } + + /* BACKTRACK LEAF OR INNER NODE */ + CurrentList = list_Cdr(CurrentList); + cont_BackTrackAndStart(); + } +} + + +void st_CancelExistRetrieval(void) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + if (st_CURRENT_RETRIEVAL != st_NOP) { + +#ifdef CHECK + cont_CheckState(); +#endif + + st_StackSetBottom(st_STACKSAVE); + + switch (st_WHICH_CONTEXTS) { + + case st_STANDARD: + cont_Reset(); + break; + + case st_NOC: + break; + + default: + misc_StartErrorReport(); + misc_ErrorReport("\n In st_CancelExistRetrieval: Unknown context type.\n"); + misc_FinishErrorReport(); + } + + st_CURRENT_RETRIEVAL = st_NOP; + st_WHICH_CONTEXTS = st_NOC; + st_INDEX_CONTEXT = NULL; + st_EXIST_MINMAX = 0; + } +} + + +POINTER st_ExistUnifier(CONTEXT IndexContext, st_INDEX StIndex, CONTEXT TermContext, TERM Term) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + SYMBOL FirstDomain; + POINTER Result; + +#ifdef CHECK + if (!st_StackEmpty(st_STACKSAVE)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_ExistUnifier: ST-Stack not empty.\n"); + misc_FinishErrorReport(); + } else if (st_CURRENT_RETRIEVAL != st_NOP) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_ExistUnifier: %d Retrieval already in progress.\n", + st_CURRENT_RETRIEVAL); + misc_FinishErrorReport(); + } +#endif + + cont_Check(); + + if (st_Exist(StIndex)) { + + st_CURRENT_RETRIEVAL = st_UNIFIER; + st_WHICH_CONTEXTS = st_STANDARD; + st_INDEX_CONTEXT = IndexContext; + + st_STACKSAVE = st_StackBottom(); + + FirstDomain = symbol_FirstIndexVariable(); + cont_CreateBinding(IndexContext, FirstDomain, TermContext, Term); + + cont_StartBinding(); + st_StackPush(StIndex->subnodes); + cont_StartBinding(); + + Result = st_TraverseForExistUnifier(IndexContext); + +#ifdef CHECK + cont_SaveState(); +#endif + + if (Result == NULL) + st_CancelExistRetrieval(); + + return Result; + } else + return NULL; +} + + +POINTER st_ExistGen(CONTEXT IndexContext, st_INDEX StIndex, TERM Term) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + SYMBOL FirstDomain; + POINTER Result; + +#ifdef CHECK + if (!st_StackEmpty(st_STACKSAVE)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_ExistGen: ST-Stack not empty.\n"); + misc_FinishErrorReport(); + } + else + if (st_CURRENT_RETRIEVAL != st_NOP) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_ExistGen: %d Retrieval already in progress.\n", + st_CURRENT_RETRIEVAL); + misc_FinishErrorReport(); + } +#endif + + cont_Check(); + + if (st_Exist(StIndex)) { + + st_CURRENT_RETRIEVAL = st_GEN; + st_WHICH_CONTEXTS = st_STANDARD; + st_INDEX_CONTEXT = IndexContext; + + st_STACKSAVE = st_StackBottom(); + + FirstDomain = symbol_FirstIndexVariable(); + cont_CreateBinding(IndexContext, FirstDomain, cont_InstanceContext(), Term); + + cont_StartBinding(); + st_StackPush(StIndex->subnodes); + cont_StartBinding(); + + Result = st_TraverseForExistGen(IndexContext); + +#ifdef CHECK + cont_SaveState(); +#endif + + if (Result == NULL) + st_CancelExistRetrieval(); + + return Result; + } else + return NULL; +} + + +POINTER st_ExistGenPreTest(CONTEXT IndexContext, st_INDEX StIndex, TERM Term) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + SYMBOL FirstDomain; + POINTER Result; + +#ifdef CHECK + if (!st_StackEmpty(st_STACKSAVE)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_ExistGenPreTest: ST-Stack not empty.\n"); + misc_FinishErrorReport(); + } + else + if (st_CURRENT_RETRIEVAL != st_NOP) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_ExistGenPreTest: %d Retrieval already in progress.\n", + st_CURRENT_RETRIEVAL); + misc_FinishErrorReport(); + } +#endif + + cont_Check(); + + if (st_Exist(StIndex)) { + + st_CURRENT_RETRIEVAL = st_GENPRETEST; + st_WHICH_CONTEXTS = st_STANDARD; + st_INDEX_CONTEXT = IndexContext; + + st_STACKSAVE = st_StackBottom(); + + + FirstDomain = symbol_FirstIndexVariable(); + st_EXIST_MINMAX = term_ComputeSize(Term); + cont_CreateBinding(IndexContext, FirstDomain, IndexContext, Term); + + cont_StartBinding(); + st_StackPush(StIndex->subnodes); + cont_StartBinding(); + + Result = st_TraverseForExistGenPreTest(IndexContext); + +#ifdef CHECK + cont_SaveState(); +#endif + + if (Result == NULL) + st_CancelExistRetrieval(); + + return Result; + } else + return NULL; +} + + +POINTER st_ExistInstance(CONTEXT IndexContext, st_INDEX StIndex, TERM Term) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + SYMBOL FirstDomain; + POINTER Result; + +#ifdef CHECK + if (!st_StackEmpty(st_STACKSAVE)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_ExistInstance: ST-Stack not empty.\n"); + misc_FinishErrorReport(); + } + else + if (st_CURRENT_RETRIEVAL != st_NOP) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_ExistInstance: %d Retrieval already in progress.\n", + st_CURRENT_RETRIEVAL); + misc_FinishErrorReport(); + } +#endif + + cont_Check(); + + if (st_Exist(StIndex)) { + + st_CURRENT_RETRIEVAL = st_INSTANCE; + st_WHICH_CONTEXTS = st_STANDARD; + st_INDEX_CONTEXT = IndexContext; + + st_STACKSAVE = st_StackBottom(); + + FirstDomain = symbol_FirstIndexVariable(); + cont_CreateBinding(IndexContext, FirstDomain, IndexContext, Term); + + cont_StartBinding(); + st_StackPush(StIndex->subnodes); + cont_StartBinding(); + + Result = st_TraverseForExistInstance(IndexContext); + +#ifdef CHECK + cont_SaveState(); +#endif + + if (Result == NULL) + st_CancelExistRetrieval(); + + return Result; + } else + return NULL; +} + + +POINTER st_ExistInstancePreTest(CONTEXT IndexContext, st_INDEX StIndex, TERM Term) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + SYMBOL FirstDomain; + POINTER Result; + +#ifdef CHECK + if (!st_StackEmpty(st_STACKSAVE)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_ExistInstancePreTest: ST-Stack not empty.\n"); + misc_FinishErrorReport(); + } + else + if (st_CURRENT_RETRIEVAL != st_NOP) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_ExistInstancePreTest: %d Retrieval already in progress.\n", + st_CURRENT_RETRIEVAL); + misc_FinishErrorReport(); + } +#endif + + cont_Check(); + + if (st_Exist(StIndex)) { + + st_CURRENT_RETRIEVAL = st_INSTANCEPRETEST; + st_WHICH_CONTEXTS = st_STANDARD; + st_INDEX_CONTEXT = IndexContext; + + st_STACKSAVE = st_StackBottom(); + + FirstDomain = symbol_FirstIndexVariable(); + st_EXIST_MINMAX = term_ComputeSize(Term); + cont_CreateBinding(IndexContext, FirstDomain, IndexContext, Term); + + cont_StartBinding(); + st_StackPush(StIndex->subnodes); + cont_StartBinding(); + + Result = st_TraverseForExistInstancePreTest(IndexContext); + +#ifdef CHECK + cont_SaveState(); +#endif + + if (Result == NULL) + st_CancelExistRetrieval(); + + return Result; + } else + return NULL; +} + + +POINTER st_NextCandidate(void) +/************************************************************** + INPUT: + RETURNS: + EFFECTS: +***************************************************************/ +{ + LIST Result; + +#ifdef CHECK + if (st_StackEmpty(st_STACKSAVE)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_NextCandidate: ST-Stack empty.\n"); + misc_FinishErrorReport(); + } + else + if (st_CURRENT_RETRIEVAL == st_NOP) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_NextCandidate: No retrieval in progress.\n"); + misc_FinishErrorReport(); + } + + cont_CheckState(); +#endif + + Result = st_StackPopResult(); + + if (list_Exist(Result)) { + st_StackPush(list_Cdr(Result)); +#ifdef CHECK + cont_SaveState(); +#endif + return list_Car(Result); + } else { + POINTER NewResult; + + NewResult = NULL; + + if (st_WHICH_CONTEXTS == st_STANDARD) + switch (st_CURRENT_RETRIEVAL) { + + case st_UNIFIER: + NewResult = st_TraverseForExistUnifier(st_INDEX_CONTEXT); + break; + + case st_GEN: + NewResult = st_TraverseForExistGen(st_INDEX_CONTEXT); + break; + + case st_GENPRETEST: + NewResult = st_TraverseForExistGenPreTest(st_INDEX_CONTEXT); + break; + + case st_INSTANCE: + NewResult = st_TraverseForExistInstance(st_INDEX_CONTEXT); + break; + + case st_INSTANCEPRETEST: + NewResult = st_TraverseForExistInstancePreTest(st_INDEX_CONTEXT); + + default: + misc_StartErrorReport(); + misc_ErrorReport("\n In st_NextCandidate: Unknown retrieval type.\n"); + misc_FinishErrorReport(); + } + else { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_NextCandidate: Unknown context type.\n"); + misc_FinishErrorReport(); + } + +#ifdef CHECK + cont_SaveState(); +#endif + + if (NewResult == NULL) + st_CancelExistRetrieval(); + + return NewResult; + } +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * OUTPUT * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +static void st_PrintHelp(st_INDEX St, int Position, void (*Print)(POINTER)) +/************************************************************** + INPUT: A node of an St, an indention and a print + function for the entries. + SUMMARY: Prints an St starting at node St. +***************************************************************/ +{ + int i; + + if (St == (st_INDEX)NULL) + return; + + for (i = 0; i < Position; i++) + putchar(' '); + puts("|"); + + for (i = 0; i < Position; i++) + putchar(' '); + fputs("+-", stdout); + + printf(" Max: %d, Min: %d, ", st_Max(St), st_Min(St)); + subst_Print(St->subst); + putchar('\n'); + + if (st_IsLeaf(St)) { + + LIST Scan; + + for (i = 0; i < Position; i++) + putchar(' '); + fputs(" =>", stdout); + + if (Print) + for (Scan = St->entries; Scan != NULL; Scan = list_Cdr(Scan)) { + putchar(' '); + Print(list_Car(Scan)); + } + else + printf(" %d Entries", list_Length(St->entries)); + + putchar('\n'); + + } else { + LIST Scan; + + for (Scan = St->subnodes; Scan != NULL; Scan = list_Cdr(Scan)) + st_PrintHelp(list_Car(Scan), Position + 2, Print); + } +} + + +void st_Print(st_INDEX StIndex, void (*Print)(POINTER)) +/************************************************************** + INPUT: The root of an St. + SUMMARY: Prints a whole St. +***************************************************************/ +{ + LIST Scan; + + if (st_Empty(StIndex)) { + puts("\n\nIndex empty."); + return; + } + + fputs("\n\nroot: ", stdout); + printf(" Max: %d, Min: %d, ", st_Max(StIndex), st_Min(StIndex)); + subst_Print(StIndex->subst); + putchar('\n'); + if (st_IsLeaf(StIndex)) { + fputs(" =>", stdout); + + if (Print) + for (Scan = StIndex->entries; Scan != NULL; Scan = list_Cdr(Scan)) { + putchar(' '); + Print(list_Car(Scan)); + } + else + printf(" %d Entries", list_Length(StIndex->entries)); + + } else + for (Scan = StIndex->subnodes; Scan != NULL; Scan = list_Cdr(Scan)) + st_PrintHelp(list_Car(Scan),2, Print); + puts("\n"); +} diff --git a/test/spass/st.h b/test/spass/st.h new file mode 100644 index 0000000000000000000000000000000000000000..93f9fb634df4f5938e2953cc1068135f0426ec0b --- /dev/null +++ b/test/spass/st.h @@ -0,0 +1,305 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * ST INDEXING * */ +/* * * */ +/* * $Module: ST * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _ST_ +#define _ST_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "foldfg.h" +#include "term.h" +#include "symbol.h" +#include "list.h" + +#include "subst.h" +#include "unify.h" + +/**************************************************************/ +/* Data Structures */ +/**************************************************************/ + +typedef enum {st_NOP, st_UNIFIER, st_GEN, + st_GENPRETEST, st_INSTANCE, st_INSTANCEPRETEST +} st_RETRIEVAL_TYPE; + +typedef enum {st_STANDARD, st_NOC} st_WHERE_TYPE; + +typedef unsigned short int st_MINMAX; + + +/**************************************************************/ +/* Type st_INDEX and Inline Functions */ +/**************************************************************/ + +typedef struct st { + SUBST subst; + LIST subnodes; + LIST entries; + st_MINMAX max, min; +} st_INDEX_NODE, *st_INDEX; + + +static __inline__ st_INDEX st_Get(void) +{ + return (st_INDEX) memory_Malloc(sizeof(st_INDEX_NODE)); +} + +static __inline__ void st_Free(st_INDEX ST) +{ + memory_Free(ST, sizeof(st_INDEX_NODE)); +} + +static __inline__ SUBST st_Subst(st_INDEX ST) +{ + return ST->subst; +} + +static __inline__ LIST st_Entries(st_INDEX ST) +{ + return ST->entries; +} + +static __inline__ LIST st_Subnodes(st_INDEX ST) +{ + return ST->subnodes; +} + +static __inline__ st_MINMAX st_Max(st_INDEX ST) +{ + return ST->max; +} + +static __inline__ void st_SetMax(st_INDEX ST, st_MINMAX Value) +{ + ST->max = Value; +} + +static __inline__ st_MINMAX st_Min(st_INDEX ST) +{ + return ST->min; +} + +static __inline__ void st_SetMin(st_INDEX ST, st_MINMAX Value) +{ + ST->min = Value; +} + +static __inline__ BOOL st_IsLeaf(st_INDEX ST) +{ + return !list_Empty(st_Entries(ST)); +} + +static __inline__ BOOL st_IsInner(st_INDEX ST) +{ + return !list_Empty(st_Subnodes(ST)); +} + +static __inline__ BOOL st_Empty(st_INDEX ST) +{ + return (ST == NULL || (!st_IsLeaf(ST) && !st_IsInner(ST))); +} + +static __inline__ BOOL st_Exist(st_INDEX ST) +{ + return (ST != NULL && (st_IsLeaf(ST) || st_IsInner(ST))); +} + +static __inline__ void st_SetNode(st_INDEX Index, SUBST Subst, + LIST Subnodes, LIST Entries) +{ + Index->subst = Subst; + Index->subnodes = Subnodes; + Index->entries = Entries; +} + +static __inline__ st_INDEX st_CreateNode(SUBST Subst, LIST Subnodes, + LIST Entries) +{ + st_INDEX index; + + index = st_Get(); + st_SetNode(index, Subst, Subnodes, Entries); + + return index; +} + + +typedef enum {st_EMPTY = 1, st_FCT, st_CONST, st_VAR, + st_STAR, st_FIRST} NODETYPE; + + +/**************************************************************/ +/* A special ST-Stack for sequential retrieval operations */ +/**************************************************************/ + +#define st_STACKSIZE 1000 + +typedef POINTER ST_STACK[st_STACKSIZE]; + +extern ST_STACK st_STACK; +extern int st_STACKPOINTER; +extern int st_STACKSAVE; + +/* Stack operations */ + +static __inline__ void st_StackInit(void) +{ + st_STACKPOINTER = 0; +} + +static __inline__ void st_StackPush(POINTER Entry) +{ +#ifdef CHECK + if (st_STACKPOINTER >= st_STACKSIZE) { + misc_StartErrorReport(); + misc_ErrorReport("\n In st_StackPush: ST-Stack Overflow!\n"); + misc_FinishErrorReport(); + } +#endif + + st_STACK[st_STACKPOINTER++] = Entry; +} + +static __inline__ void st_StackPop(void) +{ + --st_STACKPOINTER; +} + +static __inline__ POINTER st_StackPopResult(void) +{ + return st_STACK[--st_STACKPOINTER]; +} + +static __inline__ void st_StackNPop(int N) +{ + st_STACKPOINTER -= N; +} + +static __inline__ POINTER st_StackTop(void) +{ + return st_STACK[st_STACKPOINTER - 1]; +} + +static __inline__ POINTER st_StackNthTop(int N) +{ + return st_STACK[st_STACKPOINTER - (1 + N)]; +} + +static __inline__ void st_StackRplacTop(POINTER Entry) +{ + st_STACK[st_STACKPOINTER - 1] = Entry; +} + +static __inline__ void st_StackRplacNthTop(int N, POINTER Entry) +{ + st_STACK[st_STACKPOINTER - (1 + N)] = Entry; +} + +static __inline__ void st_StackRplacNth(int N, POINTER Entry) +{ + st_STACK[N] = Entry; +} + +static __inline__ int st_StackBottom(void) +{ + return st_STACKPOINTER; +} + +static __inline__ void st_StackSetBottom(int Pointer) +{ + st_STACKPOINTER = Pointer; +} + +static __inline__ BOOL st_StackEmpty(int Pointer) +{ + return st_STACKPOINTER == Pointer; +} + + +/**************************************************************/ +/* Functions for Creation and Deletion of an st_INDEX */ +/**************************************************************/ + +st_INDEX st_IndexCreate(void); +void st_IndexDelete(st_INDEX); + +/**************************************************************/ +/* Add and Remove Entries to an st_INDEX */ +/**************************************************************/ + +void st_EntryCreate(st_INDEX, POINTER, TERM, const CONTEXT); +BOOL st_EntryDelete(st_INDEX, POINTER, TERM, const CONTEXT); + +/**************************************************************/ +/* Functions for Retrieval in the Index */ +/**************************************************************/ + +LIST st_GetUnifier(CONTEXT, st_INDEX, CONTEXT, TERM); +LIST st_GetGen(CONTEXT, st_INDEX, TERM); +LIST st_GetGenPreTest(CONTEXT, st_INDEX, TERM); +LIST st_GetInstance(CONTEXT, st_INDEX, TERM); +LIST st_GetInstancePreTest(CONTEXT, st_INDEX, TERM); + +void st_CancelExistRetrieval(void); + +POINTER st_ExistUnifier(CONTEXT, st_INDEX, CONTEXT, TERM); +POINTER st_ExistGen(CONTEXT, st_INDEX, TERM); +POINTER st_ExistGenPreTest(CONTEXT, st_INDEX, TERM); +POINTER st_ExistInstance(CONTEXT, st_INDEX, TERM); +POINTER st_ExistInstancePreTest(CONTEXT, st_INDEX, TERM); + +POINTER st_NextCandidate(void); + +/**************************************************************/ +/* Function for Output */ +/**************************************************************/ + +void st_Print(st_INDEX, void (*)(POINTER)); + +#endif diff --git a/test/spass/stack.c b/test/spass/stack.c new file mode 100644 index 0000000000000000000000000000000000000000..4d46314d774ed1d4c3988f4ce2632f7c7ae2563a --- /dev/null +++ b/test/spass/stack.c @@ -0,0 +1,55 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * GLOBAL SYSTEM STACK * */ +/* * * */ +/* * $Module: STACK * */ +/* * * */ +/* * Copyright (C) 1999, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "stack.h" + + +/**************************************************************/ +/* Global Variables */ +/**************************************************************/ + +STACK stack_STACK; +NAT stack_POINTER; diff --git a/test/spass/stack.h b/test/spass/stack.h new file mode 100644 index 0000000000000000000000000000000000000000..4572b34b626b4d4a64663ae52063475e24aaa427 --- /dev/null +++ b/test/spass/stack.h @@ -0,0 +1,155 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * GLOBAL SYSTEM STACK * */ +/* * * */ +/* * $Module: STACK * */ +/* * * */ +/* * Copyright (C) 1996, 1998, 1999, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _STACK_ +#define _STACK_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "misc.h" + +/**************************************************************/ +/* More basic types and macros */ +/**************************************************************/ + + +#define stack_SIZE 10000 + +typedef POINTER STACK[stack_SIZE]; + + +/**************************************************************/ +/* Global Variables */ +/**************************************************************/ + +extern STACK stack_STACK; +extern NAT stack_POINTER; + + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +static __inline__ void stack_Init(void) +{ + stack_POINTER = 0; +} + +static __inline__ void stack_Push(POINTER Entry) +{ +#ifdef CHECK + if (stack_POINTER >= stack_SIZE) { + misc_StartErrorReport(); + misc_ErrorReport("\n In stack_Push: Stack Overflow."); + misc_FinishErrorReport(); + } +#endif + + stack_STACK[stack_POINTER++]= Entry; +} + +static __inline__ int stack_Pop(void) +{ + return --stack_POINTER; +} + +static __inline__ POINTER stack_PopResult(void) +{ + return stack_STACK[--stack_POINTER]; +} + +static __inline__ void stack_NPop(NAT N) +{ + stack_POINTER -= N; +} + +static __inline__ POINTER stack_Top(void) +{ + return stack_STACK[stack_POINTER-1]; +} + +static __inline__ POINTER stack_NthTop(NAT N) +{ + return stack_STACK[stack_POINTER-(1+N)]; +} + +static __inline__ void stack_RplacTop(POINTER Entry) +{ + stack_STACK[stack_POINTER-1] = Entry; +} + +static __inline__ void stack_RplacNthTop(NAT N, POINTER Entry) +{ + stack_STACK[stack_POINTER-(1+N)] = Entry; +} + +static __inline__ void stack_RplacNth(NAT N, POINTER Entry) +{ + stack_STACK[N] = Entry; +} + +static __inline__ NAT stack_Bottom(void) +{ + return stack_POINTER; +} + +static __inline__ void stack_SetBottom(NAT Ptr) +{ + stack_POINTER = Ptr; +} + +static __inline__ BOOL stack_Empty(NAT Ptr) +{ + return stack_POINTER == Ptr; +} + + +#endif + + diff --git a/test/spass/strings.c b/test/spass/strings.c new file mode 100644 index 0000000000000000000000000000000000000000..bd0b2ed1fe61f982e9c90f27660e503afba7722e --- /dev/null +++ b/test/spass/strings.c @@ -0,0 +1,325 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * STRING HANDLING * */ +/* * * */ +/* * $Module: STRINGS * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 35442 $ * */ +/* $State$ * */ +/* $Date: 2007-03-28 17:24:40 -0700 (Wed, 28 Mar 2007) $ * */ +/* $Author: jeffc $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include <ctype.h> +#include "stringsx.h" +#include "list.h" + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + + + +BOOL string_StringIsNumber(const char* String) +/************************************************************** + INPUT: A string. + RETURNS: TRUE iff the string solely consists of number characters. +***************************************************************/ +{ + int i; + + if (String == NULL || String[0] == '\0') + return FALSE; + + i = 0; + + while (String[i] != '\0') + if (String[i] >= '0' && String[i] <= '9') + i++; + else + return FALSE; + + return TRUE; +} + + +char* string_StringCopy(const char* String) +/************************************************************** + INPUT: A string. + RETURNS: A copy of the string. + EFFECT: The memory for the copy is allocated by the memory module. +***************************************************************/ +{ + char *copy; + + copy = (char *) memory_Malloc(strlen(String)+1); + strcpy(copy, String); + return copy; +} + + +void string_StringFree(char* String) +/************************************************************** + INPUT: A string. + RETURNS: Nothing. + EFFECT: Frees the memory used by the string. +***************************************************************/ +{ + memory_Free(String, strlen(String)+1); +} + + +char* string_IntToString(int Number) +/************************************************************** + INPUT: An integer number. + RETURNS: The number as a string. + EFFECT: Memory is allocated for the string. +***************************************************************/ +{ + char* result; + NAT size = 1; + + if (Number > 9) { + size = (NAT)log10((double) Number) + 1; + } else if (Number < 0) { + size = (NAT)log10((double) abs(Number)) + 2; /* including '-' */ + } + size++; /* for '\0' */ + + result = (char *) memory_Malloc(sizeof(char) * size); + sprintf(result, "%d", Number); + return result; +} + + +BOOL string_StringToInt(const char* String, BOOL PrintError, int* Result) +/************************************************************** + INPUT: A string that should represent a decimal number in the + format of the library function strtol, a boolean flag + concerning the printing of error messages and an pointer + to an integer that is used as a return value. + RETURNS: TRUE, if the string could be converted successfully, else FALSE. + EFFECT: This function converts the string a number of type 'int'. + If the string was converted successfully, the value of the + number is stored in <*Result> and the function returns TRUE. + If the number is too big (> INT_MAX), too small (< INT_MIN) + or the string couldn't be converted completely, <*Result> is + set to 0. + If <PrintError> is TRUE, additionally an error message is written + to stderr and the program exits. +***************************************************************/ +{ + long number; + char *end; + + end = (char*)0x1; /* Has to be != NULL, so we take address 1 */ + number = strtol(String, &end, 10); + /* Now <number> is LONG_MAX or LONG_MIN if the string represents a value */ + /* out of range. The variable <end> is set to the first non-converted */ + /* character, e.g. if the string can be converted completely, <end> points */ + /* to the terminating '\0' character. */ + if (number >= INT_MIN && number <= INT_MAX && *end == '\0') { + /* Number was converted successfully */ + *Result = (int)number; + return TRUE; + } else { + /* Number is too large or buffer can't be converted completely */ + *Result = 0; + if (PrintError) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\nString isn't a number or number to large: %s\n", + String); + misc_FinishUserErrorReport(); + } + return FALSE; + } +} + + +char* string_Conc(const char* s1, const char* s2) +/************************************************************** + INPUT: Two strings. + RETURNS: A new string s1.s2 + EFFECTS: Memory is allocated for the new string. +**************************************************************/ +{ + char* dst; + + dst = memory_Malloc(strlen(s1) + strlen(s2) + 1); + strcpy(dst, s1); + return strcat(dst,s2); +} + + +char* string_Nconc(char* s1, char* s2) +/************************************************************** + INPUT: Two strings. + RETURNS: A new string s1.s2. + EFFECTS: s1,s2 are deleted, memory for the new string is + allocated. + CAUTION: Both strings must have been allocated by the memory module! +**************************************************************/ +{ + char* dst; + + dst = memory_Malloc(strlen(s1) + strlen(s2) + 1); + strcpy(dst, s1); + dst = strcat(dst, s2); + + string_StringFree(s1); + string_StringFree(s2); + + return dst; +} + + +char* string_EmptyString(void) +/************************************************************** + INPUT: None. + RETURNS: The empty string. + EFFECT: Memory is allocated for the returned string. +**************************************************************/ +{ + char* s ; + + s = memory_Malloc(1); + s[0] = '\0'; + return s; +} + + +char* string_Prefix(const char* s, int i) +/************************************************************** + INPUT: A string and a string length. + RETURNS: The prefix of <s> of length <i>. + EFFECT: Memory is allocated for the returned string. +**************************************************************/ +{ + char* dst; + + dst = memory_Malloc(i + 1); + strncpy(dst, s, i); + dst[i] = '\0'; + return dst; +} + + +char* string_Suffix(const char* s, int i) +/************************************************************** + INPUT: A string and a string length. + RETURNS: The string that results from cutting the first + <i> characters from string <s>. + Returns the empty string if <i> >= length(s). + EFFECT: Memory is allocated for the returned string. +**************************************************************/ +{ + int l; + char *dst; + + l = strlen(s); + if (i >= l) + return string_EmptyString(); + + dst = memory_Malloc(l - i + 1); + strcpy(dst, s+i); + return dst; +} + + +char** string_Tokens(char* String, int* ArraySize) +/************************************************************** + INPUT: A string <String>. + RETURNS: The function returns an array of white space separated + substrings from <String>. <ArraySize> is set to the + actual size of the returned array. + The array size is the number of substrings + 2, since + the first entry is the program name and the last entry + is NULL. + This is done so to create an array similar to the + "argv" argument of the main() function. + EFFECT: This function breaks the string into several substrings + that don't contain any whitespace characters. + The argument string is modified temporarily within this + function, but it's restored at the end. +***************************************************************/ +{ + char *LastNonSpace, *Scan, Help, **Array; + LIST Substrings; + NAT i; + +#ifdef CHECK + if (String == NULL) { + misc_StartErrorReport(); + misc_ErrorReport("\n In string_Tokens: String is NULL pointer."); + misc_FinishErrorReport(); + } +#endif + + Substrings = list_Nil(); + Scan = String + strlen(String) - 1; + while (Scan >= String) { + while (Scan >= String && isspace((int)*Scan)) + Scan--; + + if (Scan >= String) { + LastNonSpace = Scan; + + do { + Scan--; + } while (Scan >= String && !isspace((int)*Scan)); + + Help = *(LastNonSpace + 1); + *(LastNonSpace + 1) = '\0'; + Substrings = list_Cons(string_StringCopy(Scan+1), Substrings); + *(LastNonSpace + 1) = Help; + } + } + + *ArraySize = list_Length(Substrings) + 2; + Array = memory_Malloc(sizeof(char*) * *ArraySize); + Array[0] = string_StringCopy("SPASS"); + for (i = 1; !list_Empty(Substrings); Substrings = list_Pop(Substrings), i++) + Array[i] = list_Car(Substrings); + Array[i] = NULL; + (*ArraySize)--; + + return Array; +} diff --git a/test/spass/stringsx.h b/test/spass/stringsx.h new file mode 100644 index 0000000000000000000000000000000000000000..7209b4b51fa943ae01fc0b52917b16d4debc57a7 --- /dev/null +++ b/test/spass/stringsx.h @@ -0,0 +1,88 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * STRING HANDLING * */ +/* * * */ +/* * $Module: STRINGS * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 35442 $ * */ +/* $State$ * */ +/* $Date: 2007-03-28 17:24:40 -0700 (Wed, 28 Mar 2007) $ * */ +/* $Author: jeffc $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _STRINGS_ +#define _STRINGS_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include <math.h> +#include "memory.h" + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +static __inline__ BOOL string_Equal(const char* S1, const char* S2) +{ + return strcmp(S1, S2) == 0; +} + + +BOOL string_StringIsNumber(const char*); +char* string_StringCopy(const char*); +void string_StringFree(char*); +char* string_IntToString(int); +BOOL string_StringToInt(const char*, BOOL, int*); +char* string_Conc(const char*, const char*); +char* string_Nconc(char*, char*); +char* string_EmptyString(void); +char* string_Prefix(const char*, int); +char* string_Suffix(const char*, int); +char** string_Tokens(char*, int*); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/spass/subst.c b/test/spass/subst.c new file mode 100644 index 0000000000000000000000000000000000000000..a7d5ea3509a77542a5319c855f06f2076d578180 --- /dev/null +++ b/test/spass/subst.c @@ -0,0 +1,647 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SUBSTITUTION * */ +/* * * */ +/* * $Module: SUBSTITUTION * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "subst.h" + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SUBSTITUTION CREATION AND DELETION * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +SUBST subst_Add(SYMBOL Symbol, TERM Codomain, SUBST Subst) +{ + SUBST Result; + + Result = subst_Get(); + Result->next = Subst; + Result->dom = Symbol; + Result->codomain = Codomain; + + return Result; +} + + +void subst_Delete(SUBST Subst) +{ + SUBST Next; + + while (subst_Exist(Subst)) { + Next = subst_Next(Subst); + + if (subst_Cod(Subst)) + term_Delete(subst_Cod(Subst)); + + subst_FreeOneNode(Subst); + Subst = Next; + } +} + +void subst_Free(SUBST Subst) +{ + SUBST Next; + + while (subst_Exist(Subst)) { + Next = subst_Next(Subst); + subst_FreeOneNode(Subst); + Subst = Next; + } +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * FUNCTIONS ON SUBSTITUTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +TERM subst_Term(SYMBOL Symbol, SUBST Subst) +{ + for (; subst_Exist(Subst); Subst = subst_Next(Subst)) + if (symbol_Equal(Symbol,subst_Dom(Subst))) + return subst_Cod(Subst); + return (TERM)NULL; +} + + +static TERM subst_ApplyIntern(SUBST Subst, TERM Term) +{ + TERM RplacTerm; + LIST Arglist; + SYMBOL Top; + + Top = term_TopSymbol(Term); + + if (symbol_IsVariable(Top) && (RplacTerm = subst_Term(Top,Subst))) { + Arglist = term_CopyTermList(term_ArgumentList(RplacTerm)); + term_RplacTop(Term, term_TopSymbol(RplacTerm)); + term_DeleteTermList(term_ArgumentList(Term)); + term_RplacArgumentList(Term, Arglist); + } else { + for (Arglist = term_ArgumentList(Term); + !list_Empty(Arglist); + Arglist = list_Cdr(Arglist)) + subst_ApplyIntern(Subst, list_Car(Arglist)); + } + + return Term; +} + +TERM subst_Apply(SUBST Subst, TERM Term) +{ + if (subst_Empty(Subst)) + return Term; + + return subst_ApplyIntern(Subst, Term); +} + + +SUBST subst_Merge(SUBST Source, SUBST Drain) +{ + SUBST Scan; + BOOL Changed; + + for (; subst_Exist(Source); Source = subst_Next(Source)) { + + /* Apply current assignment of Source to all */ + /* assignments of Drain. If the current ass. */ + /* cannot be applied to any codomain in Drain */ + /* the current assignment is added to Drain. */ + + Changed = FALSE; + + for (Scan = Drain; + subst_Exist(Scan); + Scan = subst_Next(Scan)) + if (term_SubstituteVariable(Source->dom, + Source->codomain, + &(Scan->codomain))) + Changed = TRUE; + + if (!Changed) + Drain = subst_Add(Source->dom, + term_Copy(Source->codomain), + Drain); + } + + return Drain; +} + +SUBST subst_Compose(SUBST Outer, SUBST Inner) +/************************************************************** + INPUT: Two substitutions. + RETURNS: The substitution corresponding to the composition of + <Outer> and <Inner>. + EFFECT: <Outer> is destructively applied to the codomain of <Inner> + <Inner> is destructively extended +***************************************************************/ +{ + SUBST Scan1,Scan2,New; + + New = subst_Nil(); + + for (Scan1=Outer; subst_Exist(Scan1); Scan1 = subst_Next(Scan1)) { + for (Scan2 = Inner;subst_Exist(Scan2);Scan2 = subst_Next(Scan2)) + term_SubstituteVariable(subst_Dom(Scan1),subst_Cod(Scan1),&(Scan2->codomain)); + if (!subst_BindVar(subst_Dom(Scan1),Inner)) + New = subst_Add(subst_Dom(Scan1), term_Copy(subst_Cod(Scan1)),New); + } + return subst_NUnion(Inner,New); +} + +BOOL subst_BindVar(SYMBOL Var, SUBST Subst) +/************************************************************** + INPUT: A variable symbol and a substitution. + RETURNS: TRUE iff <Var> is contained in the domain of <Subst> +***************************************************************/ +{ + SUBST Scan; + + for (Scan=Subst; subst_Exist(Scan); Scan = subst_Next(Scan)) + if (symbol_Equal(subst_Dom(Scan),Var)) + return TRUE; + + return FALSE; +} + + + +SUBST subst_Copy(SUBST Subst) +{ + SUBST Copy, Result; + + for (Result = subst_Nil(), + Copy = subst_Nil(); + subst_Exist(Subst); + Subst = subst_Next(Subst)) + if (subst_Exist(Result)) { + subst_SetNext(Copy, subst_Add(subst_Dom(Subst), + term_Copy(subst_Cod(Subst)), + subst_Nil())); + Copy = subst_Next(Copy); + } else { + Result = subst_Add(subst_Dom(Subst), + term_Copy(subst_Cod(Subst)), + subst_Nil()); + Copy = Result; + } + + return Result; +} + + +BOOL subst_MatchTops(const CONTEXT Context, SUBST Subst) +{ + for ( ; subst_Exist(Subst); Subst = subst_Next(Subst)) + if (cont_ContextBindingTerm(Context, subst_Dom(Subst)) && + term_EqualTopSymbols(cont_ContextBindingTerm(Context, subst_Dom(Subst)), + subst_Cod(Subst))) + return TRUE; + return FALSE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * UNIFICATION TEST * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +BOOL subst_Unify(CONTEXT IndexContext, SUBST Subst) +/********************************************************* + INPUT: + RETURNS: + CAUTION: 'Subst' IS ASSUMED TO BE NON-EMPTY. +**********************************************************/ +{ + while (subst_Exist(Subst)) { + if (!cont_VarIsBound(IndexContext, subst_Dom(Subst))) { + if (unify_OccurCheck(IndexContext, subst_Dom(Subst), IndexContext, subst_Cod(Subst))) + return FALSE; + else + cont_CreateBinding(IndexContext, subst_Dom(Subst), IndexContext, subst_Cod(Subst)); + } else if (!unify_UnifyAllOC(IndexContext, + IndexContext, + subst_Cod(Subst), + cont_ContextBindingContext(IndexContext, + subst_Dom(Subst)), + cont_ContextBindingTerm(IndexContext, + subst_Dom(Subst)))) + return FALSE; + + Subst = subst_Next(Subst); + } + + return TRUE; +} + +BOOL subst_IsShallow(SUBST Subst) { +/********************************************************** + INPUT: A unifier + RETURNS: TRUE, if the unifier is valid : + a variable or a ground term or a function with only + variables or ground terms as arguments. +***********************************************************/ + SUBST SubstScan; + for (SubstScan = Subst; SubstScan != subst_Nil(); + SubstScan = subst_Next(SubstScan)) { + TERM Codomain = subst_Cod(SubstScan); + if ((!term_IsVariable(Codomain)) + && (!term_IsGround(Codomain))) { + LIST Scan ; + for (Scan = term_ArgumentList(Codomain); Scan != list_Nil(); + Scan = list_Cdr(Scan)) { + if ((!term_IsVariable(list_Car(Scan)) + && (!term_IsGround(list_Car(Scan))))) + return FALSE; + } + } + } + return TRUE; +} + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * GENERALIZATION TEST * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +BOOL subst_Match(const CONTEXT Context, SUBST Subst) +/********************************************************* + INPUT: + RETURNS: + CAUTION: 'Subst' IS ASSUMED TO BE NON-EMPTY. +**********************************************************/ +{ + while (subst_Exist(Subst)) { + if (!cont_VarIsBound(Context, subst_Dom(Subst)) || + !unify_Match(Context, + subst_Cod(Subst), + cont_ContextBindingTerm(Context, subst_Dom(Subst)))) + return FALSE; + + Subst = subst_Next(Subst); + } + + return TRUE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INSTANCE TEST * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +BOOL subst_MatchReverse(const CONTEXT IndexContext, SUBST Subst) +/********************************************************* + INPUT: + RETURNS: + CAUTION: 'Subst' IS ASSUMED TO BE NON-EMPTY. +**********************************************************/ +{ + while (subst_Exist(Subst)) { + + if (!cont_VarIsBound(IndexContext, subst_Dom(Subst))) { + if (symbol_IsIndexVariable(subst_Dom(Subst))) + cont_CreateBinding(IndexContext, + subst_Dom(Subst), + cont_InstanceContext(), + subst_Cod(Subst)); + else + return FALSE; + } + else if (!unify_MatchReverse(IndexContext, + subst_Cod(Subst), + cont_ContextBindingContext(IndexContext, subst_Dom(Subst)), + cont_ContextBindingTerm(IndexContext, subst_Dom(Subst)))) + return FALSE; + + Subst = subst_Next(Subst); + } + + return TRUE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * VARIATION TEST * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +BOOL subst_Variation(const CONTEXT Context, SUBST Subst) +/********************************************************* + INPUT: + RETURNS: + CAUTION: 'Subst' IS ASSUMED TO BE NON-EMPTY. +**********************************************************/ +{ + while (subst_Exist(Subst)) { + + if (!cont_VarIsBound(Context, subst_Dom(Subst)) || + !unify_Variation(Context, + subst_Cod(Subst), + cont_ContextBindingTerm(Context, subst_Dom(Subst)))) + return FALSE; + + Subst = subst_Next(Subst); + } + + return TRUE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * COMMON GENERALIZATIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +SUBST subst_ComGen(const CONTEXT Context, SUBST Subst, SUBST* SubstOld, + SUBST* SubstNew) +/********************************************************* + INPUT: + RETURNS: + CAUTION: 'Subst' IS ASSUMED TO BE NON-EMPTY. +**********************************************************/ +{ + SUBST Result; + + Result = *SubstOld = *SubstNew = NULL; + + do { + + if (!cont_VarIsBound(Context, subst_Dom(Subst))) + *SubstOld=subst_Add(subst_Dom(Subst), term_Copy(subst_Cod(Subst)), *SubstOld); + + else if (term_Equal(cont_ContextBindingTerm(Context, subst_Dom(Subst)), + subst_Cod(Subst))) + Result = subst_Add(subst_Dom(Subst), term_Copy(subst_Cod(Subst)), Result); + + else + if (!symbol_Equal(term_TopSymbol(cont_ContextBindingTerm(Context, + subst_Dom(Subst))), + term_TopSymbol(subst_Cod(Subst)))) { + + *SubstOld=subst_Add(subst_Dom(Subst), + term_Copy(subst_Cod(Subst)), + *SubstOld); + *SubstNew=subst_Add(subst_Dom(Subst), + term_Copy(cont_ContextBindingTerm(Context, + subst_Dom(Subst))), + *SubstNew); + + } else + Result = subst_Add(subst_Dom(Subst), + unify_ComGenLinear(Context, + SubstNew, + cont_ContextBindingTerm(Context, + subst_Dom(Subst)), + SubstOld, + subst_Cod(Subst)), + Result); + + cont_CloseBinding(Context, subst_Dom(Subst)); + + Subst = subst_Next(Subst); + } while (subst_Exist(Subst)); + + return Result; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * CLOSE BINDINGS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +void subst_CloseVariables(const CONTEXT Context, SUBST Subst) +{ + for (; subst_Exist(Subst); Subst = subst_Next(Subst)) + cont_CloseBinding(Context, subst_Dom(Subst)); +} + + +SUBST subst_CloseOpenVariables(SUBST Result) +{ + while (cont_LastBinding()) { + if (cont_LastIsBound()) + Result = subst_Add(cont_LastBindingSymbol(), + term_Copy(cont_LastBindingTerm()), + Result); + cont_BackTrackLastBinding(); + } + + return Result; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * EXTRACT UNIFIER * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +void subst_ExtractUnifier(const CONTEXT CL, + SUBST* LeftSubst, + const CONTEXT CR, + SUBST* RightSubst) +/********************************************************* + INPUT: 'LeftSubst', 'RightSubst' for the unifier, + renaming the codomain variables starts at + 'MinimumCoVariable' excl., number of + renamings are ADDED to 'Bindings'. + RETURNS: Nothing. + SUMMARY: Extracts the unifier into two substitutions + with renamed variables in the codomain. + CAUTION: DOES NOT RESET THE BINDINGS, CREATES EVEN + MORE BINDINGS BECAUSE OF RENAMING. +**********************************************************/ +{ + CONTEXT Scan; + + *LeftSubst = subst_Nil(); + *RightSubst = subst_Nil(); + + Scan = cont_LastBinding(); + + while (Scan) { + if (cont_IsInContext(CL, + cont_BindingSymbol(Scan), + Scan)) + *LeftSubst = subst_Add(cont_BindingSymbol(Scan), + cont_CopyAndApplyBindings(cont_BindingContext(Scan), + cont_BindingTerm(Scan)), + *LeftSubst); + else if (cont_IsInContext(CR, + cont_BindingSymbol(Scan), + Scan)) + *RightSubst = subst_Add(cont_BindingSymbol(Scan), + cont_CopyAndApplyBindings(cont_BindingContext(Scan), + cont_BindingTerm(Scan)), + *RightSubst); + + Scan = cont_BindingLink(Scan); + } +} + + +void subst_ExtractUnifierCom(const CONTEXT Context, SUBST* Subst) +/********************************************************* + INPUT: 'LeftSubst', 'RightSubst' for the unifier, + renaming the codomain variables starts at + 'MinimumCoVariable' excl., number of + renamings are ADDED to 'Bindings'. + RETURNS: Nothing. + SUMMARY: Extracts the unifier into two substitutions + with renamed variables in the codomain. + CAUTION: DOES NOT RESET THE BINDINGS, CREATES EVEN + MORE BINDINGS BECAUSE OF RENAMING. +**********************************************************/ +{ + CONTEXT Scan; + + *Subst = subst_Nil(); + + Scan = cont_LastBinding(); + + while (Scan) { + *Subst = + subst_Add(cont_BindingSymbol(Scan), + cont_CopyAndApplyBindingsCom(Context, cont_BindingTerm(Scan)), + *Subst); + + Scan = cont_BindingLink(Scan); + } +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * EXTRACT MATCHER * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +SUBST subst_ExtractMatcher(void) +/********************************************************* + INPUT: None. + RETURNS: The matcher. + SUMMARY: Extracts the matcher without renaming. + CAUTION: DOES NOT RESET THE BINDINGS, DOES NOT COPY + THE CODOMAINS. +**********************************************************/ +{ + CONTEXT Scan; + SUBST Result; + + for (Scan = cont_LastBinding(), Result = subst_Nil(); + Scan; + Scan = cont_BindingLink(Scan)) + Result = subst_Add(cont_BindingSymbol(Scan), + cont_BindingTerm(Scan), + Result); + + return Result; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * OUTPUT * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +void subst_Print(SUBST Subst) +{ + fputs("{ ", stdout); + for (; subst_Exist(Subst); Subst = subst_Next(Subst)) { + symbol_Print(subst_Dom(Subst)); + if (subst_Cod(Subst)) { + fputs(" -> ", stdout); + term_PrintPrefix(subst_Cod(Subst)); + } + if (subst_Next(Subst)) + fputs("; ", stdout); + } + fputs(" }", stdout); +} + diff --git a/test/spass/subst.h b/test/spass/subst.h new file mode 100644 index 0000000000000000000000000000000000000000..db26197c6bad98b859c369913e06be3bca679920 --- /dev/null +++ b/test/spass/subst.h @@ -0,0 +1,219 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SUBSTITUTION * */ +/* * * */ +/* * $Module: SUBSTITUTION * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _SUBST_ +#define _SUBST_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "term.h" +#include "symbol.h" +#include "list.h" + +/**************************************************************/ +/* Data Structures */ +/**************************************************************/ + +typedef struct subst { + struct subst *next; + SYMBOL dom; + TERM codomain; +} SUBST_NODE, *SUBST; + + +static __inline__ SUBST subst_Get(void) +{ + return (SUBST) memory_Malloc(sizeof(SUBST_NODE)); +} + +static __inline__ void subst_FreeOneNode(SUBST SL) +{ + memory_Free(SL, sizeof(SUBST_NODE)); +} + +/**************************************************************/ +/* Include 'unify.h' after SUBST declaration. */ +/**************************************************************/ + +#include "unify.h" + +/**************************************************************/ +/* Functions on Substitutions */ +/**************************************************************/ + +static __inline__ SUBST subst_Nil(void) +{ + return (SUBST)NULL; +} + +static __inline__ BOOL subst_Exist(SUBST S) +{ + return S != subst_Nil(); +} + +static __inline__ BOOL subst_Empty(SUBST S) +{ + return S == subst_Nil(); +} + +static __inline__ SUBST subst_Next(SUBST S) +{ + return S->next; +} + +static __inline__ void subst_SetNext(SUBST S, SUBST N) +{ + S->next = N; +} + +static __inline__ SYMBOL subst_Dom(SUBST S) +{ + return S->dom; +} + +static __inline__ TERM subst_Cod(SUBST S) +{ + return S->codomain; +} + +static __inline__ SUBST subst_NUnion(SUBST S1,SUBST S2) +{ + SUBST Result; + + if (S1 == (SUBST)NULL) + return S2; + + if (S2 == (SUBST)NULL) + return S1; + + Result = S1; + + for (; S1->next != (SUBST)NULL; S1 = S1->next); + + S1->next = S2; + + return Result; +} + + +/**************************************************************/ +/* Functions for Creation and Deletion */ +/**************************************************************/ + +SUBST subst_Add(SYMBOL, TERM, SUBST); +void subst_Delete(SUBST); +void subst_Free(SUBST); + +/**************************************************************/ +/* Functions for Applying and Copying */ +/**************************************************************/ + +TERM subst_Term(SYMBOL, SUBST); +TERM subst_Apply(SUBST, TERM); +SUBST subst_Merge(SUBST, SUBST); +SUBST subst_Compose(SUBST, SUBST); +SUBST subst_Copy(SUBST); +BOOL subst_MatchTops(const CONTEXT, SUBST); +BOOL subst_BindVar(SYMBOL,SUBST); + +/**************************************************************/ +/* Functions for Search of Unifiers */ +/**************************************************************/ + +BOOL subst_Unify(CONTEXT, SUBST); +BOOL subst_IsShallow(SUBST); + +/**************************************************************/ +/* Functions for Search of Generalizations */ +/**************************************************************/ + +BOOL subst_Match(const CONTEXT, SUBST); + +/**************************************************************/ +/* Functions for Search of Instances */ +/**************************************************************/ + +BOOL subst_MatchReverse(const CONTEXT, SUBST); + +/**************************************************************/ +/* Functions for Search of Variations */ +/**************************************************************/ + +BOOL subst_Variation(const CONTEXT, SUBST); + +/**************************************************************/ +/* Functions for Computation of MSCGs */ +/**************************************************************/ + +SUBST subst_ComGen(const CONTEXT, SUBST, SUBST*, SUBST*); + +/**************************************************************/ +/* Functions for Closing Bindings */ +/**************************************************************/ + +void subst_CloseVariables(const CONTEXT, SUBST); +SUBST subst_CloseOpenVariables(SUBST); + +/**************************************************************/ +/* Functions for Extracting Substitutions from Bindings */ +/**************************************************************/ + +void subst_ExtractUnifier(const CONTEXT, SUBST*, const CONTEXT, SUBST*); +void subst_ExtractUnifierCom(const CONTEXT, SUBST*); +SUBST subst_ExtractMatcher(void); + +/**************************************************************/ +/* Functions for Debugging */ +/**************************************************************/ + +void subst_Print(SUBST); + +#endif + + diff --git a/test/spass/subsumption.c b/test/spass/subsumption.c new file mode 100644 index 0000000000000000000000000000000000000000..d312cbf8875b76679eba08bbf983b9be18e09d5b --- /dev/null +++ b/test/spass/subsumption.c @@ -0,0 +1,2041 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SUBSUMPTION * */ +/* * * */ +/* * $Module: SUBSUMPTION * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + + +#include "subsumption.h" + +static NAT multvec_i[subs__MAXLITS]; +static NAT multvec_j[subs__MAXLITS]; +static NAT stamp; + +static BOOL subs_InternIdc(CLAUSE, int, CLAUSE); +static BOOL subs_InternIdcEq(CLAUSE, int, CLAUSE); +static BOOL subs_InternIdcEqExcept(CLAUSE, int, CLAUSE, int); +static BOOL subs_InternIdcRes(CLAUSE, int, int, int); + +/* The following functions are currently unused */ +BOOL subs_IdcTestlits(CLAUSE, CLAUSE, LITPTR*); +BOOL subs_Testlits(CLAUSE, CLAUSE); + + +void subs_Init(void) +{ + int i; + + stamp = 0; + for (i = 0; i < subs__MAXLITS; i++) + multvec_i[i] = multvec_j[i] = 0; +} + + +static BOOL subs_TestlitsEq(CLAUSE c1, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1 and c2. + RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. + CAUTION: None. +***********************************************************/ +{ + TERM t1,t2; + int i,j,n,k; + BOOL found; + + n = clause_Length(c1); + k = clause_Length(c2); + + for (i = 0; i < n; i++){ + j = 0; + found = FALSE; + t1 = clause_GetLiteralTerm(c1,i); + + do { + t2 = clause_GetLiteralTerm(c2,j); + cont_StartBinding(); + if (unify_Match(cont_LeftContext(), t1, t2)) + found = TRUE; + else{ + if (symbol_Equal(term_TopSymbol(t1),term_TopSymbol(t2)) && + fol_IsEquality(fol_Atom(t1)) && + fol_IsEquality(fol_Atom(t2)) && + (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c1,i)) || + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c2,j)))) { + cont_BackTrackAndStart(); + if (unify_Match(cont_LeftContext(), + term_FirstArgument(fol_Atom(t1)), + term_SecondArgument(fol_Atom(t2))) && + unify_Match(cont_LeftContext(), + term_SecondArgument(fol_Atom(t1)), + term_FirstArgument(fol_Atom(t2)))) + found = TRUE; + else + j++; + } + else + j++; + } + cont_BackTrack(); + + } while (!found && j < k); + + if (!found) + return FALSE; + } + + return TRUE; +} + + +static BOOL subs_STMultiIntern(int i, CLAUSE c1, CLAUSE c2) +/********************************************************** + INPUT: Integers i,j and two clauses c1 and c2 + i and j stand for the i-th and the j-th literal + in the clause c1 respectively c2. + RETURNS: FALSE if c1 does not multisubsume c2 and TRUE otherwise. + CAUTION: None. +***********************************************************/ +{ + int n,j; + TERM lit1,lit2; + + j = 0; + n = clause_Length(c2); + lit1 = clause_GetLiteralTerm(c1,i); + + while (j < n) { + if (multvec_j[j] != stamp) { + lit2 = clause_GetLiteralTerm(c2,j); + cont_StartBinding(); + if (unify_Match(cont_LeftContext(),lit1,lit2)) { + if (i == (clause_Length(c1)-1)) { + cont_BackTrack(); + return TRUE; + } + multvec_j[j] = stamp; + if (subs_STMultiIntern(i+1, c1, c2)) { + cont_BackTrack(); + return TRUE; + } + multvec_j[j] = 0; + } + cont_BackTrack(); + if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && + fol_IsEquality(fol_Atom(lit1)) && + fol_IsEquality(fol_Atom(lit2)) && + (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c1,i)) || + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c2,j)))) { + cont_StartBinding(); + if (unify_Match(cont_LeftContext(), + term_FirstArgument(fol_Atom(lit1)), + term_SecondArgument(fol_Atom(lit2))) && + unify_Match(cont_LeftContext(), + term_SecondArgument(fol_Atom(lit1)), + term_FirstArgument(fol_Atom(lit2)))) { + if (i == (clause_Length(c1)-1)) { + cont_BackTrack(); + return TRUE; + } + multvec_j[j] = stamp; + if (subs_STMultiIntern(i+1, c1, c2)) { + cont_BackTrack(); + return TRUE; + } + multvec_j[j] = 0; + } + cont_BackTrack(); + } + } + j++; + } + return FALSE; +} + + +BOOL subs_STMulti(CLAUSE c1, CLAUSE c2) +{ + BOOL Result; + int n; + + n = clause_Length(c1); + + /*printf("\n St-Multi: %d -> %d",clause_Number(c1),clause_Number(c2));*/ + + if (n > clause_Length(c2) || + (n > 1 && !subs_TestlitsEq(c1,c2))) { + /*fputs(" Testlits failure ", stdout);*/ + return(FALSE); + } + + if (++stamp == NAT_MAX) { + int i; + stamp = 1; + for (i = 0; i < subs__MAXLITS; i++) + multvec_i[i] = multvec_j[i] = 0; + } + /*unify_SaveState();*/ + Result = subs_STMultiIntern(0,c1,c2); + /*unify_CheckState();*/ + return Result; +} + + +static BOOL subs_TestlitsEqExcept(CLAUSE C1, CLAUSE C2) +{ + TERM t1,t2; + int i,j,n,k; + BOOL found; + + n = clause_Length(C1); + k = clause_Length(C2); + + i = 0; + while (multvec_i[i] == stamp && i < n) + i++; + + while (i < n) { + j = 0; + found = FALSE; + t1 = clause_GetLiteralTerm(C1,i); + + do { + if (multvec_j[j] == stamp) + j++; + else { + t2 = clause_GetLiteralTerm(C2,j); + cont_StartBinding(); + if (unify_MatchBindings(cont_LeftContext(), t1, t2)) + found = TRUE; + else { + if (symbol_Equal(term_TopSymbol(t1),term_TopSymbol(t2)) && + fol_IsEquality(fol_Atom(t1)) && + fol_IsEquality(fol_Atom(t2)) && + (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C1,i)) || + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C2,j)))) { + cont_BackTrackAndStart(); + if (unify_MatchBindings(cont_LeftContext(), + term_FirstArgument(fol_Atom(t1)), + term_SecondArgument(fol_Atom(t2))) && + unify_MatchBindings(cont_LeftContext(), + term_SecondArgument(fol_Atom(t1)), + term_FirstArgument(fol_Atom(t2)))) + found = TRUE; + else + j++; + } + else + j++; + } + cont_BackTrack(); + } /* else */ + } while (!found && (j < k)); + + if (!found) + return FALSE; + do + i++; + while (multvec_i[i] == stamp && i < n); + } /* while i < n */ + + + return TRUE; +} + + +static BOOL subs_STMultiExceptIntern(CLAUSE C1, CLAUSE C2) +{ + int n, i, j, k; + NAT occs, occsaux; + TERM lit1,lit2; + + i = -1; + k = 0; + occs = 0; + j = 0; + n = clause_Length(C2); + + while (k < clause_Length(C1)) { + /* Select Literal with maximal number of variable occurrences. */ + if (multvec_i[k] != stamp) { + if (i < 0) { + i = k; + occs = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,i)); + } else + if ((occsaux = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,k))) + > occs) { + i = k; + occs = occsaux; + } + } + k++; + } + + if (i < 0) + return TRUE; + + lit1 = clause_GetLiteralTerm(C1, i); + multvec_i[i] = stamp; + + while (j < n) { + if (multvec_j[j] != stamp) { + lit2 = clause_GetLiteralTerm(C2, j); + cont_StartBinding(); + if (unify_MatchBindings(cont_LeftContext(), lit1, lit2)) { + multvec_j[j] = stamp; + if (subs_STMultiExceptIntern(C1, C2)) { + cont_BackTrack(); + return TRUE; + } + multvec_j[j] = 0; + } + cont_BackTrack(); + if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && + fol_IsEquality(fol_Atom(lit1)) && + fol_IsEquality(fol_Atom(lit2)) && + (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C1,i)) || + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C2,j)))) { + cont_StartBinding(); + if (unify_MatchBindings(cont_LeftContext(), + term_FirstArgument(fol_Atom(lit1)), + term_SecondArgument(fol_Atom(lit2))) && + unify_MatchBindings(cont_LeftContext(), + term_SecondArgument(fol_Atom(lit1)), + term_FirstArgument(fol_Atom(lit2)))) { + multvec_j[j] = stamp; + if (subs_STMultiExceptIntern(C1, C2)) { + cont_BackTrack(); + return TRUE; + } + multvec_j[j] = 0; + } + cont_BackTrack(); + } + } + j++; + } + multvec_i[i] = 0; + return FALSE; +} + + +BOOL subs_STMultiExcept(CLAUSE C1, CLAUSE C2, int ExceptI, int ExceptJ) +/********************************************************** + INPUT: Two clauses and for each clause a literal that is + already bound to each other. If the literal value is negative, + a general subsumption test is performed. + RETURNS: TRUE if the first clause subsumes the second one. + CAUTION: The weight of the clauses must be up to date! +***********************************************************/ +{ + BOOL Result; + int n; + + n = clause_Length(C1); + + if (n > clause_Length(C2) || + (clause_Weight(C1)-clause_LiteralWeight(clause_GetLiteral(C1,ExceptI))) > + (clause_Weight(C2)-clause_LiteralWeight(clause_GetLiteral(C2,ExceptJ)))) + return FALSE; + + if (++stamp == NAT_MAX) { + int i; + stamp = 1; + for (i = 0; i < subs__MAXLITS; i++) + multvec_i[i] = multvec_j[i] = 0; + } + multvec_i[ExceptI] = stamp; + multvec_j[ExceptJ] = stamp; + + if (n > 1 && !subs_TestlitsEqExcept(C1, C2)) + return FALSE; + + /*unify_SaveState();*/ + Result = subs_STMultiExceptIntern(C1, C2); + /*unify_CheckState();*/ + return Result; +} + + +static BOOL subs_PartnerTest(CLAUSE C1, int c1l, int c1r, CLAUSE C2, int c2l, int c2r) +/********************************************************** + INPUT: Two clauses and for each clause a starting left index + and an exclusive right index. + RETURNS: TRUE if every literal inside the bounds of the first clause + can be matched against a literal inside the bounds of the + second clause. + CAUTION: None. +***********************************************************/ +{ + TERM t1,t2; + int j; + BOOL found; + + if (c1l == c1r) + return TRUE; + + while (multvec_i[c1l] == stamp && c1l < c1r) + c1l++; + + if (c1l < c1r) { + if (c2l == c2r) + return FALSE; + else + do { + j = c2l; + found = FALSE; + t1 = clause_GetLiteralTerm(C1,c1l); + + do { + if (multvec_j[j] == stamp) + j++; + else { + t2 = clause_GetLiteralTerm(C2,j); + cont_StartBinding(); + if (unify_MatchBindings(cont_LeftContext(), t1, t2)) + found = TRUE; + else { + if (symbol_Equal(term_TopSymbol(t1),term_TopSymbol(t2)) && + fol_IsEquality(fol_Atom(t1)) && + fol_IsEquality(fol_Atom(t2)) && + (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C1,c1l)) || + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C2,j)))) { + cont_BackTrackAndStart(); + if (unify_MatchBindings(cont_LeftContext(), + term_FirstArgument(fol_Atom(t1)), + term_SecondArgument(fol_Atom(t2))) && + unify_MatchBindings(cont_LeftContext(), + term_SecondArgument(fol_Atom(t1)), + term_FirstArgument(fol_Atom(t2)))) + found = TRUE; + else + j++; + } + else + j++; + } + cont_BackTrack(); + } /* else */ + } while (!found && (j < c2r)); + + if (!found) + return FALSE; + do + c1l++; + while (multvec_i[c1l] == stamp && c1l < c1r); + } while (c1l < c1r); + } + return TRUE; +} + + +static BOOL subs_SubsumesInternBasic(CLAUSE C1, int c1fa, int c1fs, int c1l, + CLAUSE C2, int c2fa, int c2fs, int c2l) +{ + int i, j, n, k; + NAT occs, occsaux; + TERM lit1,lit2; + + i = -1; + k = clause_FirstLitIndex(); + occs = 0; + + while (k < c1l) { /* Select literal with maximal variable occurrences. */ + if (multvec_i[k] != stamp) { + if (i < 0) { + i = k; + occs = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,i)); + } else + if ((occsaux = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,k))) + > occs) { + i = k; + occs = occsaux; + } + } + k++; + } + + if (i < 0) + return TRUE; + + lit1 = clause_GetLiteralTerm(C1, i); + multvec_i[i] = stamp; + + if (i < c1fa) { /* Only consider relevant partner literals */ + j = clause_FirstLitIndex(); + n = c2fa; + } + else if (i < c1fs) { + j = c2fa; + n = c2fs; + } + else { + j = c2fs; + n = c2l; + } + + while (j < n) { + if (multvec_j[j] != stamp) { + lit2 = clause_GetLiteralTerm(C2, j); + cont_StartBinding(); + if (unify_MatchBindings(cont_LeftContext(), lit1, lit2)) { + multvec_j[j] = stamp; + if (subs_SubsumesInternBasic(C1,c1fa,c1fs,c1l,C2,c2fa,c2fs,c2l)) { + cont_BackTrack(); + return TRUE; + } + multvec_j[j] = 0; + } + cont_BackTrack(); + if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && + fol_IsEquality(fol_Atom(lit1)) && + fol_IsEquality(fol_Atom(lit2)) && + (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C1,i)) || + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C2,j)))) { + cont_StartBinding(); + if (unify_MatchBindings(cont_LeftContext(), + term_FirstArgument(fol_Atom(lit1)), + term_SecondArgument(fol_Atom(lit2))) && + unify_MatchBindings(cont_LeftContext(), + term_SecondArgument(fol_Atom(lit1)), + term_FirstArgument(fol_Atom(lit2)))) { + multvec_j[j] = stamp; + if (subs_SubsumesInternBasic(C1,c1fa,c1fs,c1l,C2,c2fa,c2fs,c2l)) { + cont_BackTrack(); + return TRUE; + } + multvec_j[j] = 0; + } + cont_BackTrack(); + } + } + j++; + } + multvec_i[i] = 0; + return FALSE; +} + + +BOOL subs_SubsumesBasic(CLAUSE C1, CLAUSE C2, int ExceptI, int ExceptJ) +/********************************************************** + INPUT: Two clauses and for each clause a literal that are + already bound to each other. If the literal value is negative, + a general subsumption test is performed. + RETURNS: TRUE if the first clause subsumes the second one with respect + to basic restrictions on the sort literals. + CAUTION: The weight of the clauses must be up to date! +***********************************************************/ +{ + BOOL Result; + int c1fa,c1fs,c1l,c2fa,c2fs,c2l,lw1,lw2; + + c1fa = clause_FirstAntecedentLitIndex(C1); + c1fs = clause_FirstSuccedentLitIndex(C1); + c1l = clause_Length(C1); + c2fa = clause_FirstAntecedentLitIndex(C2); + c2fs = clause_FirstSuccedentLitIndex(C2); + c2l = clause_Length(C2); + + lw1 = (ExceptI >= clause_FirstLitIndex() ? + clause_LiteralWeight(clause_GetLiteral(C1,ExceptI)) : 0); + lw2 = (ExceptJ >= clause_FirstLitIndex() ? + clause_LiteralWeight(clause_GetLiteral(C2,ExceptJ)) : 0); + + if (c1l > c2l || /* Multiset restriction */ + (clause_Weight(C1)-lw1) > (clause_Weight(C2)-lw2)) { + return FALSE; + } + + if (++stamp == NAT_MAX) { + int i; + stamp = 1; + for (i = 0; i < subs__MAXLITS; i++) + multvec_i[i] = multvec_j[i] = 0; + } + + if (ExceptI >= clause_FirstLitIndex()) + multvec_i[ExceptI] = stamp; + if (ExceptJ >= clause_FirstLitIndex()) + multvec_j[ExceptJ] = stamp; + + if (c1l > 1 && + (!subs_PartnerTest(C1,clause_FirstConstraintLitIndex(C1),c1fa, + C2,clause_FirstConstraintLitIndex(C2),c2fa) || + !subs_PartnerTest(C1,c1fa,c1fs,C2,c2fa,c2fs) || + !subs_PartnerTest(C1,c1fs,c1l,C2,c2fs,c2l))) + return FALSE; + +#ifdef CHECK + cont_SaveState(); +#endif + + Result = subs_SubsumesInternBasic(C1,c1fa,c1fs,c1l,C2,c2fa,c2fs,c2l); + +#ifdef CHECK + cont_CheckState(); +#endif + + return Result; +} + + +static BOOL subs_SubsumesInternWithSignature(int i, CLAUSE c1, CLAUSE c2, BOOL Variants, LIST* Bindings) +/********************************************************** + INPUT: + RETURNS: + CAUTION: +***********************************************************/ +{ + int n,j; + TERM lit1,lit2; + LIST NewBindings,Scan; + + j = 0; + n = clause_Length(c2); + lit1 = clause_GetLiteralTerm(c1,i); + NewBindings = list_Nil(); + + while (j < n) { + if (multvec_j[j] != stamp) { + lit2 = clause_GetLiteralTerm(c2,j); + cont_StartBinding(); + if (fol_SignatureMatch(lit1,lit2,&NewBindings,Variants)) { + if (i == (clause_Length(c1)-1)) { + *Bindings = list_Nconc(NewBindings,*Bindings); + return TRUE; + } + multvec_j[j] = stamp; + if (subs_SubsumesInternWithSignature(i+1, c1, c2,Variants,&NewBindings)) { + *Bindings = list_Nconc(NewBindings,*Bindings); + return TRUE; + } + multvec_j[j] = 0; + } + for (Scan=NewBindings;!list_Empty(Scan);Scan=list_Cdr(Scan)) { /* Backtrack bindings */ + if (symbol_IsVariable((SYMBOL)list_Car(Scan))) + term_ClearBinding((SYMBOL)list_Car(Scan)); + else + symbol_ContextClearValue((SYMBOL)list_Car(Scan)); + } + list_Delete(NewBindings); + NewBindings = list_Nil(); + if (symbol_Equal(term_TopSymbol(fol_Atom(lit1)),term_TopSymbol(fol_Atom(lit2))) && + fol_IsEquality(fol_Atom(lit1))) { + if (fol_SignatureMatch(term_FirstArgument(fol_Atom(lit1)), + term_SecondArgument(fol_Atom(lit2)), &NewBindings, Variants) && + fol_SignatureMatch(term_SecondArgument(fol_Atom(lit1)), + term_FirstArgument(fol_Atom(lit2)), &NewBindings, Variants)) { + if (i == (clause_Length(c1)-1)) { + *Bindings = list_Nconc(NewBindings,*Bindings); + return TRUE; + } + multvec_j[j] = stamp; + if (subs_SubsumesInternWithSignature(i+1, c1, c2,Variants,&NewBindings)) { + *Bindings = list_Nconc(NewBindings,*Bindings); + return TRUE; + } + multvec_j[j] = 0; + } + for (Scan=NewBindings;!list_Empty(Scan);Scan=list_Cdr(Scan)) { /* Backtrack bindings */ + if (symbol_IsVariable((SYMBOL)list_Car(Scan))) + term_ClearBinding((SYMBOL)list_Car(Scan)); + else + symbol_ContextClearValue((SYMBOL)list_Car(Scan)); + } + list_Delete(NewBindings); + NewBindings = list_Nil(); + } + } + j++; + } + return FALSE; +} + +BOOL subs_SubsumesWithSignature(CLAUSE C1, CLAUSE C2, BOOL Variants, LIST *Bindings) +/********************************************************** + INPUT: Two clauses . + RETURNS: TRUE if the first clause subsumes the second one where + we allow signature symbols to be matched as well. + If <Variants> is TRUE variables must be mapped to variables. + Returns the signature symbols that were bound. + EFFECT: Symbol context bindings are established. +***********************************************************/ +{ + BOOL Result; + + if (clause_Length(C1) > clause_Length(C2) || + clause_NumOfSuccLits(C1) > clause_NumOfSuccLits(C2) || + (clause_NumOfAnteLits(C1) + clause_NumOfConsLits(C1)) > + (clause_NumOfAnteLits(C2) + clause_NumOfConsLits(C2))) { /* Multiset restriction */ + return FALSE; + } + + if (++stamp == NAT_MAX) { + int i; + stamp = 1; + for (i = 0; i < subs__MAXLITS; i++) + multvec_i[i] = multvec_j[i] = 0; + } + + term_NewMark(); + Result = subs_SubsumesInternWithSignature(clause_FirstLitIndex(),C1,C2,Variants, Bindings); + *Bindings = list_DeleteElementIf(*Bindings, (BOOL (*)(POINTER)) symbol_IsVariable); + return Result; +} + +static BOOL subs_SubsumesIntern(CLAUSE C1, int c1fs, int c1l, CLAUSE C2, int c2fs, int c2l) +{ + int i, j, n, k; + NAT occs, occsaux; + TERM lit1,lit2; + + i = -1; + k = clause_FirstLitIndex(); + occs = 0; + + while (k < c1l) { /* Select literal with maximal variable occurrences. */ + if (multvec_i[k] != stamp) { + if (i < 0) { + i = k; + occs = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,i)); + } else + if ((occsaux = term_NumberOfVarOccs(clause_GetLiteralAtom(C1,k))) + > occs) { + i = k; + occs = occsaux; + } + } + k++; + } + + if (i < 0) + return TRUE; + + lit1 = clause_GetLiteralTerm(C1, i); + multvec_i[i] = stamp; + + if (i < c1fs) { /* Only consider relevant partner literals */ + j = clause_FirstLitIndex(); + n = c2fs; + } + else { + j = c2fs; + n = c2l; + } + + while (j < n) { + if (multvec_j[j] != stamp) { + lit2 = clause_GetLiteralTerm(C2, j); + cont_StartBinding(); + if (unify_MatchBindings(cont_LeftContext(), lit1, lit2)) { + multvec_j[j] = stamp; + if (subs_SubsumesIntern(C1,c1fs,c1l,C2,c2fs,c2l)) { + cont_BackTrack(); + return TRUE; + } + multvec_j[j] = 0; + } + cont_BackTrack(); + if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && + fol_IsEquality(fol_Atom(lit1)) && + fol_IsEquality(fol_Atom(lit2)) && + (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C1,i)) || + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(C2,j)))) { + cont_StartBinding(); + if (unify_MatchBindings(cont_LeftContext(), + term_FirstArgument(fol_Atom(lit1)), + term_SecondArgument(fol_Atom(lit2))) && + unify_MatchBindings(cont_LeftContext(), + term_SecondArgument(fol_Atom(lit1)), + term_FirstArgument(fol_Atom(lit2)))) { + multvec_j[j] = stamp; + if (subs_SubsumesIntern(C1,c1fs,c1l,C2,c2fs,c2l)) { + cont_BackTrack(); + return TRUE; + } + multvec_j[j] = 0; + } + cont_BackTrack(); + } + } + j++; + } + multvec_i[i] = 0; + return FALSE; +} + + +BOOL subs_Subsumes(CLAUSE C1, CLAUSE C2, int ExceptI, int ExceptJ) +/********************************************************** + INPUT: Two clauses and for each clause a literal that is + already bound to each other. If the literal value is negative, + a general subsumption test is performed. + RETURNS: TRUE if the first clause subsumes the second one. + CAUTION: The weight of the clauses must be up to date! +***********************************************************/ +{ + BOOL Result; + int c1fs, c1l, c2fs, c2l, lw1, lw2; + + c1fs = clause_FirstSuccedentLitIndex(C1); + c1l = clause_Length(C1); + c2fs = clause_FirstSuccedentLitIndex(C2); + c2l = clause_Length(C2); + + lw1 = (ExceptI >= clause_FirstLitIndex() ? + clause_LiteralWeight(clause_GetLiteral(C1,ExceptI)) : 0); + lw2 = (ExceptJ >= clause_FirstLitIndex() ? + clause_LiteralWeight(clause_GetLiteral(C2,ExceptJ)) : 0); + + if (c1l > c2l || /* Multiset restriction */ + (clause_Weight(C1) - lw1) > (clause_Weight(C2) - lw2)) + return FALSE; + + if (++stamp == NAT_MAX) { + int i; + stamp = 1; + for (i = 0; i < subs__MAXLITS; i++) + multvec_i[i] = multvec_j[i] = 0; + } + + if (ExceptI >= clause_FirstLitIndex()) + multvec_i[ExceptI] = stamp; + if (ExceptJ >= clause_FirstLitIndex()) + multvec_j[ExceptJ] = stamp; + + if (c1l > 1 && + (!subs_PartnerTest(C1,clause_FirstConstraintLitIndex(C1),c1fs, + C2,clause_FirstConstraintLitIndex(C2),c2fs) || + !subs_PartnerTest(C1,c1fs,c1l,C2,c2fs,c2l))) + return FALSE; + +#ifdef CHECK + cont_SaveState(); +#endif + + Result = subs_SubsumesIntern(C1,c1fs,c1l,C2,c2fs,c2l); + +#ifdef CHECK + cont_CheckState(); +#endif + + return Result; +} + + + + +BOOL subs_ST(int i, int j, CLAUSE c1, CLAUSE c2) +/********************************************************** + INPUT: Integers i,j and two clauses c1 and c2. + i and j stand for the i-th and the j-th literal + in the clause c1 respectively c2. + RETURNS: FALSE if c1 does not subsume c2 and TRUE otherwise. + CAUTION: None. +***********************************************************/ +{ + cont_StartBinding(); + + while ((j < clause_Length(c2)) && + !(unify_Match(cont_LeftContext(), + clause_GetLiteralTerm(c1,i), + clause_GetLiteralTerm(c2,j)))){ + j++; + cont_BackTrackAndStart(); + } + + if (j >= clause_Length(c2)) { + cont_BackTrack(); + return FALSE; + } + + if ((i == (clause_Length(c1)-1)) || subs_ST(i+1, 0, c1, c2)) + return TRUE; + else + cont_BackTrack(); + + if (++j == clause_Length(c2)) + return FALSE; + + return subs_ST(i, j, c1, c2); +} + + +BOOL subs_Testlits(CLAUSE c1, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1 and c2. + RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. + CAUTION: None. +***********************************************************/ +{ + TERM t1; + int i,j; + BOOL found; + + for (i = 0; i < clause_Length(c1); i++){ + j = 0; + found = FALSE; + t1 = clause_GetLiteralTerm(c1,i); + + do { + cont_StartBinding(); + if (!(found = unify_Match(cont_LeftContext(), t1, clause_GetLiteralTerm(c2,j)))) + j++; + cont_BackTrack(); + + } while (!found && (j < clause_Length(c2))); + + if (!found) + return FALSE; + } + + return TRUE; +} + + +static LIST subs_GetVariables(TERM t) +/********************************************************** + INPUT: A term. + RETURNS: The list of non bound variables of the term. + CAUTION: None. +***********************************************************/ +{ + LIST scan,insert,symbols,end; + + symbols = term_VariableSymbols(t); + insert = symbols; + end = list_Nil(); + + for (scan = symbols; !list_Empty(scan); scan = list_Cdr(scan)) { + if (!cont_VarIsBound(cont_LeftContext(), (SYMBOL)list_Car(scan))) { + end = insert; + list_Rplaca(insert, list_Car(scan)); + insert = list_Cdr(insert); + } + } + + if (!list_Empty(insert)) { + list_Delete(insert); + if (list_Empty(end)) + symbols = list_Nil(); + else + list_Rplacd(end,list_Nil()); + } + + return(symbols); +} + + +static BOOL subs_SubsumptionPossible(CLAUSE c1, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1 and c2. + RETURNS: TRUE if every literal in c1 can independently be + matched to a literal in c2. + CAUTION: None. +***********************************************************/ +{ + int i,j; + + for (i = 0; i < clause_Length(c1); i++) { + for (j = 0; j < clause_Length(c2); j++) { + cont_StartBinding(); + if (unify_Match(cont_LeftContext(), + clause_GetLiteralTerm(c1,i), + clause_GetLiteralTerm(c2,j))) + j = clause_Length(c2) + 1; + cont_BackTrack(); + } + if (j == clause_Length(c2)) + return FALSE; + } + + return TRUE; +} + + +BOOL subs_IdcTestlits(CLAUSE c1, CLAUSE c2, LITPTR* litptr) +/********************************************************** + INPUT: Two clauses c1, c2 and a pointer to a litptr structure. + RETURNS: FALSE if c1 can not independently be matched + to c2 and TRUE otherwise. + CAUTION: A structure is build and litptr points to that structure. +***********************************************************/ +{ + LIST TermIndexlist,VarSymbList,TermSymbList; + int i; + + if (subs_SubsumptionPossible(c1,c2)) { + + TermIndexlist = list_Nil(); + VarSymbList = list_Nil(); + TermSymbList = list_Nil(); + + for (i = 0; i < clause_Length(c1); i++) { + VarSymbList = subs_GetVariables(clause_GetLiteralTerm(c1,i)); + + if (VarSymbList != list_Nil()){ + TermIndexlist = list_Cons((POINTER)i, TermIndexlist); + TermSymbList = list_Cons(VarSymbList,TermSymbList); + } + } + + *litptr = litptr_Create(TermIndexlist,TermSymbList); + + list_Delete(TermSymbList); + list_Delete(TermIndexlist); + + return TRUE; + } + return FALSE; +} + + +static BOOL subs_SubsumptionVecPossible(CLAUSE c1, int vec, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1 and c2 and a vector pointer. + RETURNS: TRUE if all literals in c1 which indexes stand + in the vector with bottom pointer vec can + independently be matched to a literal in c2. + CAUTION: None. +***********************************************************/ +{ + int i,j; + + for (i = vec; i < vec_ActMax(); i++) { + for (j = 0; j < clause_Length(c2); j++) { + cont_StartBinding(); + if (unify_Match(cont_LeftContext(), + clause_GetLiteralTerm(c1, (int) vec_GetNth(i)), + clause_GetLiteralTerm(c2,j))) + j = clause_Length(c2) + 1; + cont_BackTrack(); + } + if (j == clause_Length(c2)) + return FALSE; + } + + return TRUE; +} + + +static BOOL subs_SubsumptionVecPossibleEq(CLAUSE c1, int vec, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1 and c2 and a vector pointer. + RETURNS: TRUE if all literals in c1 which indexes stand + in the vector with bottom pointer vec can + independently be matched to a literal in c2. + CAUTION: None. +***********************************************************/ +{ + int i,j,n; + TERM lit1,lit2; + + n = clause_Length(c2); + for (i = vec; i < vec_ActMax(); i++) { + lit1 = clause_GetLiteralTerm(c1, (int) vec_GetNth(i)); + for (j=0;j<n;j++) { + lit2 = clause_GetLiteralTerm(c2,j); + cont_StartBinding(); + if (unify_Match(cont_LeftContext(),lit1,lit2)) { + j = n + 1; + cont_BackTrack(); + } + else { + cont_BackTrack(); + if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && + fol_IsEquality(fol_Atom(lit1)) && + fol_IsEquality(fol_Atom(lit2)) && + (clause_LiteralIsNotOrientedEquality( + clause_GetLiteral(c1, (int)vec_GetNth(i))) || + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c2,j)))) { + cont_StartBinding(); + if (unify_Match(cont_LeftContext(), + term_FirstArgument(fol_Atom(lit1)), + term_SecondArgument(fol_Atom(lit2))) && + unify_Match(cont_LeftContext(), + term_SecondArgument(fol_Atom(lit1)), + term_FirstArgument(fol_Atom(lit2)))) + j = n+1; + cont_BackTrack(); + } + } + } + if (j==n) + return FALSE; + } + + return TRUE; +} + + +static BOOL subs_IdcVecTestlits(CLAUSE c1, int vec, CLAUSE c2, LITPTR* litptr) +/********************************************************** + INPUT: Two clauses c1, c2, a pointer to a literal structure and + a vector pointer. + RETURNS: FALSE if the literals of c1 which are designated by + the elements of vec do not subsume c2 and TRUE otherwise. + CAUTION: A structure is build and litptr points to that structure. +***********************************************************/ +{ + LIST TermIndexlist,VarSymbList,TermSymbList; + int i; + + if (subs_SubsumptionVecPossible(c1,vec,c2)) { + + TermIndexlist = list_Nil(); + VarSymbList = list_Nil(); + TermSymbList = list_Nil(); + + for (i = vec; i < vec_ActMax(); i++) { + VarSymbList = + subs_GetVariables(clause_GetLiteralTerm(c1, (int) vec_GetNth(i))); + + if (VarSymbList != list_Nil()){ + TermIndexlist = list_Cons(vec_GetNth(i), TermIndexlist); + TermSymbList = list_Cons(VarSymbList,TermSymbList); + } + } + + *litptr = litptr_Create(TermIndexlist,TermSymbList); + + list_Delete(TermSymbList); + list_Delete(TermIndexlist); + + return TRUE; + } + return FALSE; +} + + +static BOOL subs_IdcVecTestlitsEq(CLAUSE c1, int vec, CLAUSE c2, + LITPTR* litptr) +/********************************************************** + INPUT: Two clauses c1, c2, a pointer to a literal structure and + a vector pointer. + RETURNS: FALSE if the literals of c1 which are designated by + the elements of vec do not subsume c2 and TRUE otherwise. + CAUTION: A structure is build and litptr points to that structure. +***********************************************************/ +{ + LIST TermIndexlist,VarSymbList,TermSymbList; + int i; + + if (subs_SubsumptionVecPossibleEq(c1,vec,c2)) { + + TermIndexlist = list_Nil(); + VarSymbList = list_Nil(); + TermSymbList = list_Nil(); + + for (i = vec; i < vec_ActMax(); i++){ + VarSymbList = + subs_GetVariables(clause_GetLiteralTerm(c1, (int) vec_GetNth(i))); + + if (VarSymbList != list_Nil()){ + TermIndexlist = list_Cons(vec_GetNth(i), TermIndexlist); + TermSymbList = list_Cons(VarSymbList,TermSymbList); + } + } + + *litptr = litptr_Create(TermIndexlist,TermSymbList); + + list_Delete(TermSymbList); + list_Delete(TermIndexlist); + + return TRUE; + } + return FALSE; +} + + +static void subs_CompVec(LITPTR litptr) +/********************************************************** + INPUT: A LITPTR pointer. + RETURNS: None. + CAUTION: Indexes are pushed on the vector. These indexes build + a component with respect to the structure litptr and to the + actual bindings. +***********************************************************/ +{ + LIST complist, end, scan; + int lit,n,i,j; + + n = litptr_Length(litptr); + complist = list_Nil(); + + + if (n > 0){ + for (j = 0; j < n; j++) { + if (!literal_GetUsed(litptr_Literal(litptr,j))) { + complist = list_Cons((POINTER)j,complist); + vec_Push((POINTER)literal_GetLitIndex(litptr_Literal(litptr,j))); + literal_PutUsed(litptr_Literal(litptr,j), TRUE); + j = n + 1; + } + } + + if (j != n) { + end = complist; + for (scan = complist; !list_Empty(scan); scan = list_Cdr(scan)) { + lit = (int)list_Car(scan); + for (i = 0; i < n; i++) { + if (!literal_GetUsed(litptr_Literal(litptr,i)) && + list_HasIntersection(literal_GetLitVarList(litptr_Literal(litptr,lit)), + literal_GetLitVarList(litptr_Literal(litptr,i)))) { + list_Rplacd(end,list_List((POINTER)i)); + end = list_Cdr(end); + vec_Push((POINTER)literal_GetLitIndex(litptr_Literal(litptr,i))); + literal_PutUsed(litptr_Literal(litptr,i), TRUE); + } + } + } + list_Delete(complist); + } + } +} + + +static BOOL subs_StVec(int i, int j, CLAUSE c1, CLAUSE c2) +/********************************************************** + INPUT: Integers i,j and two clauses c1 and c2. + i is a pointer to vector and represents a + literal in clause c1 and j stand for the j-th + literal in the clause c2. + RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. + CAUTION: None. +***********************************************************/ +{ + int a; + + if (j >= clause_Length(c2)) + return FALSE; + + a = j; + + cont_StartBinding(); + + while ((a < clause_Length(c2)) && + !(unify_Match(cont_LeftContext(), + clause_GetLiteralTerm(c1, (int) vec_GetNth(i)), + clause_GetLiteralTerm(c2,a)))){ + a++; + cont_BackTrackAndStart(); + } + + if (a >= clause_Length(c2)) { + cont_BackTrack(); + return FALSE; + } + + if ((i == (vec_ActMax()-1)) || subs_StVec(i+1, 0, c1, c2)) + return TRUE; + else + cont_BackTrack(); + + return subs_StVec(i, a+1, c1, c2); +} + + +static int subs_SearchTop(CLAUSE c1, int vec, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1, c2, a vector pointer vec. + RETURNS: The index of that literal in c1 which has the least positive + matching tests with the literals in c2. + CAUTION: None. +***********************************************************/ +{ + int index, i, j, zaehler; + + index = (int)vec_GetNth(vec); + + for (i = vec; i < vec_ActMax(); i++) { + zaehler = 0; + j = 0; + while (j < clause_Length(c2) && zaehler < 2) { + cont_StartBinding(); + if (unify_Match(cont_LeftContext(), + clause_GetLiteralTerm(c1, (int) vec_GetNth(i)), + clause_GetLiteralTerm(c2,j))) { + zaehler++; + } + cont_BackTrack(); + j++; + } + + if (zaehler == 0 || zaehler == 1) { + index = (int)vec_GetNth(i); + return index; + } + } + return index; +} + + +static BOOL subs_TcVec(CLAUSE c1, int vec, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1, c2, a vector pointer vec. + RETURNS: FALSE if the literals of c1 which are designated by + the elements of vec do not subsume c2 and TRUE otherwise. + CAUTION: None. +***********************************************************/ +{ + int a,top_index; + a = 0; + + top_index = subs_SearchTop(c1,vec,c2); + + do { + cont_StartBinding(); + while ((a < clause_Length(c2)) && + !(unify_Match(cont_LeftContext(), + clause_GetLiteralTerm(c1,top_index), + clause_GetLiteralTerm(c2,a)))) { + a++; + cont_BackTrackAndStart(); + } + + if (a >= clause_Length(c2)){ + cont_BackTrack(); + return FALSE; + } + + if ((vec - vec_ActMax()) == 1) + return TRUE; + + if (subs_InternIdc(c1, vec, c2)) + return TRUE; + else { + cont_BackTrack(); /* Dies ist der 'Hurra' Fall.*/ + a++; + } + + } while (a < clause_Length(c2)); + + return FALSE; +} + +static BOOL subs_TcVecEq(CLAUSE c1, int vec, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1, c2, a vector pointer vec. + RETURNS: FALSE if the literals of c1 which are designated by + the elements of vec do not subsume c2 and TRUE otherwise. + CAUTION: None. +***********************************************************/ +{ + int a,top_index; + BOOL search; + TERM lit1,lit2; + + a = 0; + top_index = subs_SearchTop(c1,vec,c2); + lit1 = clause_GetLiteralTerm(c1,top_index); + + do { + search = TRUE; + + while (a < clause_Length(c2) && search) { + lit2 = clause_GetLiteralTerm(c2,a); + cont_StartBinding(); + if (unify_Match(cont_LeftContext(),lit1,lit2)) + search = FALSE; + else { + if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && + fol_IsEquality(fol_Atom(lit1)) && + fol_IsEquality(fol_Atom(lit2)) && + (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c1,top_index)) || + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c2,a)))) { + cont_BackTrackAndStart(); + if (unify_Match(cont_LeftContext(), + term_FirstArgument(fol_Atom(lit1)), + term_SecondArgument(fol_Atom(lit2))) && + unify_Match(cont_LeftContext(), + term_SecondArgument(fol_Atom(lit1)), + term_FirstArgument(fol_Atom(lit2)))) + search = FALSE; + } + if (search) { + a++; + cont_BackTrack(); + } + } + } + + if (a >= clause_Length(c2)) { + cont_BackTrack(); + return FALSE; + } + + if ((vec_ActMax() - vec) == 1) + return TRUE; + + if (subs_InternIdcEq(c1, vec, c2)) + return TRUE; + else { + cont_BackTrack(); + a++; + } + + } while (a < clause_Length(c2)); + + return FALSE; +} + + +static BOOL subs_InternIdc(CLAUSE c1, int vec, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1, c2, a vector pointer vec. + RETURNS: FALSE if the literals of c1 which are designed by + the elements of vec do not subsume c2 and TRUE otherwise. + CAUTION: +***********************************************************/ +{ + int locvec; + LITPTR litptr; + + + if (!subs_IdcVecTestlits(c1,vec,c2,&litptr)) + return FALSE; + + locvec = vec_ActMax(); + + do { + subs_CompVec(litptr); + if (!vec_IsMax(locvec)) { + if (!subs_TcVec(c1,locvec,c2)) { + vec_SetMax(locvec); + litptr_Delete(litptr); + return FALSE; + } + else + vec_SetMax(locvec); + } + } while (!litptr_AllUsed(litptr)); + + litptr_Delete(litptr); + + return TRUE; +} + + +static BOOL subs_InternIdcEq(CLAUSE c1, int vec, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1, c2, a vector pointer vec. + RETURNS: FALSE if the literals of c1 which are designed by + the elements of vec do not subsume c2 and TRUE otherwise. + CAUTION: +***********************************************************/ +{ + int locvec; + LITPTR litptr; + + + if (!subs_IdcVecTestlitsEq(c1,vec,c2,&litptr)) + return FALSE; + + locvec = vec_ActMax(); + + do { + subs_CompVec(litptr); + if (!vec_IsMax(locvec)) { + if (!subs_TcVecEq(c1,locvec,c2)) { + vec_SetMax(locvec); + litptr_Delete(litptr); + return FALSE; + } + else + vec_SetMax(locvec); + } + + } while (!litptr_AllUsed(litptr)); + + litptr_Delete(litptr); + + return TRUE; +} + + +BOOL subs_Idc(CLAUSE c1, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1, c2. + RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. + CAUTION: +***********************************************************/ +{ + int i,vec; + BOOL Result; + + vec = vec_ActMax(); + + for (i = 0; i < clause_Length(c1); i++) + vec_Push((POINTER) i); + + Result = subs_InternIdc(c1,vec,c2); + + vec_SetMax(vec); + + cont_Reset(); + + return Result; +} + + +BOOL subs_IdcEq(CLAUSE c1, CLAUSE c2) +/********************************************************** + INPUT: Two clauses c1, c2. + RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. + CAUTION: +***********************************************************/ +{ + int i,vec; + BOOL Result; + + /*fputs("\n Idc on: ", stdout); clause_Print(c1); + putchar('\t'); clause_Print(c2); */ + vec = vec_ActMax(); + + for (i = 0; i < clause_Length(c1); i++) + vec_Push((POINTER) i); + + Result = subs_InternIdcEq(c1,vec,c2); + + vec_SetMax(vec); + + cont_Reset(); + + /*printf(" Result: %s ",(Result ? "TRUE" : "FALSE"));*/ + + return Result; +} + + +BOOL subs_IdcEqMatch(CLAUSE c1, CLAUSE c2, SUBST subst) +/********************************************************** + INPUT: Two clauses c1, c2. + RETURNS: FALSE if c1 do not subsume c2 and TRUE otherwise. + CAUTION: +***********************************************************/ +{ + int i,vec; + BOOL Result; + + /* fputs("\n Idc on: ", stdout); clause_Print(c1); + putchar('\t'); clause_Print(c2); DBG */ + vec = vec_ActMax(); + + for (i = 0; i < clause_Length(c1); i++) + vec_Push((POINTER) i); + + i = 0; /* Doesn't matter, there is a general cont_Reset below */ + unify_EstablishMatcher(cont_LeftContext(), subst); + + Result = subs_InternIdcEq(c1,vec,c2); + + vec_SetMax(vec); + + cont_Reset(); + + /*fputs("\nsubs_Idc end: ",stdout); clause_Print(c1); clause_Print(c2); DBG */ + + return Result; +} + + +static BOOL subs_SubsumptionVecPossibleRes(CLAUSE c1, int vec, + int beg, int end) +/********************************************************** + INPUT: Two clauses c1 and c2 and three vector pointer + vec,beg and end. + RETURNS: TRUE if all literals in c1 which indexes stand + in the vector with bottom pointer vec can + independently be matched to a literal in c2 + which indexes stand in the vector between the + pointers beg and end (exclusive). + CAUTION: None. +***********************************************************/ +{ + int j,i; + + for (i = vec; i < vec_ActMax(); i++) { + for (j = beg; j < end; j++){ + cont_StartBinding(); + if (unify_Match(cont_LeftContext(), + clause_GetLiteralTerm(c1, (int) vec_GetNth(i)), + clause_GetLiteralTerm(c1, (int) vec_GetNth(j)))) + j = end+1; + cont_BackTrack(); + } + if (j == end) + return FALSE; + } + return TRUE; +} + + +static BOOL subs_IdcVecTestlitsRes(CLAUSE c1, int vec, + int beg, int end, LITPTR* litptr) +/********************************************************** + INPUT: A clause c1, a pointer to a literal structure and + three vector pointer vec, beg and end. + RETURNS: FALSE if the literals of c1 which are designated by + the elements of vec can not be matched independently + to literal in c2 which are designated by the elements + of the vector between the pointers beg and end (exclusive). + CAUTION: A structure is build and litptr points to that structure. +***********************************************************/ +{ + LIST TermIndexlist,VarSymbList,TermSymbList; + int i; + + if (subs_SubsumptionVecPossibleRes(c1,vec,beg,end)) { + + TermIndexlist = list_Nil(); + VarSymbList = list_Nil(); + TermSymbList = list_Nil(); + + for (i = vec; i < vec_ActMax(); i++) { + VarSymbList = + subs_GetVariables(clause_GetLiteralTerm(c1, (int) vec_GetNth(i))); + + if (VarSymbList != list_Nil()) { + TermIndexlist = list_Cons(vec_GetNth(i), TermIndexlist); + TermSymbList = list_Cons(VarSymbList,TermSymbList); + } + } + + *litptr = litptr_Create(TermIndexlist,TermSymbList); + + list_Delete(TermSymbList); + list_Delete(TermIndexlist); + + return TRUE; + } + return FALSE; +} + + +static int subs_SearchTopRes(CLAUSE c1, int vec, int beg, int end) +/********************************************************** + INPUT: A clause c1, three vector pointers vec, beg and end. + RETURNS: The index of that literal in c1 which has the least positive + matching tests with the literals in c2 with respect to + vector and the vector pointers beg and end. + CAUTION: None. +***********************************************************/ +{ + int index,i,j,zaehler; + + index = (int) vec_GetNth(vec); + + for (i = vec; i < vec_ActMax(); i++) { + zaehler = 0; + j = beg; + while ((j < end) && (zaehler < 2)) { + cont_StartBinding(); + if (unify_Match(cont_LeftContext(), + clause_GetLiteralTerm(c1, (int) vec_GetNth(i)), + clause_GetLiteralTerm(c1, (int) vec_GetNth(j)))) { + zaehler++; + } + cont_BackTrack(); + j++; + } + + if (zaehler == 0 || zaehler == 1) { + index = (int)vec_GetNth(i); + return index; + } + } + return index; +} + + +static BOOL subs_TcVecRes(CLAUSE c1, int vec, int beg, int end) +/********************************************************** + INPUT: A clause c1, three vector pointers vec,beg and end. + RETURNS: FALSE if the literals of c1 which are designated by + the elements of vec do not subsume c2 with + respect to the vector and the vector pointers + beg and end and TRUE otherwise. + CAUTION: None. +***********************************************************/ +{ + int a,top_index; + + a = beg; + + top_index = subs_SearchTopRes(c1,vec,beg,end); + + do { + cont_StartBinding(); + while ((a < end) && + !unify_Match(cont_LeftContext(), + clause_GetLiteralTerm(c1,top_index), + clause_GetLiteralTerm(c1,(int)vec_GetNth(a)))) { + a++; + cont_BackTrackAndStart(); + } + + if (a >= end){ + cont_BackTrack(); + return FALSE; + } + + if ((vec - vec_ActMax()) == 1) + return TRUE; + + if (subs_InternIdcRes(c1, vec, beg, end)) + return TRUE; + else { + cont_BackTrack(); + a++; + } + + } while (a < end); + + return FALSE; +} + + +static BOOL subs_InternIdcRes(CLAUSE c1, int vec, int beg, int end) +/********************************************************** + INPUT: A clause c1 and three vector pointers vec,beg and end. + RETURNS: FALSE if the literals of c1 which are designated by + the elements of vec do not subsume c2 with respect + to vector and the vector pointers beg and end + and TRUE otherwise. + CAUTION: None. +***********************************************************/ +{ + int locvec; + LITPTR litptr; + + + if (!subs_IdcVecTestlitsRes(c1,vec,beg,end,&litptr)) + return FALSE; + + locvec = vec_ActMax(); + + do { + subs_CompVec(litptr); + if (!vec_IsMax(locvec)) { + if (!subs_TcVecRes(c1,locvec,beg,end)) { + vec_SetMax(locvec); + litptr_Delete(litptr); + return FALSE; + } + else + vec_SetMax(locvec); + } + } while (!litptr_AllUsed(litptr)); + + litptr_Delete(litptr); + + return TRUE; +} + + +BOOL subs_IdcRes(CLAUSE c1, int beg, int end) +/********************************************************** + INPUT: A clause c1 and two vector pointers beg and end. + RETURNS: FALSE if c1 do not subsume c2 with respect to + vector and the vector pointers beg and end + and TRUE otherwise. + CAUTION: +***********************************************************/ +{ + int i,vec; + BOOL Result; + + vec = vec_ActMax(); + + for (i = 0; i < clause_Length(c1); i++) + vec_Push((POINTER) i); + + Result = subs_InternIdcRes(c1, vec, beg, end); + + vec_SetMax(vec); + + cont_Reset(); + + return Result; +} + + +static BOOL subs_TcVecEqExcept(CLAUSE c1, int vec, CLAUSE c2, int i2) +/********************************************************** + INPUT: Two clauses c1, c2, a vector pointer vec. + RETURNS: FALSE if the literals of c1 which are designated by + the elements of vec do not subsume c2 and TRUE otherwise. + CAUTION: None. +***********************************************************/ +{ + int a,top_index; + BOOL search; + TERM lit1,lit2; + + a = 0; + top_index = subs_SearchTop(c1,vec,c2); + lit1 = clause_GetLiteralTerm(c1,top_index); + + do { + search = TRUE; + + while (a < clause_Length(c2) && search) { + if (a != i2) { + lit2 = clause_GetLiteralTerm(c2,a); + cont_StartBinding(); + if (unify_Match(cont_LeftContext(),lit1,lit2)) + search = FALSE; + else { + if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && + fol_IsEquality(fol_Atom(lit1)) && + fol_IsEquality(fol_Atom(lit2)) && + (clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c1,top_index)) || + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c2,a)))) { + cont_BackTrackAndStart(); + if (unify_Match(cont_LeftContext(), + term_FirstArgument(fol_Atom(lit1)), + term_SecondArgument(fol_Atom(lit2))) && + unify_Match(cont_LeftContext(), + term_SecondArgument(fol_Atom(lit1)), + term_FirstArgument(fol_Atom(lit2)))) + search = FALSE; + } + if (search) { + a++; + cont_BackTrack(); + } + } + } + else + a++; + } + + if (a>=clause_Length(c2)) { + cont_BackTrack(); + return FALSE; + } + + if ((vec_ActMax() - vec) == 1) + return TRUE; + + if (subs_InternIdcEqExcept(c1, vec, c2, i2)) + return TRUE; + else { + cont_BackTrack(); + a++; + } + + } while (a < clause_Length(c2)); + + return FALSE; +} + + +static BOOL subs_SubsumptionVecPossibleEqExcept(CLAUSE c1, int vec, + CLAUSE c2, int i2) +/********************************************************** + INPUT: Two clauses c1 and c2 and a vector pointer + and an accept literal index for c2. + RETURNS: TRUE if all literals in c1 which indexes stand + in the vector with bottom pointer vec can + independently be matched to a literal in c2. + CAUTION: None. +***********************************************************/ +{ + int i,j,n; + TERM lit1,lit2; + + n = clause_Length(c2); + for (i = vec; i < vec_ActMax(); i++) { + lit1 = clause_GetLiteralTerm(c1, (int) vec_GetNth(i)); + for (j = 0; j < n; j++) { + if (j != i2) { + lit2 = clause_GetLiteralTerm(c2,j); + cont_StartBinding(); + if (unify_Match(cont_LeftContext(),lit1,lit2)) + j = n + 1; + else { + if (symbol_Equal(term_TopSymbol(lit1),term_TopSymbol(lit2)) && + fol_IsEquality(fol_Atom(lit1)) && + fol_IsEquality(fol_Atom(lit2)) && + (clause_LiteralIsNotOrientedEquality( + clause_GetLiteral(c1,(int)vec_GetNth(i))) || + clause_LiteralIsNotOrientedEquality(clause_GetLiteral(c2,j)))) { + cont_BackTrackAndStart(); + if (unify_Match(cont_LeftContext(), + term_FirstArgument(fol_Atom(lit1)), + term_SecondArgument(fol_Atom(lit2))) && + unify_Match(cont_LeftContext(), + term_SecondArgument(fol_Atom(lit1)), + term_FirstArgument(fol_Atom(lit2)))) + j = n+1; + } + } + cont_BackTrack(); + } + } + if (j==n) + return FALSE; + } + + return TRUE; +} + + +static BOOL subs_IdcVecTestlitsEqExcept(CLAUSE c1, int vec, + CLAUSE c2, int i2, LITPTR* litptr) +/********************************************************** + INPUT: Two clauses c1, c2, a pointer to a literal structure and + a vector pointer and a literal index i2 in c2 + RETURNS: FALSE if the literals of c1 which are designated by + the elements of vec do not subsume c2 and TRUE otherwise. + CAUTION: A structure is build and litptr points to that structure. + ***********************************************************/ +{ + LIST TermIndexlist,VarSymbList,TermSymbList; + int i; + + if (subs_SubsumptionVecPossibleEqExcept(c1,vec,c2,i2)) { + + TermIndexlist = list_Nil(); + VarSymbList = list_Nil(); + TermSymbList = list_Nil(); + + for (i = vec; i < vec_ActMax(); i++) { + VarSymbList = + subs_GetVariables(clause_GetLiteralTerm(c1, (int) vec_GetNth(i))); + + if (VarSymbList != list_Nil()){ + TermIndexlist = list_Cons(vec_GetNth(i), TermIndexlist); + TermSymbList = list_Cons(VarSymbList,TermSymbList); + } + } + + *litptr = litptr_Create(TermIndexlist,TermSymbList); + + list_Delete(TermSymbList); + list_Delete(TermIndexlist); + + return TRUE; + } + return FALSE; +} + + +static BOOL subs_InternIdcEqExcept(CLAUSE c1, int vec, CLAUSE c2, int i2) +/********************************************************** + INPUT: Two clauses c1, c2, a vector pointer vec and a literal + i2 in c2 which must not be considered + RETURNS: FALSE if the literals of c1 which are designed by + the elements of vec do not subsume c2/i2 and TRUE otherwise. + CAUTION: +***********************************************************/ +{ + int locvec; + LITPTR litptr; + + + if (!subs_IdcVecTestlitsEqExcept(c1,vec,c2,i2,&litptr)) + return FALSE; + + locvec = vec_ActMax(); + + do { + subs_CompVec(litptr); + if (!vec_IsMax(locvec)) { + if (!subs_TcVecEqExcept(c1,locvec,c2,i2)) { + vec_SetMax(locvec); + litptr_Delete(litptr); + return FALSE; + } + else + vec_SetMax(locvec); + } + } while (!litptr_AllUsed(litptr)); + + litptr_Delete(litptr); + + return TRUE; +} + + +BOOL subs_IdcEqMatchExcept(CLAUSE c1, int i1, CLAUSE c2, int i2, + SUBST subst) +/********************************************************** + INPUT: Two clauses c1, c2 with the indices of two literals + which need not to be considered and a matcher + RETURNS: TRUE if (<c1>/<i1>)<subst> subsumes (<c2>/<i2>)<subst> + CAUTION: +***********************************************************/ +{ + int i,vec; + BOOL Result; + + /*fputs("\n IdcEQExcept on: \n\t", stdout); + subst_Print(subst); fputs("\n\t", stdout); + clause_Print(c1); printf(" \t\t%d \n\t",i1); + clause_Print(c2); printf(" \t\t%d \n\t",i2);*/ + + if (clause_Length(c1) == 1) + Result = TRUE; + else { + vec = vec_ActMax(); + + for (i = 0; i < clause_Length(c1); i++) + if (i != i1) + vec_Push((POINTER) i); + + i = 0; /* Doesn't matter, there is a general cont_Reset below */ + unify_EstablishMatcher(cont_LeftContext(), subst); + + Result = subs_InternIdcEqExcept(c1,vec,c2,i2); + + /* printf("Result : %d",Result); */ + + vec_SetMax(vec); + + cont_Reset(); + } + + return Result; +} diff --git a/test/spass/subsumption.h b/test/spass/subsumption.h new file mode 100644 index 0000000000000000000000000000000000000000..3f5b8ab75f247f2ac0fcb91773b9e83ccc34a637 --- /dev/null +++ b/test/spass/subsumption.h @@ -0,0 +1,87 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SUBSUMPTION * */ +/* * * */ +/* * $Module: SUBSUMPTION * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1999, 2000 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + + +#ifndef _SUBSUMPTION_ +#define _SUBSUMPTION_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "misc.h" +#include "unify.h" +#include "component.h" +#include "vector.h" +#include "clause.h" + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +#define subs__MAXLITS 100 + +static __inline__ int subs_NoException(void) +{ + return -1; +} + +void subs_Init(void); +BOOL subs_ST(int, int, CLAUSE, CLAUSE); +BOOL subs_STMulti(CLAUSE, CLAUSE); +BOOL subs_STMultiExcept(CLAUSE, CLAUSE, int, int); +BOOL subs_Subsumes(CLAUSE, CLAUSE, int, int); +BOOL subs_SubsumesBasic(CLAUSE, CLAUSE, int, int); +BOOL subs_SubsumesWithSignature(CLAUSE, CLAUSE, BOOL, LIST*); +BOOL subs_Idc(CLAUSE, CLAUSE); +BOOL subs_IdcRes(CLAUSE, int, int); +BOOL subs_IdcEq(CLAUSE, CLAUSE); +BOOL subs_IdcEqMatch(CLAUSE, CLAUSE, SUBST); +BOOL subs_IdcEqMatchExcept(CLAUSE, int, CLAUSE, int, SUBST); + +#endif + diff --git a/test/spass/symbol.c b/test/spass/symbol.c new file mode 100644 index 0000000000000000000000000000000000000000..ab1b0b450dd2c1edd3c776b77ee60fe2ed51a850 --- /dev/null +++ b/test/spass/symbol.c @@ -0,0 +1,1020 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SYMBOLS * */ +/* * * */ +/* * $Module: SYMBOL * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "symbol.h" + +SIGNATURE *symbol_SIGNATURE; + +SYMBOL symbol_STANDARDVARCOUNTER; +SYMBOL symbol_INDEXVARCOUNTER; + +const int symbol_MASK = 3; /* 0000011 */ +const int symbol_TYPEMASK = 3; /* 0000011 */ +const int symbol_STATMASK = 4; /* 0000100 */ +const int symbol_TYPESTATMASK = 7; /* 0000111 */ + + +const int symbol_TYPEBITS = 2; +const int symbol_STATBITS = 1; +const int symbol_TYPESTATBITS = 3; + +const int symbol_SIGTYPES = 4; + +const char symbol_SKFNAME[]="skf"; +const char symbol_SKCNAME[]="skc"; +const char symbol_SKPNAME[]="SkP"; +const char symbol_SKANAME[]="SkC"; +const int symbol_SKLENGTH = 3; + +static BOOL symbol_HASSIGNATURE; +static LIST symbol_FREEDSYMBOLS; + +int symbol_ACTINDEX; +int symbol_ACTSKOLEMFINDEX; +int symbol_ACTSKOLEMCINDEX; +int symbol_ACTSKOLEMAINDEX; +int symbol_ACTSKOLEMPINDEX; +int symbol_ORDERING; +char *symbol_VARSTRING; + +SYMBOL symbol_CONTEXT[symbol__MAXSIGNATURE]; + +static unsigned long symbol_COUNT[symbol__MAXSIGNATURE]; + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SYMBOL CREATION * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +int symbol_GetIncreasedOrderingCounter(void) +{ + return symbol_ORDERING++; +} + +NAT symbol_MaxStringLength(void) +/************************************************************** + INPUT: None. + RETURNS: The maximal number of characters needed for a string in the signature. +***************************************************************/ +{ + int Index; + NAT Result,Length; + SIGNATURE Entry; + + Result = 0; + + for (Index=1; Index < symbol_ACTINDEX; Index++) { + Entry = symbol_Signature(Index); + if (Entry != NULL) { + Length = Entry->length; + if (Length > Result) + Result = Length; + } + } + return Result; +} + +static SYMBOL symbol_SignatureCreate(char* String, int Type, int Arity, + int Status, PRECEDENCE Precedence) +/************************************************************** + INPUT: A pointer to a string, a type, the arity and the status + RETURNS: The symbol containing the passed parameters. + SUMMARY: Establishes a new symbol in the symbol table and returns the + internal representation (pointer and type). + CAUTION: The string is not copied! +***************************************************************/ +{ + SIGNATURE Entry; + +#ifdef CHECK + if (!symbol_SignatureExists()) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_SignatureCreate:"); + misc_ErrorReport(" Module was initialized with no signature.\n"); + misc_FinishErrorReport(); + } + if (Type < 0 || Type >= symbol_SIGTYPES) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_SignatureCreate: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if ((int)symbol_ACTINDEX >= symbol__MAXSIGNATURE && + list_Empty(symbol_FREEDSYMBOLS)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In symbol_SignatureCreate: No more symbols available.\n"); + misc_FinishUserErrorReport(); + } + + if (strlen(String)>=symbol__SYMBOLMAXLEN) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In symbol_SignatureCreate: String too long.\n"); + misc_FinishUserErrorReport(); + } + + Entry = symbol_GetSignature(); + Entry->weight = 1; + Entry->props = 0; + Entry->name = String; + Entry->length = strlen(String); + Entry->arity = Arity; + Entry->generatedBy = list_Nil(); + + if (list_Empty(symbol_FREEDSYMBOLS)) { + Entry->info = symbol_SignatureSymbol(symbol_ACTINDEX, Type, Status); + symbol_SetSignature(symbol_ACTINDEX++, Entry); + } + else { + int Index; + + Index = (int)list_Car(symbol_FREEDSYMBOLS); + symbol_FREEDSYMBOLS = list_PointerDeleteElement(symbol_FREEDSYMBOLS, + (POINTER)Index); + Entry->info = symbol_SignatureSymbol(Index, Type, Status); + symbol_SetSignature(Index, Entry); + } + + /* Define precedence of symbol */ + symbol_SetIncreasedOrdering(Precedence, Entry->info); + + return Entry->info; +} + + +SYMBOL symbol_CreateFunction(const char* String, int Arity, int Status, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A string defining a symbol name, an arity, the status the + created function symbol is supposed to have and a precedence + object. + RETURNS: A new symbol for a new function. + SUMMARY: Creates a new function symbol. + EFFECTS: Inserts the new function in the symbol table. + The precedence of the new symbol is set in <Precedence>. +***************************************************************/ +{ + if (Arity == 0) + return symbol_SignatureCreate(strcpy(memory_Malloc(symbol__SYMBOLMAXLEN), + String), + symbol_CONSTANT, Arity, Status, Precedence); + else + return symbol_SignatureCreate(strcpy(memory_Malloc(symbol__SYMBOLMAXLEN), + String), + symbol_FUNCTION, Arity, Status, Precedence); +} + +SYMBOL symbol_CreateSkolemFunction(int Arity, PRECEDENCE Precedence) +/************************************************************** + INPUT: The arity of a function to be created, and a precedence. + RETURNS: A new skolem symbol having the required arity. + SUMMARY: Creates a new function symbol. + EFFECTS: Inserts the new function in the symbol table. + The precedence of the new symbol is set in <Precedence>. +***************************************************************/ +{ + char newname[10]; + SYMBOL Result; + + Result = (SYMBOL)NULL; + + while (Result == (SYMBOL)NULL) { + if (Arity == 0) + sprintf(newname,"%s%d",symbol_SKCNAME,symbol_ACTSKOLEMCINDEX++); + else + sprintf(newname,"%s%d",symbol_SKFNAME,symbol_ACTSKOLEMFINDEX++); + if (symbol_Lookup(newname) == 0) + Result = symbol_CreateFunction(newname, Arity, symbol_STATLEX, Precedence); + } + + symbol_AddProperty(Result,SKOLEM); + + return Result; +} + + +SYMBOL symbol_CreatePredicate(const char* String, int Arity, int Status, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A string, a symbol arity, the status the created predicate + is supposed to have, and a precedence object. + RETURNS: A new symbol for a new predicate. + SUMMARY: Creates a new predicate symbol. + EFFECTS: Inserts the new predicate symbol into the symbol table. + The precedence of the new symbol is set in <Precedence>. +***************************************************************/ +{ + return symbol_SignatureCreate(strcpy(memory_Malloc(symbol__SYMBOLMAXLEN), + String), + symbol_PREDICATE, Arity, Status, Precedence); +} + +SYMBOL symbol_CreateSkolemPredicate(int Arity, PRECEDENCE Precedence) +/************************************************************** + INPUT: The arity of a new Skolem predicate symbol and a precedence object. + RETURNS: A new symbol for a new predicate. + SUMMARY: Creates a new predicate symbol. + EFFECTS: Inserts the new predicate symbol into the symbol table. + The precedence of the new symbol is set in <Precedence>. +***************************************************************/ +{ + char newname[10]; + SYMBOL Result; + + Result = (SYMBOL)NULL; + + while (Result == (SYMBOL)NULL) { + if (Arity==0) + sprintf(newname,"%s%d",symbol_SKANAME,symbol_ACTSKOLEMAINDEX++); + else + sprintf(newname,"%s%d",symbol_SKPNAME,symbol_ACTSKOLEMPINDEX++); + if (symbol_Lookup(newname) == 0) + Result = symbol_CreatePredicate(newname, Arity, symbol_STATLEX, Precedence); + } + + return Result; +} + + +SYMBOL symbol_CreateJunctor(const char* String, int Arity, int Status, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A string, a symbol arity, the status the created junctor + is supposed to have, and a precedence object. + RETURNS: A new symbol for a new junctor. + SUMMARY: Creates a new junctor symbol. + EFFECTS: Inserts the new junctor symbol into the symbol table. + The precedence of the new symbol is set in <Precedence>. +***************************************************************/ +{ + return symbol_SignatureCreate(strcpy(memory_Malloc(symbol__SYMBOLMAXLEN), + String), + symbol_JUNCTOR, Arity, Status, Precedence); +} + + +BOOL symbol_IsSymbol(SYMBOL Symbol) +/************************************************************** + INPUT: A symbol. + RETURNS: TRUE if the symbols is a variable or contained + in the symbol table. +***************************************************************/ +{ + return + (!symbol_SignatureExists() || + ((!symbol_Equal(Symbol, symbol__NULL)) && + ((symbol_IsVariable(Symbol) && Symbol<symbol_MaxVars()) || + (symbol_IsSignature(Symbol) && symbol_Index(Symbol)<symbol_ACTINDEX)))); +} + + +void symbol_Delete(SYMBOL Symbol) +/************************************************************** + INPUT: A symbol. + RETURNS: Nothing. + SUMMARY: Deletes the symbol from the symbol table and frees its memory. +***************************************************************/ +{ +#ifdef CHECK + if (!symbol_SignatureExists()) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_Delete: Module was initialized without signature.\n"); + misc_FinishErrorReport(); + } + if (!symbol_IsSymbol(Symbol)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_Delete: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if (!symbol_IsVariable(Symbol)) { + int Index; + SIGNATURE Entry; + + Index = symbol_Index(Symbol); + symbol_FREEDSYMBOLS = list_Cons((POINTER)Index,symbol_FREEDSYMBOLS); + Entry = symbol_Signature(Index); + symbol_SetSignature(Index, NULL); + symbol_FreeSignature(Entry); + } +} + +LIST symbol_GetAllSymbols(void) +/************************************************************** + INPUT: None. + RETURNS: A list of all generated symbols. +***************************************************************/ +{ + LIST Result; + + Result = list_Nil(); + + if (symbol_SignatureExists()) { + int Index; + SIGNATURE S; + + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + S = symbol_Signature(Index); + if (S != NULL) { + Result = list_Cons((POINTER)symbol_GetSigSymbol(Index), Result); + } + } + } + return Result; +} + + +LIST symbol_GetAllPredicates(void) +/************************************************************** + INPUT: None. + RETURNS: A list of all predicate symbols. +***************************************************************/ +{ + LIST Result; + + Result = list_Nil(); + + if (symbol_SignatureExists()) { + int Index; + SIGNATURE S; + + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + S = symbol_Signature(Index); + if (S != NULL && symbol_IsPredicate(symbol_GetSigSymbol(Index))) + Result = list_Cons((POINTER)symbol_GetSigSymbol(Index), Result); + } + } + return Result; +} + + +LIST symbol_GetAllFunctions(void) +/************************************************************** + INPUT: None. + RETURNS: A list of all function symbols. +***************************************************************/ +{ + LIST Result; + + Result = list_Nil(); + + if (symbol_SignatureExists()) { + int Index; + SIGNATURE S; + + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + S = symbol_Signature(Index); + if (S != NULL && symbol_IsFunction(symbol_GetSigSymbol(Index))) + Result = list_Cons((POINTER)symbol_GetSigSymbol(Index), Result); + } + } + return Result; +} + + +void symbol_FreeAllSymbols(void) +/************************************************************** + INPUT: None. + RETURNS: Nothing. + EFFECTS: Frees all generated symbols +***************************************************************/ +{ + if (symbol_SignatureExists()) { + int Index; + SIGNATURE S; + + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + S = symbol_Signature(Index); + if (S != NULL) + symbol_FreeSignature(S); + } + memory_Free(symbol_SIGNATURE, sizeof(SIGNATURE[symbol__MAXSIGNATURE])); + } + + memory_Free(symbol_VARSTRING, symbol__SYMBOLMAXLEN); + list_Delete(symbol_FREEDSYMBOLS); +} + + +void symbol_Init(BOOL Signature) +/************************************************************** + INPUT: A flag indicating whether a signature is used or not. + RETURNS: None. + SUMMARY: Initializes the Symbol Module. + EFFECTS: Initializes global variables. + CAUTION: MUST BE CALLED BEFORE ANY OTHER Symbol-FUNCTION. +***************************************************************/ +{ + symbol_ResetSkolemIndex(); + symbol_ContextClean(); + + if (Signature) + symbol_SIGNATURE = (SIGNATURE*)memory_Malloc(sizeof(SIGNATURE[symbol__MAXSIGNATURE])); + + symbol_STANDARDVARCOUNTER = symbol_GetInitialStandardVarCounter(); + symbol_INDEXVARCOUNTER = symbol_GetInitialIndexVarCounter(); + + symbol_ACTINDEX = 1; + symbol_ORDERING = 1; + symbol_VARSTRING = memory_Malloc(symbol__SYMBOLMAXLEN); + + symbol_HASSIGNATURE = Signature; + symbol_FREEDSYMBOLS = list_Nil(); +} + + +BOOL symbol_SignatureExists(void) +/************************************************************** + INPUT: None. + RETURNS: TRUE, if a symbol signature was created, FALSE otherwise. +***************************************************************/ +{ + return symbol_HASSIGNATURE; +} + +void symbol_ReinitGenericNameCounters(void) +/************************************************************** + INPUT: None. + RETURNS: Nothing. + EFFECTS: Scans the symbol signature for generic names and if + there exists some, the corresponding counters are increased. +***************************************************************/ +{ + if (symbol_SignatureExists()) { + int Index,Num; + SYMBOL Info; + SIGNATURE Entry; + char *Name,*Subname; + + for (Index=1; Index < symbol_ACTINDEX; Index++) { + Entry = symbol_Signature(Index); + if (Entry != NULL) { + Info = Entry->info; + Name = Entry->name; + if (strlen(Name)>symbol_SKLENGTH) { + Subname = Name + symbol_SKLENGTH; + + switch (symbol_Type(Info)) { + + case symbol_CONSTANT: + if (strncmp(Name,symbol_SKCNAME,symbol_SKLENGTH) == 0 && + string_StringIsNumber(Subname)) { + Num = atoi(Subname); + if (Num >= symbol_ACTSKOLEMCINDEX) + symbol_ACTSKOLEMCINDEX = Num + 1; + } + break; + case symbol_FUNCTION: + if (strncmp(Name,symbol_SKFNAME,symbol_SKLENGTH) == 0 && + string_StringIsNumber(Subname)) { + Num = atoi(Subname); + if (Num >= symbol_ACTSKOLEMFINDEX) + symbol_ACTSKOLEMFINDEX = Num + 1; + } + break; + case symbol_PREDICATE: + if (Entry->arity == 0) { + if (strncmp(Name,symbol_SKANAME,symbol_SKLENGTH) == 0 && + string_StringIsNumber(Subname)) { + Num = atoi(Subname); + if (Num >= symbol_ACTSKOLEMAINDEX) + symbol_ACTSKOLEMAINDEX = Num + 1; + } + } + else { + if (strncmp(Name,symbol_SKPNAME,symbol_SKLENGTH) == 0 && + string_StringIsNumber(Subname)) { + Num = atoi(Subname); + if (Num >= symbol_ACTSKOLEMPINDEX) + symbol_ACTSKOLEMPINDEX = Num + 1; + } + } + } + } + } + } + } +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SYMBOL SEARCHING * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +SYMBOL symbol_Lookup(const char* String) +/********************************************************** + INPUT: A pointer to a string. + RETURNS: If a symbol with name String exists in the signature, the symbol; + 0 otherwise +********************************************************/ +{ + if (symbol_SignatureExists()) { + int Index; + SIGNATURE S; + + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + S = symbol_Signature(Index); + if (S != NULL && string_Equal(String, S->name)) + return S->info; + } + } + + return 0; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SPECIALS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +void symbol_LowerSignature(void) +/************************************************************** + INPUT: None. + RETURNS: Nothing. + EFFECT: Any predicate or function symbol in the signature that + starts with a capital letter is prefixed with "ss" +***************************************************************/ +{ + int Index; + SIGNATURE Entry; + SYMBOL Info; + char* String; + + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + Entry = symbol_Signature(Index); + if (Entry != NULL) { + Info = Entry->info; + + if (symbol_IsPredicate(Info) || symbol_IsFunction(Info)) { + String = Entry->name; + if ('A' <= String[0] && String[0] <= 'Z') { + char* New; + New = (char *)memory_Malloc(symbol__SYMBOLMAXLEN); + strcpy(&(New[2]),String); + New[0] = New[1] = 's'; /* prefix "ss" */ + + Entry->name = New; + memory_Free(String,symbol__SYMBOLMAXLEN); + } + } + } + } +} + +void symbol_Dump(PRECEDENCE Precedence) +/************************************************************** + INPUT: A precedence + RETURNS: Nothing. + EFFECT: Dumps all existing symbols to stdout. +***************************************************************/ +{ + if (symbol_SignatureExists()) { + int Index; + SIGNATURE S; + fputs("Dump:", stdout); + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + S = symbol_Signature(Index); + if (S != NULL) + printf("\n\t %4d:%4d:%4d:%4d:%4d:%s:%d", Index, S->info, S->weight, + Precedence[Index], S->props, S->name, S->length); + } + } +} + + +LIST symbol_SortByPrecedence(LIST Symbols, PRECEDENCE Precedence) +/************************************************************** + INPUT: A list of symbols, and a precedence. + RETURNS: The same list where the elements are sorted with + respect to decreasing precedence. + CAUTION: Destructive. +***************************************************************/ +{ + LIST Scan1,Scan2,Min; + POINTER Exchange; + + /* We can't use list_Sort, since list_Sort expects an ordering + function that receives two arguments. Since symbol_PrecedenceGreater + requires three arguments, we have to define our own sorting function. + */ + + for (Scan1=Symbols; !list_Empty(Scan1); Scan1=list_Cdr(Scan1)) { + Min = Scan1; + for (Scan2 = list_Cdr(Scan1); !list_Empty(Scan2); Scan2 = list_Cdr(Scan2)) + if (symbol_PrecedenceGreater(Precedence, (SYMBOL) list_Car(Scan2), + (SYMBOL) list_Car(Min))) { + Exchange = list_Car(Min); + list_Rplaca(Min, list_Car(Scan2)); + list_Rplaca(Scan2, Exchange); + } + } + + return Symbols; +} + +void symbol_RearrangePrecedence(PRECEDENCE Precedence, LIST UserPrecedence) +/************************************************************** + INPUT: A precedence and a list of symbols in the user + specified precedence, sorted in decreasing order. + RETURNS: Nothing. + EFFECT: Modifies the given precedence to comply with the + symbol precedence selected by the user. +***************************************************************/ +{ + LIST Scan1, Scan2, Precedences; + + Precedences = list_Nil(); + + for (Scan1 = UserPrecedence; !list_Empty(Scan1); Scan1 = list_Cdr(Scan1)) { + Precedences = list_Cons((POINTER) symbol_Ordering(Precedence, (SYMBOL) list_Car(Scan1)), + Precedences); + } + + Precedences = list_PointerSort(Precedences); + + Scan1 = UserPrecedence; + Scan2 = Precedences; + + while (Scan1 != list_Nil() && Scan2 != list_Nil()) { + symbol_SetOrdering(Precedence, (SYMBOL) list_Car(Scan1), (int) list_Car(Scan2)); + Scan1 = list_Cdr(Scan1); + Scan2 = list_Cdr(Scan2); + } + + list_Delete(Precedences); +} + +/* unused */ +void symbol_PrintPrecedence(PRECEDENCE Precedence) +/************************************************************** + INPUT: A precedence. + RETURNS: Nothing. + EFFECT: Prints the precedence to stdout. +***************************************************************/ +{ + if (symbol_SignatureExists()) { + LIST Symbols, Scan; + int Index; + SIGNATURE S; + Symbols = list_Nil(); + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + S = symbol_Signature(Index); + if (S != NULL && + (symbol_IsPredicate(S->info) || symbol_IsFunction(S->info))) + Symbols = list_Cons((POINTER)S->info, Symbols); + } + Symbols = symbol_SortByPrecedence(Symbols, Precedence); + + for (Scan = Symbols; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + S = symbol_Signature(symbol_Index((SYMBOL)list_Car(Scan))); + fputs(S->name, stdout); + if (!list_Empty(list_Cdr(Scan))) + fputs(" > ", stdout); + } + list_Delete(Symbols); + } +} + + +void symbol_FPrintPrecedence(FILE *File, PRECEDENCE Precedence) +/************************************************************** + INPUT: A file pointer and a precedence. + RETURNS: void + EFFECT: Prints the current precedence as a setting command + in DFG syntax to <File>. +***************************************************************/ +{ + if (symbol_SignatureExists()) { + LIST Symbols,Scan; + int Index; + SIGNATURE S; + + Symbols = list_Nil(); + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + S = symbol_Signature(Index); + if (S != NULL && + (symbol_IsPredicate(S->info) || symbol_IsFunction(S->info))) + Symbols = list_Cons((POINTER)S->info, Symbols); + } + Symbols = symbol_SortByPrecedence(Symbols, Precedence); + Index = 0; + fputs("set_precedence(", File); + for (Scan = Symbols; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + S = symbol_Signature(symbol_Index((SYMBOL)list_Car(Scan))); + fputs(S->name, File); + if (!list_Empty(list_Cdr(Scan))) + putc(',', File); + if (Index > 15) { + Index = 0; + fputs("\n\t", File); + } + else + Index++; + } + fputs(").", File); + list_Delete(Symbols); + } +} + +void symbol_SetCount(SYMBOL Symbol, unsigned long Count) +/************************************************************** + INPUT: A symbol, and a symbol count. + RETURNS: Nothing. + SUMMARY: Sets the symbol count for the symbol to Count. +***************************************************************/ +{ + symbol_COUNT[symbol_Index(Symbol)] = Count; +} + +unsigned long symbol_GetCount(SYMBOL Symbol) +/************************************************************** + INPUT: A symbol. + RETURNS: The number of occurences of the symbol in the clause + set. + SUMMARY: Gets the symbol count for the symbol. +***************************************************************/ +{ + return symbol_COUNT[symbol_Index(Symbol)]; +} + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SYMBOL OUTPUT * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +void symbol_Print(SYMBOL Symbol) +/************************************************************** + INPUT: A symbol. + RETURNS: Nothing. + SUMMARY: Prints a symbol to stdout. +***************************************************************/ +{ + symbol_FPrint(stdout, Symbol); +} + + +void symbol_FPrint(FILE* File, SYMBOL Symbol) +/************************************************************** + INPUT: A file and a symbol. + RETURNS: None. + SUMMARY: Prints a symbol to the file. +***************************************************************/ +{ +#ifdef CHECK + if (!symbol_IsSymbol(Symbol)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_FPrint: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if (symbol_Equal(symbol_Null(),Symbol)) + fputs("NULL", File); + else if (symbol_IsVariable(Symbol)) { + SYMBOL NormSymbol; + + NormSymbol = symbol_NormVar(Symbol); + + if (symbol_IsStandardVariable(Symbol)) { + if (Symbol <= 6) + /* U, V, W, X, Y, Z */ + sprintf(symbol_VARSTRING,"%c", 'U' + NormSymbol - 1); + else + /* X1, X2, X3, ... */ + sprintf(symbol_VARSTRING,"X%d", NormSymbol - 6); + } + else if (symbol_IsIndexVariable(Symbol)) + /* I1, I2, I3, ... */ + sprintf(symbol_VARSTRING,"I%d", NormSymbol); + + fputs(symbol_VARSTRING, File); + } + else if (symbol_SignatureExists()) + fputs(symbol_Name(Symbol), File); + else + fprintf(File, "%d", Symbol); +} + + +void symbol_FPrintOtter(FILE* File, SYMBOL Symbol) +/************************************************************** + INPUT: A file and a symbol. + RETURNS: None. + SUMMARY: Prints a symbol in Otter format to stdout. +***************************************************************/ +{ +#ifdef CHECK + if (!symbol_IsSymbol(Symbol)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_FPrintOtter: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + if (symbol_IsVariable(Symbol)) { + SYMBOL NormSymbol; + + NormSymbol = symbol_NormVar(Symbol); + + if (symbol_IsStandardVariable(Symbol)) { + if (Symbol <= 6) + /* u, v, w, x, y, z */ + sprintf(symbol_VARSTRING,"%c", 116 + NormSymbol); + else + /* x1, x2, x3, ... */ + sprintf(symbol_VARSTRING,"x%d", NormSymbol - 6); + } + else if (symbol_IsIndexVariable(Symbol)) + /* I1, I2, I3, ... */ + sprintf(symbol_VARSTRING,"I%d", NormSymbol); + + fputs(symbol_VARSTRING, File); + } + else + if (symbol_SignatureExists()) { + if (symbol_IsConstant(Symbol)) + fprintf(File, "c%s", symbol_Name(Symbol)); + else + if (symbol_IsFunction(Symbol)) + fprintf(File, "f%s", symbol_Name(Symbol)); + else + if (symbol_IsPredicate(Symbol)) + fprintf(File, "P%s", symbol_Name(Symbol)); + else + fputs(symbol_Name(Symbol), File); + } + else + fprintf(File, "%d", Symbol); +} + + +void symbol_PrintLn(SYMBOL Symbol) +/************************************************************** + INPUT: A symbol. + RETURNS: None. + SUMMARY: Prints a symbol and a newline to stdout. +***************************************************************/ +{ + symbol_Print(Symbol); + putchar('\n'); + +} + + +void symbol_PrintAll(void) +/************************************************************** + INPUT: None. + RETURNS: None. + SUMMARY: Prints all symbols to stdout. +***************************************************************/ +{ + const int symbol_TABLEBLANKS = 2; + const int symbol_TABLETYPE = 6; /* breadth of the columns */ + const int symbol_TABLEARITY = 7; + const int symbol_TABLESTAT = 6; + const int symbol_TABLEPROP = 8; + const int symbol_TABLESTRING = 36; + + if (symbol_SignatureExists()) { + int Index; + SYMBOL Info; + SIGNATURE Entry; + unsigned int TypePos, ArityPos, StatPos, PropPos, StringPos, EndPos, ActPos; + + TypePos = symbol_TABLEBLANKS; + ArityPos = TypePos + symbol_TABLETYPE + 1; + StatPos = ArityPos + symbol_TABLEARITY + 1; + PropPos = StatPos + symbol_TABLESTAT + 1; + StringPos = PropPos + symbol_TABLEPROP + 1; + EndPos = StringPos + symbol_TABLESTRING + 1; + + fputs("\n\n", stdout); + misc_PrintChar(symbol_TABLEBLANKS, ' '); putchar('+'); + misc_PrintChar(symbol_TABLETYPE, '-'); putchar('+'); + misc_PrintChar(symbol_TABLEARITY, '-'); putchar('+'); + misc_PrintChar(symbol_TABLESTAT, '-'); putchar('+'); + misc_PrintChar(symbol_TABLEPROP, '-'); putchar('+'); + misc_PrintChar(symbol_TABLESTRING, '-'); putchar('+'); putchar('\n'); + misc_PrintChar(symbol_TABLEBLANKS, ' '); putchar('|'); + ActPos = TypePos + 1 + fputs(" Type", stdout); + misc_PrintChar((ArityPos - ActPos), ' '); putchar('|'); + ActPos = ArityPos + 1 + fputs(" Arity", stdout); + misc_PrintChar((StatPos - ActPos), ' '); putchar('|'); + ActPos = StatPos + 1 + fputs(" Stat", stdout); + misc_PrintChar((PropPos - ActPos), ' '); putchar('|'); + ActPos = PropPos + 1 + fputs(" Prop", stdout); + misc_PrintChar((StringPos - ActPos), ' '); putchar('|'); + ActPos = StringPos + 1 + fputs(" String", stdout); + misc_PrintChar((EndPos - ActPos), ' '); putchar('|'); putchar('\n'); + misc_PrintChar(symbol_TABLEBLANKS, ' '); putchar('+'); + misc_PrintChar(symbol_TABLETYPE, '-'); putchar('+'); + misc_PrintChar(symbol_TABLEARITY, '-'); putchar('+'); + misc_PrintChar(symbol_TABLESTAT, '-'); putchar('+'); + misc_PrintChar(symbol_TABLEPROP, '-'); putchar('+'); + misc_PrintChar(symbol_TABLESTRING, '-'); putchar('+'); putchar('\n'); + + for (Index = 1; Index < symbol_ACTINDEX; Index++) { + Entry = symbol_Signature(Index); + if (Entry != NULL) { + Info = Entry->info; + + misc_PrintChar(symbol_TABLEBLANKS, ' '); putchar('|'); + ActPos = TypePos + 1; + + switch (symbol_Type(Info)) { + case symbol_CONSTANT: + ActPos += fputs(" Con", stdout); break; + case symbol_FUNCTION: + ActPos += fputs(" Fun", stdout); break; + case symbol_PREDICATE: + ActPos += fputs(" Pre", stdout); break; + case symbol_JUNCTOR: + ActPos += fputs(" Jun", stdout); break; + } + misc_PrintChar((ArityPos - ActPos), ' '); putchar('|'); + ActPos = ArityPos + 1 + printf(" %3d", Entry->arity); + misc_PrintChar((StatPos - ActPos), ' '); putchar('|'); + ActPos = StatPos + 1; + if (symbol_Type(Info) == symbol_FUNCTION) { + switch (symbol_Stat(Info)) { + case symbol_STATLEX: + ActPos += fputs(" Lex", stdout); break; + case symbol_STATMUL: + ActPos += fputs(" Mul", stdout); break; + } + } + misc_PrintChar((PropPos - ActPos), ' '); putchar('|'); + ActPos = PropPos + 1 + printf(" %u", Entry->props); + misc_PrintChar((StringPos - ActPos), ' '); putchar('|'); + ActPos = StringPos + 1 + printf(" %s", Entry->name); + misc_PrintChar((EndPos - ActPos), ' '); putchar('|'); putchar('\n'); + } + } + misc_PrintChar(symbol_TABLEBLANKS, ' '); putchar('+'); + misc_PrintChar(symbol_TABLETYPE, '-'); putchar('+'); + misc_PrintChar(symbol_TABLEARITY, '-'); putchar('+'); + misc_PrintChar(symbol_TABLESTAT, '-'); putchar('+'); + misc_PrintChar(symbol_TABLEPROP, '-'); putchar('|'); + misc_PrintChar(symbol_TABLESTRING, '-'); putchar('+'); putchar('\n'); + } +} + diff --git a/test/spass/symbol.h b/test/spass/symbol.h new file mode 100644 index 0000000000000000000000000000000000000000..a31f353af8b1f864e2e35be553368289f8c2acd1 --- /dev/null +++ b/test/spass/symbol.h @@ -0,0 +1,786 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SYMBOLS * */ +/* * * */ +/* * $Module: SYMBOL * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 35442 $ * */ +/* $State$ * */ +/* $Date: 2007-03-28 17:24:40 -0700 (Wed, 28 Mar 2007) $ * */ +/* $Author: jeffc $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + + +#ifndef _SYMBOL_ +#define _SYMBOL_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "list.h" +#include "stringsx.h" + +/**************************************************************/ +/* Data Structures and Constants */ +/**************************************************************/ + +/* Critical values: the maximum length of a symbol string and the */ +/* maximum number of different variables (in one term, clause) */ +/* CAUTION: symbol__MAXVARIABLES is the overall number of */ +/* variables + 1 to provide safe allocation of contexts */ +/* ... because the first var begins with 1 instead of 0. */ + +#define symbol__SYMBOLMAXLEN 64 + +#define symbol__NOOFSTANDARDVAR 2000 +#define symbol__NOOFINDEXVAR 1000 + +#define symbol__MAXSTANDARDVAR symbol__NOOFSTANDARDVAR +#define symbol__MAXINDEXVAR (symbol__NOOFSTANDARDVAR + symbol__NOOFINDEXVAR) + +#define symbol__NOOFVARIABLES (symbol__NOOFSTANDARDVAR + symbol__NOOFINDEXVAR) +#define symbol__MAXVARIABLES (symbol__NOOFVARIABLES + 1) + +/* Symbol Types, Symbols are represented as integers. In case of */ +/* constants, functions, predicates, junctors, the two least */ +/* significant bits encode the type. Variables are just */ +/* positive integers, all other symbols negative integers */ +/* The third least significant bit encodes the status of */ +/* function symbols (lexicographic or multiset) */ + +extern const int symbol_MASK; +extern const int symbol_TYPEMASK; +extern const int symbol_STATMASK; +extern const int symbol_TYPESTATMASK; + +extern const int symbol_ARBITRARYARITY; + +extern const int symbol_TYPEBITS; +extern const int symbol_STATBITS; +extern const int symbol_TYPESTATBITS; + +extern const int symbol_SIGTYPES; + +#define symbol_CONSTANT 0 +#define symbol_FUNCTION 1 +#define symbol_PREDICATE 2 +#define symbol_JUNCTOR 3 + +#define symbol_STATLEX 0 +#define symbol_STATMUL 1 + +/* For constants, functions, predicates, junctors, is a special */ +/* symbol table available, containing the arity, status and the */ +/* print name. */ + +typedef int SYMBOL; +typedef int *PRECEDENCE; + +typedef struct signature { + char *name; /* The name of the symbol as a string */ + NAT length; /* The length of the name. Needed for efficient printing */ + int weight; /* The weight of the symbol for ordering purposes */ + int arity; /* The arity of the symbol */ + NAT props; /* Special Properties of the symbol, e.g. AC, Skolem,... */ + SYMBOL info; /* 2 LSB denote Type and 3rd LSB denotes status */ + LIST generatedBy; +} SIGNATURE_NODE, *SIGNATURE; + +typedef enum {SKOLEM=1, CUMMUTATIVE=2, ASSOCIATIVE=4, ORDRIGHT=8, ORDMUL=16, + DECLSORT=32, DOMPRED=64, ISDEF=128, FREELY=256, GENERATED=512 +} SPROPERTY; + + +#define symbol__MAXSIGNATURE 4000 + +extern SIGNATURE *symbol_SIGNATURE; + +extern SYMBOL symbol_STANDARDVARCOUNTER; +extern SYMBOL symbol_INDEXVARCOUNTER; + +extern int symbol_ACTINDEX; +extern int symbol_ACTSKOLEMFINDEX; +extern int symbol_ACTSKOLEMCINDEX; +extern int symbol_ACTSKOLEMPINDEX; +extern int symbol_ACTSKOLEMAINDEX; + +/* For matching of signature symbols */ +extern SYMBOL symbol_CONTEXT[symbol__MAXSIGNATURE]; + + +/**************************************************************/ +/* Specials */ +/**************************************************************/ + +NAT symbol_MaxStringLength(void); + +void symbol_ReinitGenericNameCounters(void); + +int symbol_GetIncreasedOrderingCounter(void); + +void symbol_Delete(SYMBOL); +BOOL symbol_IsSymbol(SYMBOL); +void symbol_Dump(PRECEDENCE); + +LIST symbol_SortByPrecedence(LIST, PRECEDENCE); +void symbol_RearrangePrecedence(PRECEDENCE, LIST); + +void symbol_LowerSignature(void); + +LIST symbol_GetAllSymbols(void); +LIST symbol_GetAllPredicates(void); +LIST symbol_GetAllFunctions(void); + +void symbol_SetCount(SYMBOL, unsigned long); +unsigned long symbol_GetCount(SYMBOL); +/**************************************************************/ +/* Symbol Comparisons */ +/**************************************************************/ + +static __inline__ BOOL symbol_Equal(SYMBOL A, SYMBOL B) +{ + return A==B; +} + +static __inline__ BOOL symbol_IsSignature(SYMBOL S) +{ + return S < 0; +} + +static __inline__ void symbol_CheckNoVariable(SYMBOL S) +{ +#ifdef CHECK + if (!symbol_IsSignature(S)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_CheckNoVariable: illegal input\n"); + misc_FinishErrorReport(); + } +#endif +} + +static __inline__ int symbol_Type(SYMBOL ActSymbol) +{ + symbol_CheckNoVariable(ActSymbol); + return (-ActSymbol) & symbol_TYPEMASK; +} + +static __inline__ BOOL symbol_IsJunctor(SYMBOL S) +{ + return (symbol_IsSignature(S) && symbol_Type(S) == symbol_JUNCTOR); +} + +static __inline__ BOOL symbol_IsFunction(SYMBOL S) +{ + return (symbol_IsSignature(S) && + (symbol_Type(S) == symbol_FUNCTION || + symbol_Type(S) == symbol_CONSTANT)); +} + +static __inline__ BOOL symbol_IsConstant(SYMBOL S) +{ + return (symbol_IsSignature(S) && symbol_Type(S) == symbol_CONSTANT); +} + +static __inline__ BOOL symbol_IsPredicate(SYMBOL S) +{ + return (symbol_IsSignature(S) && symbol_Type(S) == symbol_PREDICATE); +} + +static __inline__ BOOL symbol_IsVariable(SYMBOL S) +{ + return S > 0; +} + +static __inline__ BOOL symbol_IsStandardVariable(SYMBOL S) +{ + return symbol_IsVariable(S) && (S <= symbol__MAXSTANDARDVAR); +} + +static __inline__ BOOL symbol_IsIndexVariable(SYMBOL S) +{ + return (S > symbol__MAXSTANDARDVAR) && (S <= symbol__MAXINDEXVAR); +} + +static __inline__ BOOL symbol_IsComplex(SYMBOL S) +{ + return (!symbol_IsVariable(S) && !symbol_IsConstant(S)); +} + +static __inline__ BOOL symbol_IsSuccessor(SYMBOL S, SYMBOL P) +{ + return S > P; +} + + +/**************************************************************/ +/* Symbol Manipulation */ +/**************************************************************/ + +static __inline__ int symbol_GetInitialStandardVarCounter(void) +{ + return 0; +} + +static __inline__ int symbol_GetInitialIndexVarCounter(void) +{ + return symbol__MAXSTANDARDVAR; +} + +static __inline__ int symbol_FirstIndexVariable(void) +{ + return symbol__MAXSTANDARDVAR + 1; +} + +static __inline__ int symbol_LastIndexVariable(void) +{ + return symbol_INDEXVARCOUNTER; +} + +/* Special predefined symbols */ + +#define symbol__NULL 0 + +static __inline__ int symbol_MaxVars(void) +{ + return symbol__MAXVARIABLES; +} + +static __inline__ int symbol_MaxConsts(void) +{ + return symbol__MAXSIGNATURE; +} + +static __inline__ int symbol_MaxBaseSorts(void) +{ + return symbol__MAXSIGNATURE; +} + +static __inline__ int symbol_TypeBits(void) +{ + return symbol_TYPEBITS; +} + +static __inline__ int symbol_Null(void) +{ + return 0; +} + +static __inline__ int symbol_ActIndex(void) +{ + return symbol_ACTINDEX; +} + +static __inline__ void symbol_ResetSkolemIndex(void) +{ + symbol_ACTSKOLEMFINDEX = 0; + symbol_ACTSKOLEMCINDEX = 0; + symbol_ACTSKOLEMPINDEX = 0; + symbol_ACTSKOLEMAINDEX = 0; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * MEMORY MANAGEMENT * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +static __inline__ void symbol_FreeSignature(SIGNATURE Sig) +/*************************************************************** + INPUT: A signature datum. + RETURNS: void + EFFECTS: The datum is deleted and its memory freed. +****************************************************************/ +{ + memory_Free(Sig->name, symbol__SYMBOLMAXLEN); + list_Delete(Sig->generatedBy); + memory_Free(Sig, sizeof(SIGNATURE_NODE)); +} + +static __inline__ SIGNATURE symbol_GetSignature(void) +{ + return (SIGNATURE) memory_Malloc(sizeof(SIGNATURE_NODE)); +} + + +/**************************************************************/ +/* Symbol Creation */ +/**************************************************************/ + +static __inline__ SYMBOL symbol_CreateStandardVariable(void) +/*************************************************************** + INPUT: None + RETURNS: A new symbol for a new standard variable numbered according to + symbol_STANDARDVARCOUNTER + SUMMARY: Creates a new standard variable symbol. + EFFECTS: None +****************************************************************/ +{ +#ifdef CHECK + if (symbol_STANDARDVARCOUNTER >= symbol__MAXSTANDARDVAR) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_CreateStandardVariable: Number of standard variables exceeded.\n"); + misc_FinishErrorReport(); + } +#endif + + return (++symbol_STANDARDVARCOUNTER); +} + + +static __inline__ SYMBOL symbol_CreateIndexVariable(void) +/*************************************************************** + INPUT: None + RETURNS: A new symbol for a new index variable numbered according to + symbol_INDEXVARCOUNTER + SUMMARY: Creates a new index variable symbol. + EFFECTS: None +****************************************************************/ +{ +#ifdef CHECK + if (symbol_INDEXVARCOUNTER >= symbol__MAXINDEXVAR) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_CreateIndexVariable: Number of index variables exceeded.\n"); + misc_FinishErrorReport(); + } +#endif + + return (++symbol_INDEXVARCOUNTER); +} + + +static __inline__ SYMBOL symbol_NextIndexVariable(SYMBOL Variable) +{ +#ifdef CHECK + if ((Variable != symbol_GetInitialIndexVarCounter() && + !symbol_IsIndexVariable(Variable)) || + Variable == symbol__MAXINDEXVAR) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_NextVariable: Illegal input.\n"); + misc_FinishErrorReport(); + } +#endif + + return (Variable + 1); +} + + +static __inline__ void symbol_SetStandardVarCounter(SYMBOL Variable) +{ +#ifdef CHECK + if (Variable != symbol_GetInitialStandardVarCounter() && + !symbol_IsStandardVariable(Variable)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_SetStandardVarCounter: Illegal input.\n"); + misc_FinishErrorReport(); + } + else + if (Variable >= symbol__MAXSTANDARDVAR) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_SetStandardVarCounter: Number of standard variables exceeded.\n"); + misc_FinishErrorReport(); + } +#endif + + symbol_STANDARDVARCOUNTER = Variable; +} + +static __inline__ SYMBOL symbol_FirstVariable(void) +{ + return 1; +} + +static __inline__ BOOL symbol_GreaterVariable(SYMBOL Var1, SYMBOL Var2) +{ + return Var1 > Var2; +} + +static __inline__ void symbol_ResetStandardVarCounter(void) +{ + symbol_STANDARDVARCOUNTER = symbol_GetInitialStandardVarCounter(); +} + +void symbol_Init(BOOL); +BOOL symbol_SignatureExists(void); +void symbol_FreeAllSymbols(void); +SYMBOL symbol_CreateFunction(const char*, int, int, PRECEDENCE); +SYMBOL symbol_CreateSkolemFunction(int, PRECEDENCE); +SYMBOL symbol_CreateSkolemPredicate(int, PRECEDENCE); +SYMBOL symbol_CreatePredicate(const char*, int, int, PRECEDENCE); +SYMBOL symbol_CreateJunctor(const char*, int, int, PRECEDENCE); + +/**************************************************************/ +/* Symbol Access */ +/**************************************************************/ + +SYMBOL symbol_Lookup(const char*); + +static __inline__ int symbol_VarIndex(SYMBOL ActSymbol) +{ + return ActSymbol; +} + +static __inline__ int symbol_NormVar(SYMBOL ActSymbol) +{ + /* Normalization of variables s.t. the index of the variable + is normalized starting always with 1: + Standard variables are already normalized. + Index variables are decreased by the number of the + underlying standard variables. */ + return (ActSymbol <= symbol__MAXSTANDARDVAR) ? ActSymbol : (ActSymbol - symbol__MAXSTANDARDVAR); +} + +/* The name, index and arity macros are only defined for signature */ +/* elements not for variables. The type of the symbol is not checked */ +/* by the macros. */ + +static __inline__ int symbol_Index(SYMBOL ActSymbol) +{ + symbol_CheckNoVariable(ActSymbol); + return (-ActSymbol) >> symbol_TYPESTATBITS; +} + +static __inline__ void symbol_CheckIndexInRange(int Index) +{ +#ifdef CHECK + if (Index < 0 || Index >= symbol__MAXSIGNATURE) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_CheckIndexInRange: Symbol index is out of range.\n"); + misc_FinishErrorReport(); + } +#endif +} + +static __inline__ SYMBOL symbol_SignatureSymbol(int ActIndex, int Type, int Status) +{ + return -((ActIndex << symbol_TYPESTATBITS) + | (Status << symbol_TYPEBITS) + | Type); +} + +static __inline__ SIGNATURE symbol_Signature(int Index) + /* Returns the signature of the symbol with <Index> or NULL */ + /* if the symbol was deleted */ +{ + symbol_CheckIndexInRange(Index); + return symbol_SIGNATURE[Index]; +} + +static __inline__ void symbol_SetSignature(int ActIndex, SIGNATURE Sig) +{ + symbol_CheckIndexInRange(ActIndex); + symbol_SIGNATURE[ActIndex] = Sig; +} + +static __inline__ SYMBOL symbol_GetSigSymbol(int Index) +{ + return symbol_Signature(Index)->info; +} + +static __inline__ int symbol_Stat(SYMBOL ActSymbol) +{ + symbol_CheckNoVariable(ActSymbol); + return ((-ActSymbol) & symbol_STATMASK) >> symbol_TYPEBITS; +} + +static __inline__ SYMBOL symbol_ChangeType(SYMBOL S, int Type) +/************************************************************** + INPUT: A symbol and a new type for that symbols. + RETURNS: A new symbol that is the old symbol with type changed to <Type>, + therefore the return value is different from <S>. + EFFECT: Uses the signature memory of the input symbol. + CAUTION: Usage only allowed by the parsing modules!!! +***************************************************************/ +{ + SIGNATURE Sig; + symbol_CheckNoVariable(S); + Sig = symbol_Signature(symbol_Index(S)); + S = symbol_SignatureSymbol(symbol_Index(S), Type, symbol_Stat(S)); + Sig->info = S; + return S; +} + +static __inline__ int symbol_Arity(SYMBOL ActSymbol) +{ + return symbol_Signature(symbol_Index(ActSymbol))->arity; +} + +static __inline__ NAT symbol_PositiveArity(SYMBOL ActSymbol) +{ + int arity = symbol_Arity(ActSymbol); + if (arity < 0) + return NAT_MAX; + else + return arity; +} + +static __inline__ void symbol_SetArity(SYMBOL ActSymbol, int Arity) +{ + symbol_Signature(symbol_Index(ActSymbol))->arity = Arity; +} + +static __inline__ int symbol_ArbitraryArity(void) +{ + return -1; +} + +static __inline__ char* symbol_Name(SYMBOL ActSymbol) +{ + return symbol_Signature(symbol_Index(ActSymbol))->name; +} + +static __inline__ NAT symbol_NameLength(SYMBOL ActSymbol) +{ + return symbol_Signature(symbol_Index(ActSymbol))->length; +} + +static __inline__ int symbol_Info(SYMBOL ActSymbol) +{ + return symbol_Signature(symbol_Index(ActSymbol))->info; +} + +static __inline__ int symbol_Weight(SYMBOL ActSymbol) +{ + return symbol_Signature(symbol_Index(ActSymbol))->weight; +} + +static __inline__ int symbol_Ordering(PRECEDENCE P, SYMBOL ActSymbol) +{ + int Index; + + Index = symbol_Index(ActSymbol); +#ifdef CHECK + symbol_CheckIndexInRange(Index); + if (P[Index] < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In symbol_Ordering: Ordering of symbol %s is invalid\n", + symbol_Name(ActSymbol)); + misc_FinishErrorReport(); + } +#endif + return P[Index]; +} + +static __inline__ void symbol_SetWeight(SYMBOL ActSymbol, int Weight) +{ + symbol_Signature(symbol_Index(ActSymbol))->weight = Weight; +} + +static __inline__ void symbol_SetName(SYMBOL ActSymbol, char* Name) +{ + symbol_Signature(symbol_Index(ActSymbol))->name = Name; +} + +static __inline__ LIST symbol_GeneratedBy(SYMBOL S) +{ + return symbol_Signature(symbol_Index(S))->generatedBy; +} + +static __inline__ BOOL symbol_IsGeneratedBy(SYMBOL S1, SYMBOL S2) +{ + return list_PointerMember(symbol_GeneratedBy(S1), (POINTER)S2); +} + +static __inline__ void symbol_SetGeneratedBy(SYMBOL S, LIST SymbolList) +{ + symbol_Signature(symbol_Index(S))->generatedBy = SymbolList; +} + +static __inline__ void symbol_SetOrdering(PRECEDENCE P, SYMBOL ActSymbol, + int Ordering) +{ + int Index; + + Index = symbol_Index(ActSymbol); + symbol_CheckIndexInRange(Index); + P[Index] = Ordering; +} + +static __inline__ void symbol_SetIncreasedOrdering(PRECEDENCE P, SYMBOL S) +{ + symbol_SetOrdering(P, S, symbol_GetIncreasedOrderingCounter()); +} + + +static __inline__ BOOL symbol_PrecedenceGreater(PRECEDENCE P, SYMBOL S1, SYMBOL S2) +{ + return symbol_Ordering(P, S1) < symbol_Ordering(P, S2); +} + +static __inline__ BOOL symbol_HasProperty(SYMBOL ActSymbol, SPROPERTY Property) +{ + return (symbol_Signature(symbol_Index(ActSymbol))->props & Property); +} + +static __inline__ void symbol_AddProperty(SYMBOL ActSymbol, SPROPERTY Property) +{ + SIGNATURE S = symbol_Signature(symbol_Index(ActSymbol)); + S->props = S->props | Property; +} + +static __inline__ void symbol_RemoveProperty(SYMBOL ActSymbol, SPROPERTY Property) +{ + SIGNATURE S = symbol_Signature(symbol_Index(ActSymbol)); + if (S->props & Property) + S->props = S->props - Property; +} + +static __inline__ BOOL symbol_IsBaseSort(SYMBOL Symbol) +{ + return (symbol_Arity(Symbol) == 1); +} + +static __inline__ void symbol_ClearPrecedence(PRECEDENCE P) +{ + int i; + const int clear = -42; /* Some negative number */ + + for (i = 0; i < symbol__MAXSIGNATURE; i++) + P[i] = clear; +} + +static __inline__ PRECEDENCE symbol_CreatePrecedence(void) +{ + PRECEDENCE P; + + P = memory_Malloc(sizeof(int[symbol__MAXSIGNATURE])); + symbol_ClearPrecedence(P); + return P; +} + +static __inline__ void symbol_DeletePrecedence(PRECEDENCE P) +{ + memory_Free(P, sizeof(int[symbol__MAXSIGNATURE])); +} + +static __inline__ void symbol_TransferPrecedence(PRECEDENCE Source, + PRECEDENCE Target) + /* Copy settings from one precedence object to another */ +{ + int i; + + for (i = 0; i < symbol__MAXSIGNATURE; i++) + Target[i] = Source[i]; +} + +static __inline__ LIST symbol_DeleteSymbolFromList(LIST Symbols, SYMBOL S) + /* Deletes all occurrences of <S> from the list */ +{ + return list_DeleteElement(Symbols, (POINTER) S, + (BOOL (*)(POINTER, POINTER)) symbol_Equal); +} + +static __inline__ void symbol_DeleteSymbolList(LIST Symbols) + /* The list AND the symbols within are deleted */ +{ + list_DeleteWithElement(Symbols, (void (*)(POINTER))symbol_Delete); +} + +/**************************************************************/ +/* Symbol CONTEXT */ +/**************************************************************/ + +static __inline__ BOOL symbol_ContextIsClean(void) +{ + int i; + for (i = 0; i < symbol__MAXSIGNATURE; i++) + if (symbol_CONTEXT[i] != (SYMBOL)0) + return FALSE; + return TRUE; +} + +static __inline__ void symbol_ContextClean(void) +{ + int i; + for (i = 0; i < symbol__MAXSIGNATURE; i++) + symbol_CONTEXT[i] = (SYMBOL)0; +} + +static __inline__ BOOL symbol_ContextIsMapped(SYMBOL Symbol) +{ + int i; + for (i = 0; i < symbol__MAXSIGNATURE; i++) + if (symbol_Equal(symbol_CONTEXT[i],Symbol)) + return TRUE; + return FALSE; +} + +static __inline__ SYMBOL symbol_ContextGetValue(SYMBOL Symbol) +{ + int Index; + + Index = symbol_Index(Symbol); + symbol_CheckIndexInRange(Index); + return symbol_CONTEXT[Index]; +} + +static __inline__ void symbol_ContextSetValue(SYMBOL Symbol, SYMBOL Value) +{ + int Index; + + Index = symbol_Index(Symbol); + symbol_CheckIndexInRange(Index); + symbol_CONTEXT[Index] = Value; +} + +static __inline__ void symbol_ContextClearValue(SYMBOL Symbol) +{ + symbol_ContextSetValue(Symbol, (SYMBOL)0); +} + +static __inline__ BOOL symbol_ContextIsBound(SYMBOL Symbol) +{ + return (symbol_ContextGetValue(Symbol) != (SYMBOL)0); +} + +/**************************************************************/ +/* Symbol Output */ +/**************************************************************/ + +void symbol_Print(SYMBOL); +void symbol_PrintPrecedence(PRECEDENCE); +void symbol_FPrintPrecedence(FILE*, PRECEDENCE); +void symbol_FPrint(FILE*, SYMBOL); +void symbol_FPrintOtter(FILE*, SYMBOL); +void symbol_PrintLn(SYMBOL); +void symbol_PrintAll(void); + +#endif diff --git a/test/spass/table.c b/test/spass/table.c new file mode 100644 index 0000000000000000000000000000000000000000..639dbfd6f7a9a0060c1d44e1e4c6bfa7c4ecaded --- /dev/null +++ b/test/spass/table.c @@ -0,0 +1,553 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SIGNATURE TABLE * */ +/* * * */ +/* * $Module: TABLE * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "table.h" + + +/**************************************************************/ +/* Inline functions */ +/**************************************************************/ + +static __inline__ int table_Index(SYMBOL symbol) +{ + if (symbol_IsVariable(symbol)) + return -(int) symbol; + else + return symbol_Index(symbol); +} + + +static __inline__ TERM table_GetTerm(TERMARRAY ta) +{ + return ta->term; +} + + +static __inline__ TERMARRAY table_SetTerm(TERMARRAY ta, TERM term) +{ + ta->term = term; + return ta; +} + + +static __inline__ int table_GetStamp(TERMARRAY ta) +{ + return ta->stamp; +} + + +static __inline__ TERMARRAY table_SetStamp(TERMARRAY ta, int stamp) +{ + ta->stamp = stamp; + return ta; +} + + +static __inline__ TERMARRAY table_GetChild(TERMARRAY ta) +{ + return ta->child; +} + + +static __inline__ TERMARRAY table_SetChild(TERMARRAY ta, TERMARRAY child) +{ + ta->child = child; + return ta; +} + + +static __inline__ TERMARRAY table_GetTermarray(TABLE table) +{ + return table->ta; +} + + +static __inline__ TABLE table_SetTermarray(TABLE table, TERMARRAY ta) +{ + table->ta = ta; + return table; +} + + +static __inline__ TERMARRAY *table_GetPoss(TABLE table) +{ + return table->pos; +} + + +static __inline__ TERMARRAY table_GetPos(TABLE table, int index) +{ + return table_GetPoss(table)[index]; +} + + +static __inline__ TABLE table_SetPoss(TABLE table, TERMARRAY *ref) +{ + table->pos = ref; + return table; +} + + +static __inline__ TABLE table_SetPos(TABLE table, int index, TERMARRAY ta) +{ + table_GetPoss(table)[index] = ta; + return table; +} + + +static __inline__ int *table_GetPosstamps(TABLE table) +{ + return table->posstamp; +} + + +static __inline__ int table_GetPosstamp(TABLE table, int index) +{ + return table_GetPosstamps(table)[index]; +} + + +static __inline__ TABLE table_SetPosstamps(TABLE table, int *ref) +{ + table->posstamp = ref; + return table; +} + + +static __inline__ TABLE table_SetPosstamp(TABLE table, int index, int stamp) +{ + table_GetPosstamps(table)[index] = stamp; + return table; +} + + +static __inline__ int table_GetStampcounter(TABLE table) +{ + return table->stampcounter; +} + + +static __inline__ TABLE table_SetStampcounter(TABLE table, int stampcounter) +{ + table->stampcounter = stampcounter; + return table; +} + + +static __inline__ int table_GetOpbound(TABLE table) +{ + return table->opbound; +} + + +static __inline__ TABLE table_SetOpbound(TABLE table, int opbound) +{ + table->opbound = opbound; + return table; +} + + +static __inline__ int table_GetVarbound(TABLE table) +{ + return table->varbound; +} + + +static __inline__ TABLE table_SetVarbound(TABLE table, int varbound) +{ + table->varbound = varbound; + return table; +} + + +static __inline__ int table_GetTermbound(TABLE table) +{ + return table->termbound; +} + + +static __inline__ TABLE table_SetTermbound(TABLE table, int termbound) +{ + table->termbound = termbound; + return table; +} + + +static __inline__ BOOL table_LegalPosIndex(TABLE table, int index) +{ + return 0 <= index && index <= table_GetTermbound(table); +} + + +static __inline__ BOOL table_Stamped(TABLE table, TERMARRAY ta) +{ + return table_GetStamp(ta) == table_GetStampcounter(table); +} + + +static __inline__ TERMARRAY table_DelayedInit(TABLE table, TERMARRAY ta) +/*************************************************************** + INPUT: a table and a termarray + RETURNS: the (now stamped) termarray + EFFECT: partially initializes table by setting the + termarray's entry to the empty term +***************************************************************/ +{ + if (!table_Stamped(table, ta)) { + table_SetTerm(ta, term_Null()); + table_SetStamp(ta, table_GetStampcounter(table)); + } + return ta; +} + + +static __inline__ BOOL table_PosStamped(TABLE table, int index) +{ + return table_GetPosstamp(table, index) == table_GetStampcounter(table); +} + + +static __inline__ int table_DelayedPosInit(TABLE table, int index) +/*************************************************************** + INPUT: a table and a position index + RETURNS: the (now stamped) position index + EFFECT: partially initializes table by setting the indexed + position to the empty pointer, which means that the + term with this index is not stored in table +***************************************************************/ +{ + if (!table_PosStamped(table, index)) { + table_SetPos(table, index, (TERMARRAY) NULL); + table_SetPosstamp(table, index, table_GetStampcounter(table)); + } + return index; +} + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +TABLE table_Null(void) +{ + return (TABLE) NULL; +} + + +TABLE table_Create(int opbound, int varbound, int termbound) +/*************************************************************** + INPUT: bounds for the operator symbol, variable and term + indices of the terms to be stored in the signature + table (i. e. for every such term its top symbol index + has to be in [1, opbound] and the term numbers of its + arguments in [0, termbound] - or its variable index + in [1, varbound] if it is a variable) + RETURNS: a new (and empty) signature table +***************************************************************/ +{ + TABLE result; + +#ifdef CHECK + if (opbound < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In table_Create: negative opbound."); + misc_FinishErrorReport(); + } + if (varbound < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In table_Create: negative varbound."); + misc_FinishErrorReport(); + } + if (termbound < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In table_Create: negative termbound."); + misc_FinishErrorReport(); + } +#endif + + result = (TABLE) memory_Malloc(sizeof(struct table)); + table_SetTermarray(result, (TERMARRAY) memory_Calloc ( + opbound + varbound + 1, + sizeof(struct termarray) + ) + varbound); + /* move pointer to the middle of the array to allow negative indices */ + table_SetPoss( + result, + (TERMARRAY*) memory_Malloc((termbound + 1) * sizeof(TERMARRAY)) + ); + table_SetPosstamps(result, (int*) memory_Calloc(termbound + 1, sizeof(int))); + table_SetOpbound(result, opbound); + table_SetVarbound(result, varbound); + table_SetTermbound(result, termbound); + table_SetStampcounter(result, 1); + return result; +} + + +static void table_FreeTermarray(TERMARRAY ta, int size) +/*************************************************************** + INPUT: the termarray to free and its size + EFFECT: recursively frees the tree structure allocated for the + signature array +***************************************************************/ +{ + int i; + + if (ta) { + for (i = 0; i < size; i++) + table_FreeTermarray(table_GetChild(ta + i), size); + memory_Free(ta, size * sizeof(struct termarray)); + } +} + + +void table_Free(TABLE table) +{ + int i; + + if (table != table_Null()) { + for (i = -table_GetVarbound(table); i <= table_GetOpbound(table); i++) + table_FreeTermarray( + table_GetChild(table_GetTermarray(table) + i), + table_GetTermbound(table) + 1 + ); + memory_Free( + table_GetTermarray(table) - table_GetVarbound(table), + (table_GetOpbound(table) + table_GetVarbound(table) + 1) * sizeof(struct + termarray) + ); + memory_Free( + table_GetPoss(table), + (table_GetTermbound(table) + 1) * sizeof(TERMARRAY) + ); + memory_Free( + table_GetPosstamps(table), + (table_GetTermbound(table) + 1) * sizeof(int) + ); + memory_Free(table, sizeof(struct table)); + } +} + + +TABLE table_Init(TABLE table, int opbound, int varbound, int termbound) +/*************************************************************** + INPUT: the table to recycle and bounds for the operator + symbol, variable and term indices of the terms to be + stored in the signature table (i. e. for every such + term its top symbol index has to be in [1, opbound] + and the term numbers of its arguments in + [0, termbound] - or its variable index in + [1, varbound] if it is a variable) + RETURNS: a cleaned up signature table + CAUTION: potentially frees the old table, therefore must be + called inside of an assignment like: + table = table_Init(table, ...) +***************************************************************/ +{ + int opmax, varmax, termmax, i; + TERMARRAY old; + +#ifdef CHECK + if (opbound < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In table_Init: negative opbound."); + misc_FinishErrorReport(); + } + if (varbound < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In table_Init: negative varbound."); + misc_FinishErrorReport(); + } + if (termbound < 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In table_Init: negative termbound."); + misc_FinishErrorReport(); + } +#endif + + opmax = table_GetOpbound(table) > opbound ? table_GetOpbound(table) : + opbound; + varmax = table_GetVarbound(table) > varbound ? table_GetVarbound(table) : + varbound; + termmax = table_GetTermbound(table) > termbound ? table_GetTermbound(table) : + termbound; + table_SetStampcounter(table, table_GetStampcounter(table) + 1); + + /* in case of stamp overflow or too small termarray nodes get a new table: */ + if (table_GetStampcounter(table)<=0 || termbound>table_GetTermbound(table)) { + table_Free(table); + return table_Create(opmax, varmax, termmax); + } + + /* if only the top layer of the tree is too small get a larger top layer: */ + else if (opbound+varbound > table_GetOpbound(table)+table_GetVarbound(table)){ + old = table_GetTermarray(table); + table_SetTermarray(table, (TERMARRAY) memory_Calloc( + opmax + varmax + 1, + sizeof(struct termarray) + ) + varmax); + for (i = -table_GetVarbound(table); i <= table_GetOpbound(table); i++) + table_SetChild(table_GetTermarray(table) + i, table_GetChild(old + i)); + memory_Free( + old - table_GetVarbound(table), + (table_GetOpbound(table) + table_GetVarbound(table) + 1) * sizeof(struct + termarray) + ); + table_SetOpbound(table, opmax); + table_SetVarbound(table, varmax); + return table; + } + + else { + + /* move pointer to termarray's new middle: */ + table_SetTermarray( + table, + table_GetTermarray(table) + table_GetOpbound(table) - opbound + ); + + table_SetVarbound( + table, + table_GetOpbound(table) + table_GetVarbound(table) - opbound + ); + table_SetOpbound(table, opbound); + return table; + } +} + + +TERM table_QueryAndEnter(TABLE table, PARTITION p, TERM term) +/*************************************************************** + RETURNS: a term with the same p-signature (sigtab_Index(top + symbol), [arg 1] , ..., [arg n] ) as term - or the + p p + empty term if no such term exists + EFFECT: term enters table in the latter case +***************************************************************/ +{ + TERMARRAY ta; + LIST terms; + +#ifdef CHECK + if (part_Size(p) - 1 > table_GetTermbound(table)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In table_QueryAndEnter: partition not suitable."); + misc_FinishErrorReport(); + } + if (table_Index(term_TopSymbol(term)) > table_GetOpbound(table)) { + misc_StartErrorReport(); + misc_ErrorReport + ("\n In table_QueryAndEnter: term's operation symbol out of bounds."); + misc_FinishErrorReport(); + } + if (table_Index(term_TopSymbol(term)) < -table_GetVarbound(table)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In table_QueryAndEnter: variable out of bounds."); + misc_FinishErrorReport(); + } + if (!table_LegalPosIndex(table, term_Size(term))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In table_QueryAndEnter: term out of bounds."); + misc_FinishErrorReport(); + } +#endif + + ta = table_GetTermarray(table) + table_Index(term_TopSymbol(term)); + for (terms = term_ArgumentList(term); !list_Empty(terms); terms = + list_Cdr(terms)) { + if (!table_GetChild(ta)) + table_SetChild(ta, (TERMARRAY) memory_Calloc ( + table_GetTermbound(table) + 1, + sizeof(struct termarray) + )); + ta = table_GetChild(ta) + part_Find(p, term_Size(list_Car(terms))); + } + table_DelayedInit(table, ta); + if (table_GetTerm(ta)) + return table_GetTerm(ta); + else { + table_SetTerm(ta, term); + table_SetPos(table, table_DelayedPosInit(table, term_Size(term)), ta); + return term_Null(); + } +} + + +TABLE table_Delete(TABLE table, TERM term) +/*************************************************************** + EFFECT: if term has entered table before, it is deleted +***************************************************************/ +{ + int no; + +#ifdef CHECK + if (!table_LegalPosIndex(table, term_Size(term))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In table_Delete: illegal table access."); + misc_FinishErrorReport(); + } +#endif + + no = term_Size(term); + table_DelayedPosInit(table, no); + if (table_GetPos(table, no)) { + +#ifdef CHECK + if (!table_Stamped(table, table_GetPos(table, no))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In table_Delete: table corrupted."); + misc_FinishErrorReport(); + } +#endif + + table_SetTerm(table_GetPos(table, no), term_Null()); + table_SetPos(table, no, (TERMARRAY) NULL); + } + return table; +} + diff --git a/test/spass/table.h b/test/spass/table.h new file mode 100644 index 0000000000000000000000000000000000000000..e0024a402cdba702bee28c2d831508ad37c61d94 --- /dev/null +++ b/test/spass/table.h @@ -0,0 +1,101 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * SIGNATURE TABLE * */ +/* * * */ +/* * $Module: TABLE * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/* module manages signature tables i. e. tables of terms (including the empty */ +/* term NULL) where the lookup key is the tuple of top symbol index and */ +/* arguments' equivalence classes with respect to a partition p, the */ +/* _p-signature_ (sigtab_Index(top symbol), [arg 1] , ..., [arg n] ) */ +/* p p */ + +#ifndef _TABLE_ +#define _TABLE_ + + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "term.h" +#include "partition.h" + + +/**************************************************************/ +/* Basic types */ +/**************************************************************/ + +typedef struct termarray { + TERM term; + int stamp; + struct termarray *child; +} *TERMARRAY; + +typedef struct table { + TERMARRAY ta, *pos; + int *posstamp, stampcounter, opbound, varbound, termbound; +} +*TABLE; + +/* a signature table is an "array of terms allocated by need" (i. e. a tree */ +/* where the nodes of the same layer represent array entries with the same */ +/* dimension), an array of positions in this "array", stamps for the */ +/* positions, the stamp counter and bounds for the operator symbol, variable */ +/* and term indices of the terms to be stored in the signature table (i. e. */ +/* for every such term its top symbol index has to be in [1, opbound] and the */ +/* term numbers of its arguments in [0, termbound] - or its variable index in */ +/* [1, varbound] if it is a variable) */ + + +/**************************************************************/ +/* Prototypes */ +/**************************************************************/ + +TABLE table_Null(void); +TABLE table_Create(int, int, int); +void table_Free(TABLE); +TABLE table_Init(TABLE, int, int, int); +TERM table_QueryAndEnter(TABLE, PARTITION, TERM); +TABLE table_Delete(TABLE, TERM); + + +#endif + diff --git a/test/spass/tableau.c b/test/spass/tableau.c new file mode 100644 index 0000000000000000000000000000000000000000..5b1ab8aa77d17c81433db38aa2b9c06c41a50440 --- /dev/null +++ b/test/spass/tableau.c @@ -0,0 +1,880 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * TABLEAU PROOF TREES * */ +/* * * */ +/* * Copyright (C) 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ + +/* $RCSfile$ */ + +#include "tableau.h" + +/* for graph output */ +extern BOOL pcheck_ClauseCg; +extern GRAPHFORMAT pcheck_GraphFormat; + +TABPATH tab_PathCreate(int MaxLevel, TABLEAU Tab) +/************************************************************** + INPUT: A tableau, its maximum expected depth + RETURNS: A path consisting of the root node of the tableau + which can have a max length of <MaxLevel> +***************************************************************/ +{ + TABPATH TabPath; + + TabPath = (TABPATH)memory_Malloc(sizeof(TABPATH_NODE)); + TabPath->Path = (TABLEAU*)memory_Malloc(sizeof(TABLEAU)*(MaxLevel+1)); + TabPath->Path[0] = Tab; + TabPath->MaxLength = MaxLevel; + TabPath->Length = 0; + + return TabPath; +} + +void tab_PathDelete(TABPATH TabPath) +/************************************************************** + INPUT: A tableau path. + RETURNS: Nothing. + EFFECTS: The path is deleted. +***************************************************************/ +{ + memory_Free(TabPath->Path, (TabPath->MaxLength+1)*sizeof(TABLEAU)); + memory_Free(TabPath, sizeof(TABPATH_NODE)); +} + + +BOOL tab_PathContainsClause(TABPATH Path, CLAUSE Clause) +/************************************************************** + INPUT: A tableau path, a clause + RETURNS: TRUE iff the clause exists on its level (wrt. the + path) in the tableau +***************************************************************/ +{ + LIST Scan; + + if (clause_SplitLevel(Clause) > tab_PathLength(Path)) + return FALSE; + + for (Scan = tab_Clauses(tab_PathNthNode(Path, clause_SplitLevel(Clause))); + !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (list_Car(Scan) == Clause) + return TRUE; + } + return FALSE; +} + +static BOOL tab_PathContainsClauseSoft(TABPATH Path, CLAUSE Clause) +/************************************************************** + INPUT: A tableau path, a clause + RETURNS: TRUE iff the clause is on one of the levels + in the tableau traversed by the path. Different + from tab_PathContainsClauseSoft, since it does + not expect the clause on its split level. +***************************************************************/ +{ + LIST Scan; + int Level; + + if (clause_SplitLevel(Clause) > tab_PathLength(Path)) + return FALSE; + + for (Level = 0; Level <= tab_PathLength(Path); Level++) { + for (Scan = tab_Clauses(tab_PathNthNode(Path, Level)); + !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (list_Car(Scan) == Clause) + return TRUE; + } + } + return FALSE; +} + +/* unused */ +/*static*/ BOOL tab_PathContainsClauseRobust(TABPATH P, CLAUSE C) +/************************************************************** + INPUT: A tableau path, a clause + RETURNS: TRUE if clause can be find on the path (not + necessarily on its level) + EFFECTS: Prints a note if clause cannot be found on + its level. Intended for debugging. +***************************************************************/ +{ + if (tab_PathContainsClause(P,C)) + return TRUE; + + if (tab_PathContainsClauseSoft(P,C)) { + fputs("NOTE: Clause is found on path, but not indexed by level.\n", stderr); + clause_PParentsFPrint(stderr,C); + fflush(stderr); + return TRUE; + } + return FALSE; +} + + +void tab_AddSplitAtCursor(TABPATH Path, BOOL LeftSide) +/************************************************************** + INPUT: A tableau path, a flag + RETURNS: Nothing. + EFFECTS: Extends the tableau containing the path <Path> to + the left if <LeftSide> is TRUE, to the right + otherwise +***************************************************************/ +{ + TABLEAU Tab, NewBranch; + + Tab = tab_PathTop(Path); + NewBranch = tab_CreateNode(); + if (LeftSide) { + +#ifdef CHECK + if (!tab_LeftBranchIsEmpty(Tab)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In tab_AddSplitAtCursor: Recreating existing"); + misc_ErrorReport(" left branch in tableau.\n"); + misc_FinishErrorReport(); + } +#endif + + tab_SetLeftBranch(Tab,NewBranch); + } else { + +#ifdef CHECK + if (!tab_RightBranchIsEmpty(Tab)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In tab_AddSplitAtCursor: Recreating existing"); + misc_ErrorReport(" right branch in tableau.\n"); + misc_FinishErrorReport(); + } +#endif + tab_SetRightBranch(Tab, NewBranch); + } + tab_PathPush(NewBranch, Path); +} + +void tab_AddClauseOnItsLevel(CLAUSE C, TABPATH Path) +/************************************************************** + INPUT: A clause, a tableau path + RETURNS: Nothing + EFFECTS: Adds the clause on its split level which + must belong to <Path> +***************************************************************/ +{ + int Level; + + Level = clause_SplitLevel(C); + if (Level > tab_PathLength(Path)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\nError: Split level of some clause "); + misc_UserErrorReport("\nis higher than existing level."); + misc_UserErrorReport("\nThis may be a bug in the proof file."); + misc_FinishUserErrorReport(); + } + + tab_AddClause(C, tab_PathNthNode(Path, clause_SplitLevel(C))); +} + + +int tab_Depth(TABLEAU T) +/************************************************************** + INPUT: A tableau + RETURNS: The depth of the tableau +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return 0; + if (tab_IsLeaf(T)) + return 0; + else + return (misc_Max(tab_Depth(tab_RightBranch(T))+1, tab_Depth(tab_LeftBranch(T)))+1); +} + +static BOOL tab_HasEmptyClause(TABLEAU T) +/************************************************************** + INPUT: A tableau + RETURNS: TRUE iff an empty clause is among the clauses + on this level +***************************************************************/ +{ + LIST Scan; + + for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (clause_IsEmptyClause(list_Car(Scan))) + return TRUE; + + return FALSE; +} + + +BOOL tab_IsClosed(TABLEAU T) +/************************************************************** + INPUT: A Tableau + RETURNS: TRUE iff the tableau is closed. (NOTE: FALSE + if the tableau is empty) +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return FALSE; + + if (tab_HasEmptyClause(T)) + return TRUE; + /* + * now tableau can only be closed + * if there has been a split, and + * both subtableaus are closed + */ + + if (tab_RightBranchIsEmpty(T) || tab_LeftBranchIsEmpty(T)) { + printf("\nopen node label: %d", T->Label); + fflush(stdout); + + return FALSE; + } + return tab_IsClosed(tab_RightBranch(T)) && tab_IsClosed(tab_LeftBranch(T)); +} + +static LIST tab_DeleteFlat(TABLEAU T) +/************************************************************** + INPUT: A tableau + RETURNS: The list of its clauses on the first level of + the tableau + EFFECTS: Frees the root tableau node. +***************************************************************/ +{ + LIST Clauses; + + Clauses = tab_Clauses(T); + memory_Free(T, sizeof(TABLEAU_NODE)); + + return Clauses; +} + + +static void tab_DeleteGen(TABLEAU T, LIST* Clauses, BOOL DeleteClauses) +/************************************************************** + INPUT: A tableau, a list of clauses by reference, a flag + RETURNS: Nothing + EFFECTS: Depending on <DeleteClauses>, all clauses in the + tableau are added to <Clauses> or just deleted. + The memory for the tableau and its clause lists is + freed. +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return; + + tab_DeleteGen(tab_RightBranch(T), Clauses, DeleteClauses); + tab_DeleteGen(tab_LeftBranch(T), Clauses, DeleteClauses); + + list_Delete(tab_RightSplitClauses(T)); + if (DeleteClauses) + list_Delete(tab_Clauses(T)); + else + *Clauses = list_Nconc(tab_Clauses(T), *Clauses); + + tab_DeleteFlat(T); + +} + +static void tab_DeleteCollectClauses(TABLEAU T, LIST* Clauses) +/************************************************************** + INPUT: A tableau, a list of clauses by reference + RETURNS: Nothing + EFFECTS: Frees the memory of the tableau, but collects + its clauses +***************************************************************/ +{ + tab_DeleteGen(T, Clauses, FALSE); +} + +void tab_Delete(TABLEAU T) +/************************************************************** + INPUT: A tableau + RETURNS: Nothing + EFFECTS: Frees the memory of the tableau +***************************************************************/ +{ + LIST Redundant; + + Redundant = list_Nil(); + tab_DeleteGen(T, &Redundant, TRUE); +} + +static void tab_SetSplitLevelsRec(TABLEAU T, int Level) +/************************************************************** + INPUT: A tableau + RETURNS: Nothing + EFFECTS: The split levels of the clauses in the + tableau are set to the level of the + tableau level they are contained in. +***************************************************************/ +{ + LIST Scan; + + if (tab_IsEmpty(T)) + return; + + for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + clause_SetSplitLevel(list_Car(Scan), Level); + if (Level >0) { + clause_ClearSplitField(list_Car(Scan)); + clause_SetSplitFieldBit(list_Car(Scan), Level); + } + else + clause_SetSplitField(list_Car(Scan), (SPLITFIELD)NULL,0); + } + + tab_SetSplitLevelsRec(tab_RightBranch(T), Level+1); + tab_SetSplitLevelsRec(tab_LeftBranch(T), Level+1); +} + +void tab_SetSplitLevels(TABLEAU T) +/************************************************************** + INPUT: A tableau + RETURNS: Nothing + EFFECTS: The split levels of the clauses in the + tableau are set to the level of the + tableau they belong to. +***************************************************************/ +{ + tab_SetSplitLevelsRec(T,0); +} + + +TABLEAU tab_PruneClosedBranches(TABLEAU T, LIST* Clauses) +/************************************************************** + INPUT: A tableau, a list of clauses by reference. + RETURNS: The (destructively) reduced tableau: Descendants of + nodes that have an empty clause are deleted. + EFFECTS: The tableau is modified. +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return T; + + /* if there is an empty clause on this level, delete subtrees */ + + if (tab_HasEmptyClause(T)) { + + tab_DeleteCollectClauses(tab_RightBranch(T), Clauses); + tab_DeleteCollectClauses(tab_LeftBranch(T), Clauses); + tab_SetRightBranch(T, tab_EmptyTableau()); + tab_SetLeftBranch(T, tab_EmptyTableau()); + list_Delete(tab_RightSplitClauses(T)); + tab_SetRightSplitClauses(T, list_Nil()); + tab_SetSplitClause(T,clause_Null()); + tab_SetLeftSplitClause(T, clause_Null()); + } + /* else recursively prune subtrees */ + else { + tab_SetRightBranch(T, tab_PruneClosedBranches(tab_RightBranch(T), Clauses)); + tab_SetLeftBranch(T, tab_PruneClosedBranches(tab_LeftBranch(T), Clauses)); + } + + return T; +} + + +TABLEAU tab_RemoveIncompleteSplits(TABLEAU T, LIST* Clauses) +/************************************************************** + INPUT: A Tableau, a list of clauses by reference + RETURNS: The reduced tableau: If a node has exactly one + successor (that is, the corresponding split was + not completed), delete the successor and move + its subtrees to <T>. + EFFECTS: The successor node is deleted, and its clauses added + to <Clauses> +***************************************************************/ +{ + LIST NewClauses; + TABLEAU Child; + + if (tab_IsEmpty(T)) + return T; + + if (tab_IsLeaf(T)) + return T; + + if (!tab_IsEmpty(tab_RightBranch(T)) && + !tab_IsEmpty(tab_LeftBranch(T))) { + tab_SetRightBranch(T, tab_RemoveIncompleteSplits(tab_RightBranch(T), Clauses)); + tab_SetLeftBranch(T, tab_RemoveIncompleteSplits(tab_LeftBranch(T), Clauses)); + return T; + } + if (tab_IsEmpty(tab_RightBranch(T))) + Child = tab_LeftBranch(T); + else + Child = tab_RightBranch(T); + + Child = tab_RemoveIncompleteSplits(Child, Clauses); + + tab_SetLeftBranch(T, tab_LeftBranch(Child)); + tab_SetRightBranch(T, tab_RightBranch(Child)); + + /* copy split data */ + + tab_SetSplitClause(T, tab_SplitClause(Child)); + tab_SetLeftSplitClause(T, tab_LeftSplitClause(Child)); + tab_SetRightSplitClauses(T, tab_RightSplitClauses(Child)); + + /* delete ancestors of deleted clauses and remember */ + + NewClauses = tab_DeleteFlat(Child); + (*Clauses) = list_Nconc(NewClauses, *Clauses); + + return T; +} + + +void tab_CheckEmpties(TABLEAU T) +/************************************************************** + INPUT: A tableau + RETURNS: Nothing. + EFFECTS: Prints warnings if non-leaf nodes contain + empty clauses (which should not be the case + after pruning any more), of if leaf nodes + contain more than one empty clause +***************************************************************/ +{ + LIST Scan, Empties; + BOOL Printem; + + if (tab_IsEmpty(T)) + return; + + /* get all empty clauses in this node */ + Empties = list_Nil(); + for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (clause_IsEmptyClause(list_Car(Scan))) + Empties = list_Cons(list_Car(Scan), Empties); + } + Printem = FALSE; + if (!list_Empty(Empties) && !tab_IsLeaf(T)) { + puts("\nNOTE: non-leaf node contains empty clauses."); + Printem = TRUE; + } + + if (tab_IsLeaf(T) && list_Length(Empties) > 1) { + puts("\nNOTE: Leaf contains more than one empty clauses."); + Printem = TRUE; + } + if (Printem) { + puts("Clauses:"); + clause_PParentsListPrint(tab_Clauses(T)); + } + list_Delete(Empties); + tab_CheckEmpties(tab_LeftBranch(T)); + tab_CheckEmpties(tab_RightBranch(T)); +} + + +void tab_GetAllEmptyClauses(TABLEAU T, LIST* L) +/************************************************************** + INPUT: A tableau, a list by reference + RETURNS: All empty clauses in the tableau prepended to <L>. +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return; + + tab_GetAllEmptyClauses(tab_LeftBranch(T), L); + tab_GetAllEmptyClauses(tab_RightBranch(T), L); +} + + +void tab_GetEarliestEmptyClauses(TABLEAU T, LIST* L) +/************************************************************** + INPUT : A tableau, a list of clauses by reference + RETURNS: Nothing. + EFFECTS: For each leaf node, adds empty clauses in + leaf nodes to <L>. If the leaf node contains only one + empty clause, it is added to <L> anyway. + If the leaf node contains more than one empty clause, + the earliest derived empty clause is added to <L>. +***************************************************************/ +{ + CLAUSE FirstEmpty; + LIST Scan; + + if (tab_IsEmpty(T)) + return; + + if (tab_IsLeaf(T)) { + FirstEmpty = clause_Null(); + + for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (clause_IsEmptyClause(list_Car(Scan))) { + if (FirstEmpty == clause_Null()) + FirstEmpty = list_Car(Scan); + else if (clause_Number(FirstEmpty) > clause_Number(list_Car(Scan))) + FirstEmpty = list_Car(Scan); + } + } + + if (FirstEmpty != clause_Null()) + (*L) = list_Cons(FirstEmpty, *L); + } + tab_GetEarliestEmptyClauses(tab_LeftBranch(T), L); + tab_GetEarliestEmptyClauses(tab_RightBranch(T), L); + +} + +void tab_ToClauseList(TABLEAU T, LIST* Proof) +/************************************************************** + INPUT: A tableau <T>, a list of clauses + RETURNS: Nothing. + EFFECTS: All clauses in T are added to <Proof> +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return; + + (*Proof) = list_Nconc(list_Copy(tab_Clauses(T)), *Proof); + + tab_ToClauseList(tab_LeftBranch(T),Proof); + tab_ToClauseList(tab_RightBranch(T),Proof); +} + + +static void tab_ToSeqProofOrdered(TABLEAU T, LIST* Proof) +/************************************************************** + INPUT: A tableau <T>, a list of clauses <Proof> representing a + proof by reference + RETURNS: The sequential proof corresponding to the tableau. +***************************************************************/ +{ + LIST Scan; + BOOL RightSplitRead, LeftSplitRead; + + if (tab_IsEmpty(T)) + return; + + Scan = tab_Clauses(T); + RightSplitRead = LeftSplitRead = FALSE; + + while (!list_Empty(Scan)) { + /* insert left and right splits and descendants controlled by clause number */ + + if (!RightSplitRead && !tab_RightBranchIsEmpty(T) && + clause_Number(list_Car(Scan)) < + clause_Number(list_Car(tab_RightSplitClauses(T)))) { + tab_ToSeqProofOrdered(tab_RightBranch(T), Proof); + RightSplitRead = TRUE; + } + if (!LeftSplitRead && !tab_LeftBranchIsEmpty(T) && + clause_Number(list_Car(Scan)) < + clause_Number(tab_LeftSplitClause(T))) { + tab_ToSeqProofOrdered(tab_LeftBranch(T), Proof); + LeftSplitRead = TRUE; + } + (*Proof) = list_Cons(list_Car(Scan), *Proof); + Scan = list_Cdr(Scan); + } + /* if a split clause with descendants has not been inserted yet, + it been generated after all other clauses */ + + if (!RightSplitRead) + tab_ToSeqProofOrdered(tab_RightBranch(T), Proof); + if (!LeftSplitRead) + tab_ToSeqProofOrdered(tab_LeftBranch(T), Proof); +} + + +/****************************************************************/ +/* SPECIALS FOR GRAPHS */ +/****************************************************************/ + +static void tab_LabelNodesRec(TABLEAU T, int* Num) +/************************************************************** + INPUT: A Tableau, a number by reference + RETURNS: Nothing. + EFFECTS: Labels the tableau nodes dflr, starting with <Num> +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return; + T->Label = *Num; + (*Num)++; + tab_LabelNodesRec(tab_LeftBranch(T), Num); + tab_LabelNodesRec(tab_RightBranch(T), Num); +} + + +void tab_LabelNodes(TABLEAU T) +/************************************************************** + INPUT: A Tableau, a number by reference + RETURNS: Nothing. + EFFECTS: Labels the tableau nodes dflr, starting with 0 +***************************************************************/ +{ + int Num; + + Num = 0; + tab_LabelNodesRec(T, &Num); +} + + +static void tab_FPrintNodeLabel(FILE *File, TABLEAU T) +/************************************************************** + INPUT: A file handle, a tableau + RETURNS: Nothing. + EFFECTS: Prints the root node information to <File>: + clauses, split information +***************************************************************/ +{ + LIST Scan; + + /* start printing of node label string */ + + fprintf(File, "\"label: %d\\n", T->Label); + + /* print left and right parts of split */ + fputs("SplitClause : ", File); + clause_PParentsFPrint(File, tab_SplitClause(T)); + fputs("\\nLeft Clause : ", File); + clause_PParentsFPrint(File, tab_LeftSplitClause(T)); + fputs("\\nRightClauses: ", File); + if (list_Empty(tab_RightSplitClauses(T))) + fputs("[]\\n", File); + else { + clause_PParentsFPrint(File, list_Car(tab_RightSplitClauses(T))); + fputs("\\n", File); + for (Scan = list_Cdr(tab_RightSplitClauses(T)); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + fputs(" ", File); + clause_PParentsFPrint(File, list_Car(Scan)); + fputs("\\n", File); + } + } + /* print clause at this level */ + if (pcheck_ClauseCg) { + if (list_Empty(tab_Clauses(T))) + fputs("[]", File); + else { + for (Scan = tab_Clauses(T); !list_Empty(Scan); Scan = list_Cdr(Scan)){ + clause_PParentsFPrint(File, list_Car(Scan)); + fputs("\\n", File); + } + } + } + putc('"', File); /* close string */ +} + + +static void tab_FPrintEdgeCgFormat(FILE* File, int Source, int Target, BOOL Left) +/************************************************************** + INPUT: A file handle, two node labels, a flag + RETURNS: Nothing. + EFFECTS: Prints the edge denoted by <Source> and <Target> + to <File>, with an edge label (0/1) according to <Left>. + The edge label is added since xvcg cannot handle + ordered edges. +***************************************************************/ +{ + fputs("\nedge: {", File); + fprintf(File, "\nsourcename: \"%d\"", Source); + fprintf(File, "\ntargetname: \"%d\"\n", Target); + fputs("\nlabel: \"", File); + if (Left) + putc('0', File); + else + putc('1', File); + fputs("\" }\n", File); +} + + +static void tab_FPrintEdgesCgFormat(FILE* File, TABLEAU T) +/************************************************************** + INPUT: A file handle, a tableau + RETURNS: Nothing. + EFFECTS: Prints edge information of <T> in xvcg graph format + to <File>. +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return; + + if (!tab_LeftBranchIsEmpty(T)) + tab_FPrintEdgeCgFormat(File, T->Label, tab_LeftBranch(T)->Label, TRUE); + if (!tab_RightBranchIsEmpty(T)) + tab_FPrintEdgeCgFormat(File, T->Label, tab_RightBranch(T)->Label, FALSE); + + tab_FPrintEdgesCgFormat(File, tab_LeftBranch(T)); + tab_FPrintEdgesCgFormat(File, tab_RightBranch(T)); +} + + +static void tab_FPrintNodesCgFormat(FILE* File, TABLEAU T) +/************************************************************** + INPUT: A file handle, a tableau + RETURNS: Nothing + EFFECTS: Prints egde information of <T> in xvcg graph format + to <File>. +***************************************************************/ +{ + if (tab_IsEmpty(T)) + return; + + fputs("\nnode: {\n\nlabel: ", File); + tab_FPrintNodeLabel(File, T); + putc('\n', File); /* end label section */ + + fprintf(File, "title: \"%d\"\n", T->Label); + fputs(" }\n", File); + + /* recursion */ + tab_FPrintNodesCgFormat(File, tab_LeftBranch(T)); + tab_FPrintNodesCgFormat(File, tab_RightBranch(T)); + +} + +static void tab_FPrintCgFormat(FILE* File, TABLEAU T) +/************************************************************** + INPUT: A file handle, a tableau + RETURNS: Nothing. + EFFECTS: Prints tableau as a graph in xvcg format to <File> +***************************************************************/ +{ + fputs("graph: \n{\ndisplay_edge_labels: yes\n", File); + + tab_FPrintNodesCgFormat(File, T); + tab_FPrintEdgesCgFormat(File, T); + fputs("}\n", File); +} + +/* unused */ +/*static*/ void tab_PrintCgFormat(TABLEAU T) +/************************************************************** + INPUT: A tableau. + RETURNS: Nothing. + EFFECTS: Print tableau in xvcg format to stdout +***************************************************************/ +{ + tab_FPrintCgFormat(stdout, T); +} + + +/**************************************************************/ +/* procedures for printing graph in da Vinci format */ +/**************************************************************/ + +static void tab_FPrintDaVinciEdge(FILE* File, int L1, int L2) +/************************************************************** + INPUT: A file handle, two numbers + RETURNS: Nothing + EFFECTS: Print an edge in daVinci format +***************************************************************/ +{ + fprintf(File, "l(\"%d->%d\"," ,L1,L2); + fputs("e(\"\",[],\n", File); + /* print child node as reference */ + fprintf(File, "r(\"%d\")))\n", L2); +} + + +static void tab_FPrintDaVinciFormatRec(FILE* File, TABLEAU T) +/************************************************************** + INPUT: A file handle, a tableau + RETURNS: Nothing + EFFECTS: Prints tableau to <File> in daVinci format +***************************************************************/ +{ + /* print node label */ + fprintf(File, "l(\"%d\",", T->Label); + /* print node attributes */ + fputs("n(\"\", [a(\"OBJECT\",", File); + tab_FPrintNodeLabel(File, T); + fputs(")],\n", File); + + /* print egde list */ + putc('[', File); + if (!tab_LeftBranchIsEmpty(T)) + tab_FPrintDaVinciEdge(File, T->Label, tab_LeftBranch(T)->Label); + + if (!tab_RightBranchIsEmpty(T)) { + if (!tab_LeftBranchIsEmpty(T)) + putc(',', File); + tab_FPrintDaVinciEdge(File, T->Label, tab_RightBranch(T)->Label); + } + fputs("]))", File); /* this ends the node description */ + + if (!tab_LeftBranchIsEmpty(T)) { + putc(',', File); + tab_FPrintDaVinciFormatRec(File, tab_LeftBranch(T)); + } + if (!tab_RightBranchIsEmpty(T)) { + putc(',', File); + tab_FPrintDaVinciFormatRec(File, tab_RightBranch(T)); + } +} + + +static void tab_FPrintDaVinciFormat(FILE* File, TABLEAU T) +/************************************************************** + INPUT: A file handle <File>, a tableau + RETURNS: Nothing + EFFECTS: Print tableau in daVinci format to <File> +***************************************************************/ +{ + fputs("[\n", File); + tab_FPrintDaVinciFormatRec(File,T); + fputs("]\n", File); +} + + +void tab_WriteTableau(TABLEAU T, const char* Filename, GRAPHFORMAT Format) +/************************************************************** + INPUT: A tableau, a filename + RETURNS: Nothing. +***************************************************************/ +{ + FILE* File; + + if (Format != DAVINCI && Format != XVCG) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\nError: unknown output format for tableau.\n"); + misc_FinishUserErrorReport(); + } + + File = misc_OpenFile(Filename, "w"); + + if (Format == DAVINCI) + tab_FPrintDaVinciFormat(File, T); + else + if (Format == XVCG) + tab_FPrintCgFormat(File, T); + + misc_CloseFile(File, Filename); +} diff --git a/test/spass/tableau.h b/test/spass/tableau.h new file mode 100644 index 0000000000000000000000000000000000000000..f04a82655790ec71be0f585e383d7f39e5473fea --- /dev/null +++ b/test/spass/tableau.h @@ -0,0 +1,292 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * TABLEAUS * */ +/* * * */ +/* * $Module: TABLEAU * */ +/* * * */ +/* * Copyright (C) 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _TABLEAU_ +#define _TABLEAU_ + + +#include "list.h" +#include "clause.h" + +typedef struct TABLEAU_HELP { + LIST Clauses; /* all clauses generated on the split level */ + CLAUSE SplitClause; /* this levels split clause */ + + CLAUSE LeftSplitClause; /* first clause generated by split */ + LIST RightSplitClauses; /* other clauses generated by split */ + + struct TABLEAU_HELP* LeftBranch; /* branch corresponding to first split clause */ + struct TABLEAU_HELP* RightBranch; /* branch corresponding to other split clauses */ + + int Label; +} TABLEAU_NODE, *TABLEAU; + + +typedef struct { + TABLEAU *Path; /* An array of tableaux */ + int Length; + int MaxLength; + +} TABPATH_NODE, *TABPATH; + +/* tableau output formats */ +typedef enum { DAVINCI, XVCG } GRAPHFORMAT; + + +TABPATH tab_PathCreate(int, TABLEAU); +void tab_PathDelete(TABPATH); +BOOL tab_PathContainsClause(TABPATH, CLAUSE); +void tab_AddClauseOnItsLevel(CLAUSE, TABPATH); +void tab_AddSplitAtCursor(TABPATH, BOOL); +BOOL tab_IsClosed(TABLEAU); +TABLEAU tab_PruneClosedBranches(TABLEAU, LIST*); +int tab_Depth(TABLEAU); +void tab_SetSplitLevels(TABLEAU T); +TABLEAU tab_RemoveIncompleteSplits(TABLEAU, LIST*); +void tab_PathDelete(TABPATH); +void tab_Delete(TABLEAU); +void tab_ToClauseList(TABLEAU, LIST*); +void tab_GetEarliestEmptyClauses(TABLEAU, LIST*); +void tab_WriteTableau(TABLEAU, const char*, GRAPHFORMAT); +void tab_CheckEmpties(TABLEAU); +void tab_GetAllEmptyClauses(TABLEAU, LIST*); +void tab_LabelNodes(TABLEAU); + +/* inline functions for tableau paths */ + +static __inline__ int tab_PathLength(TABPATH TabPath) +{ + return TabPath->Length; +} + +static __inline__ TABLEAU tab_PathNthNode(TABPATH TabPath, int n) +{ +#ifdef CHECK + if (n > TabPath->MaxLength) { + misc_StartErrorReport(); + misc_ErrorReport("\n In tab_PathNthNode:"); + misc_ErrorReport(" Path length is %d,", tab_PathLength(TabPath)); + misc_ErrorReport("\nnode %d was requested.\n", n); + misc_FinishErrorReport(); + } +#endif + + return TabPath->Path[n]; +} + +static __inline__ TABPATH tab_PathPush(TABLEAU Tab, TABPATH TabPath) +{ + TabPath->Length++; + TabPath->Path[TabPath->Length] = Tab; + +#ifdef CHECK + if (TabPath->Length > TabPath->MaxLength) { + misc_StartErrorReport(); + misc_ErrorReport("\n In tab_PathPush: Maximum path length %d exceeded\n", + TabPath->MaxLength); + misc_FinishErrorReport(); + } +#endif + + return TabPath; +} + +static __inline__ TABLEAU tab_EmptyTableau(void) +{ + return (TABLEAU)NULL; +} + +static __inline__ TABPATH tab_PathPop(TABPATH TabPath) +{ +#ifdef CHECK + if (TabPath->Length <= 0) { + misc_StartErrorReport(); + misc_ErrorReport("\n In tab_PathPop: Popping from empty path.\n"); + misc_FinishErrorReport(); + } +#endif + + TabPath->Path[TabPath->Length--] = tab_EmptyTableau(); + + return TabPath; +} + +static __inline__ BOOL tab_PathEmpty(TABPATH P) +{ + return (tab_PathLength(P) == 0); +} + +static __inline__ TABLEAU tab_CreateNode(void) +{ + TABLEAU Node; + + Node = (TABLEAU)memory_Malloc(sizeof(TABLEAU_NODE)); + Node->RightBranch = (TABLEAU)NULL; + Node->LeftBranch = (TABLEAU)NULL; + Node->SplitClause = (CLAUSE)NULL; + Node->LeftSplitClause = (CLAUSE)NULL; + Node->RightSplitClauses = list_Nil(); + + Node->Clauses = list_Nil(); + +#ifdef USE_LABEL + Node->Label = 0; +#endif + + return Node; +} + +static __inline__ TABPATH tab_PathPrefix(int Level, TABPATH TabPath) +{ + TabPath->Length = Level; + return TabPath; +} + +static __inline__ TABLEAU tab_PathTop(TABPATH Path) +{ + return tab_PathNthNode(Path, tab_PathLength(Path)); +} + + +static __inline__ BOOL tab_IsEmpty(TABLEAU Tab) +{ + return (Tab == tab_EmptyTableau()); +} + +static __inline__ TABLEAU tab_RightBranch(TABLEAU Tab) +{ + return Tab->RightBranch; +} + +static __inline__ TABLEAU tab_LeftBranch(TABLEAU Tab) +{ + return Tab->LeftBranch; +} + +static __inline__ void tab_SetRightBranch(TABLEAU Tab, TABLEAU SubTab) +{ + Tab->RightBranch = SubTab; +} + +static __inline__ void tab_SetLeftBranch(TABLEAU Tab, TABLEAU SubTab) +{ + Tab->LeftBranch = SubTab; +} + +static __inline__ BOOL tab_RightBranchIsEmpty(TABLEAU Tab) +{ + return (Tab->RightBranch == tab_EmptyTableau()); +} + +static __inline__ BOOL tab_LeftBranchIsEmpty(TABLEAU Tab) +{ + return (Tab->LeftBranch == tab_EmptyTableau()); +} + +static __inline__ CLAUSE tab_SplitClause(TABLEAU Tab) +{ + return Tab->SplitClause; +} + +static __inline__ void tab_SetSplitClause(TABLEAU Tab, CLAUSE C) +{ + Tab->SplitClause = C; +} + +static __inline__ BOOL tab_HasSplit(TABLEAU T) +{ + return (tab_SplitClause(T) != clause_Null()); +} + +static __inline__ void tab_AddClause(CLAUSE C,TABLEAU T) +{ + T->Clauses = list_Cons(C,T->Clauses); +} + +static __inline__ LIST tab_Clauses(TABLEAU T) +{ + return T->Clauses; +} + +static __inline__ void tab_SetClauses(TABLEAU T, LIST Clauses) +{ + T->Clauses = Clauses; +} + +static __inline__ CLAUSE tab_LeftSplitClause(TABLEAU T) +{ + return T->LeftSplitClause; +} + +static __inline__ void tab_SetLeftSplitClause(TABLEAU T, CLAUSE C) +{ + T->LeftSplitClause = C; +} + + +static __inline__ LIST tab_RightSplitClauses(TABLEAU T) +{ + return T->RightSplitClauses; +} + + +static __inline__ void tab_SetRightSplitClauses(TABLEAU T, LIST L) +{ + T->RightSplitClauses = L; +} + +static __inline__ void tab_AddRightSplitClause(TABLEAU T, CLAUSE C) +{ + T->RightSplitClauses = list_Cons(C, T->RightSplitClauses); +} + +static __inline__ BOOL tab_IsLeaf(TABLEAU T) +{ + return (tab_RightBranchIsEmpty(T) && tab_LeftBranchIsEmpty(T)); +} + +#endif diff --git a/test/spass/term.c b/test/spass/term.c new file mode 100644 index 0000000000000000000000000000000000000000..2bc38e4d987bbc25b28a127339b571f6b14f93c8 --- /dev/null +++ b/test/spass/term.c @@ -0,0 +1,2551 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * TERMS * */ +/* * * */ +/* * $Module: TERM * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + + +#include "term.h" + +/**************************************************************/ +/* Global variables */ +/**************************************************************/ + +NAT term_MARK; +POINTER term_BIND[symbol__MAXVARIABLES][2]; +#ifdef CHECK +BOOL term_BINDPHASE; +#endif + +NAT term_STAMP; +BOOL term_STAMPBLOCKED; +static BOOL term_STAMPOVERFLOW[term_MAXSTAMPUSERS]; +static NAT term_STAMPUSERS; + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * TERM CREATION FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +void term_Init(void) +/********************************************************** + INPUT: None. + RETURNS: None. + CAUTION: The term module is initialized. +***********************************************************/ +{ + int i; + + term_MARK = 1; + + term_STAMP = 0; + term_STAMPBLOCKED = FALSE; + for (i = 0; i < term_MAXSTAMPUSERS; i++) + term_STAMPOVERFLOW[i] = FALSE; + term_STAMPUSERS = 0; +#ifdef CHECK + term_BINDPHASE = FALSE; +#endif +} + + +TERM term_Create(SYMBOL Symbol, LIST List) +/********************************************************** + INPUT: A symbol and a list of arguments. + RETURNS: A term consisting of the top symbol 'Symbol' and + the arguments stored in 'List'. + CAUTION: None. +********************************************************/ +{ + TERM Result; + +#ifdef CHECK + if (!symbol_IsSymbol(Symbol) || !term_IsTermList(List)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_Create: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Result = (TERM)memory_Malloc(sizeof(TERM_NODE)); + Result->symbol = Symbol; + Result->args = List; + Result->super.termlist = list_Nil(); + Result->stamp = 0; + Result->size = 0; + return Result; +} + +TERM term_CreateAddFather(SYMBOL Symbol, LIST List) +/********************************************************** + INPUT: A symbol and a list of arguments. + RETURNS: A term consisting of the top symbol 'Symbol' and + the arguments stored in 'List'. + In contrast to term_Create the superterm members are set for the arguments. + CAUTION: None. +********************************************************/ +{ + TERM Result; + LIST l; + Result = term_Create(Symbol, List); + for (l=term_ArgumentList(Result); !list_Empty(l); l = list_Cdr(l)) + term_RplacSuperterm((TERM) list_Car(l), Result); + return Result; +} + +TERM term_CreateStandardVariable(void) +/********************************************************** + RETURNS: Returns a term with a new variable as top symbol. +***********************************************************/ +{ + return term_Create(symbol_CreateStandardVariable(), list_Nil()); +} + + +void term_Delete(TERM Term) +/********************************************************** + INPUT: A term. + SUMMARY: Deletes the term and frees the storage. + CAUTION: The arguments of Term are also deleted. +********************************************************/ +{ + if (term_IsComplex(Term)) { + LIST Scan; + for (Scan = term_ArgumentList(Term); + list_Exist(Scan); + Scan = list_Cdr(Scan)) + term_Delete(list_Car(Scan)); + list_Delete(term_ArgumentList(Term)); + } + term_Free(Term); +} + + +void term_DeleteIterative(TERM Term) +/********************************************************** + INPUT: A term. + SUMMARY: Deletes the term and frees the storage. + CAUTION: The arguments of Term are also deleted. +********************************************************/ +{ + if (term_IsComplex(Term)) { + LIST Stack, Aux; + Stack = list_StackBottom(); + do { + if (term_IsComplex(Term)) + Stack = list_Push(term_ArgumentList(Term),Stack); + term_Free(Term); + while (!list_StackEmpty(Stack) && list_Empty(list_Top(Stack))) + Stack = list_Pop(Stack); + if (!list_StackEmpty(Stack)) { + Aux = list_Top(Stack); + Term = (TERM)list_Car(Aux); + list_RplacTop(Stack, list_Cdr(Aux)); + list_Free(Aux); + } + } while (!list_StackEmpty(Stack)); + } + else + term_Free(Term); +} + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * PRIMITIVE TERM FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +BOOL term_Equal(TERM Term1, TERM Term2) +/********************************************************* + INPUT: Two terms. + RETURNS: The boolean value TRUE if the terms are equal. + CAUTION: EQUAL FUNCTION- OR PREDICATE SYMBOLS SHARE THE + SAME ARITY. THIS IS NOT VALID FOR JUNCTORS! +**********************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(Term1) || !term_IsTerm(Term2)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_Equal: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + /* if (term_IsIndexVariable(Term1)) + puts("\nterm_Equal: Left index variable."); + else if (term_IsIndexVariable(Term2)) + puts("\nterm_Equal: Right index variable."); + + fflush(stdout); */ + + if (Term1 == Term2) /* pointers are equal */ + return TRUE; + else if (!term_EqualTopSymbols(Term1, Term2)) + return FALSE; + else if (term_ArgumentList(Term1)) { + LIST Scan1, Scan2; + for (Scan1=term_ArgumentList(Term1), Scan2=term_ArgumentList(Term2); + list_Exist(Scan1) && list_Exist(Scan2); + Scan1=list_Cdr(Scan1), Scan2=list_Cdr(Scan2)) + if (!term_Equal(list_Car(Scan1),list_Car(Scan2))) + return FALSE; + return (list_Empty(Scan1) ? list_Empty(Scan2) : FALSE); + } else + return TRUE; +} + + +BOOL term_EqualIterative(TERM Term1, TERM Term2) +/********************************************************* + INPUT: Two terms. + RETURNS: The boolean value TRUE if the terms are equal. + CAUTION: Notice that there may be symbols with arbitrary arity +*******************************************************/ +{ + LIST Stack1,Stack2; + +#ifdef CHECK + if (!term_IsTerm(Term1) || !term_IsTerm(Term2)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_EqualIterative: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Stack1 = Stack2 = list_StackBottom(); + do { + if (term_EqualTopSymbols(Term1,Term2) && + term_IsComplex(Term1) && term_IsComplex(Term2)) { + Stack1 = list_Push(term_ArgumentList(Term1),Stack1); + Stack2 = list_Push(term_ArgumentList(Term2),Stack2); + } + if (!term_EqualTopSymbols(Term1,Term2) || + term_IsComplex(Term1) != term_IsComplex(Term2)) { + Stack1 = list_StackFree(Stack1); + Stack2 = list_StackFree(Stack2); + return FALSE; + } + while (!list_StackEmpty(Stack1) && list_Empty(list_Top(Stack1))) + if (!list_StackEmpty(Stack2) && list_Empty(list_Top(Stack2))) { + Stack1 = list_Pop(Stack1); + Stack2 = list_Pop(Stack2); + } + else { + Stack1 = list_StackFree(Stack1); + Stack2 = list_StackFree(Stack2); + return FALSE; + } + if (!list_StackEmpty(Stack1)) { + if (!list_Empty(list_Top(Stack2))) { + Term1 = (TERM)list_Car(list_Top(Stack1)); + list_RplacTop(Stack1, list_Cdr(list_Top(Stack1))); + Term2 = (TERM)list_Car(list_Top(Stack2)); + list_RplacTop(Stack2, list_Cdr(list_Top(Stack2))); + } + else { + Stack1 = list_StackFree(Stack1); + Stack2 = list_StackFree(Stack2); + return FALSE; + } + } + } while (!list_StackEmpty(Stack1)); + return TRUE; +} + + +BOOL term_VariableEqual(TERM Variable1, TERM Variable2) +/********************************************************* + INPUT: Two Variables. + RETURNS: The boolean value TRUE, if the variables are + equal. +**********************************************************/ +{ + return term_EqualTopSymbols(Variable1, Variable2); +} + + +BOOL term_IsGround(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: A boolean value which is TRUE, if 'Term' is a + ground term, i.e. does not contain variables. +********************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_IsGround: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (term_IsComplex(Term)) { + LIST Stack; + Stack = list_StackBottom(); + do { + if (term_IsComplex(Term)) + Stack = list_Push(term_ArgumentList(Term),Stack); + else + if (term_IsVariable(Term)) { + Stack = list_StackFree(Stack); + return FALSE; + } + while (!list_StackEmpty(Stack) && list_Empty(list_Top(Stack))) + Stack = list_Pop(Stack); + if (!list_StackEmpty(Stack)) { + Term = (TERM)list_Car(list_Top(Stack)); + list_RplacTop(Stack, list_Cdr(list_Top(Stack))); + } + } while (!list_StackEmpty(Stack)); + return TRUE; + } else + return !term_IsVariable(Term); +} + + +BOOL term_IsTerm(TERM Term) +/********************************************************* + INPUT: A term. + RETURNS: TRUE, if 'Term' is not NULL + and has a symbol as its top symbol. +**********************************************************/ +{ + return (Term != (TERM)NULL && symbol_IsSymbol(term_TopSymbol(Term))); +} + + +BOOL term_IsTermList(LIST TermList) +/********************************************************* + INPUT: A term. + RETURNS: TRUE iff <TermList> is a list of terms. +*******************************************************/ +{ + for ( ; !list_Empty(TermList); TermList=list_Cdr(TermList)) + if (!(term_IsTerm((TERM)list_Car(TermList)))) + return FALSE; + + return TRUE; +} + + +BOOL term_AllArgsAreVar(TERM Term) +/********************************************************* + INPUT: A term. + RETURNS: The boolean value TRUE, if all arguments of the + term are variables. +*******************************************************/ +{ + LIST Scan; + for (Scan = term_ArgumentList(Term); + !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (!term_IsVariable(list_Car(Scan))) + return FALSE; + return TRUE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * LOW LEVEL FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +TERM term_Copy(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: A copy of 'Term' where the stamp field is copied, too. + SUMMARY: Copies "Term" and returns a pointer to the copy. +*********************************************************/ +{ + TERM Result; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_Copy: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (term_IsComplex(Term)) { + LIST Scan, ArgumentList; + for (Scan = ArgumentList = list_Copy(term_ArgumentList(Term)); + list_Exist(Scan); + Scan = list_Cdr(Scan)) + list_Rplaca(Scan, term_Copy(list_Car(Scan))); + Result = term_Create(term_TopSymbol(Term), ArgumentList); + } else + Result = term_Create(term_TopSymbol(Term), list_Nil()); + + Result->stamp = Term->stamp; + Result->size = Term->size; + + return Result; +} + + +TERM term_CopyIterative(TERM Term) +/********************************************************** + INPUT: A term. + RETURNS: A copy of <Term>. + SUMMARY: Copies <Term> and returns a pointer to the copy. +*********************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_CopyIterative: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (term_IsComplex(Term)) { + LIST TopStack, ArgumentStack, ActStack; + TopStack = list_Push((POINTER)term_TopSymbol(Term), + list_StackBottom()); + ArgumentStack = list_Push(list_Copy(term_ArgumentList(Term)), + list_StackBottom()); + ActStack = list_Push(list_Top(ArgumentStack), + list_StackBottom()); + + while (!list_StackEmpty(TopStack)) { + if (list_Empty(list_Top(ActStack))) { + Term = term_Create((SYMBOL)list_Top(TopStack), + (LIST)list_Top(ArgumentStack)); + TopStack = list_Pop(TopStack); + ArgumentStack = list_Pop(ArgumentStack); + ActStack = list_Pop(ActStack); + if (!list_StackEmpty(TopStack)) { + list_Rplaca(list_Top(ActStack), Term); + list_RplacTop(ActStack, list_Cdr(list_Top(ActStack))); + } + } + else { + Term = (TERM)list_Car(list_Top(ActStack)); + if (term_IsComplex(Term)) { + TopStack = list_Push((POINTER)term_TopSymbol(Term), TopStack); + ArgumentStack = list_Push(list_Copy(term_ArgumentList(Term)), + ArgumentStack); + ActStack = list_Push(list_Top(ArgumentStack), ActStack); + } + else { + list_Rplaca(list_Top(ActStack), + term_Create(term_TopSymbol(Term), list_Nil())); + list_RplacTop(ActStack, list_Cdr(list_Top(ActStack))); + } + } + } + return Term; + } + else + return term_Create(term_TopSymbol(Term), list_Nil()); +} + + +TERM term_CopyWithEmptyArgListNode(TERM Term, LIST ArgListNode, + LIST* ListNodeCopyPt) +/********************************************************** + INPUT: A term and a pointer to an argument list node of + this term. + RETURNS: A copy of 'Term' with a NULL as list_Car(ListNodeCopy). + SUMMARY: Copies "Term" and returns a pointer to the copy. +*********************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_CopyWithEmptyArgListNode: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (term_IsComplex(Term)) { + LIST Scan, ArgumentList, HelpScan; + TERM Result; + + HelpScan = term_ArgumentList(Term); + ArgumentList = list_Copy(HelpScan); + + for (Scan = ArgumentList; + list_Exist(Scan); + Scan = list_Cdr(Scan),HelpScan = list_Cdr(HelpScan)) + if (HelpScan != ArgListNode) + list_Rplaca(Scan, + term_CopyWithEmptyArgListNode(list_Car(Scan), + ArgListNode, + ListNodeCopyPt)); + else{ + list_Rplaca(Scan, (TERM)NULL); + *ListNodeCopyPt = Scan; + } + + Result = (TERM)memory_Malloc(sizeof(TERM_NODE)); + Result->symbol = term_TopSymbol(Term); + Result->args = ArgumentList; + Result->super.termlist = list_Nil(); + + return Result; + + } else + return term_Create(term_TopSymbol(Term), list_Nil()); +} + + +void term_PrintWithEmptyArgListNode(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: none. + SUMMARY: Prints any term to stdout, especially terms with empty + argument list nodes. + CAUTION: Uses the other term_Output functions. +*************************************************************/ +{ + if (Term == (TERM)NULL) + fputs("(NULL)", stdout); + + else if (term_IsComplex(Term)) { + putchar('('); + symbol_Print(term_TopSymbol(Term)); + putchar(' '); + list_Apply((void (*)(POINTER)) term_PrintWithEmptyArgListNode, + term_ArgumentList(Term)); + putchar(')'); + + } else if (term_IsVariable(Term)) { + + symbol_Print(term_TopSymbol(Term)); + + } else { + + /* term_IsConstant(Term) */ + putchar('('); + symbol_Print(term_TopSymbol(Term)); + putchar(')'); + } +} + + +BOOL term_ReplaceSubtermBy(TERM Atom, TERM TermS, TERM TermT) +/************************************************************** + INPUT: Three terms. + RETURNS: None. + EFFECT: Replaces all occurrences of TermS in Atom by TermT. + Top level is NOT considered! +*************************************************************/ +{ + LIST ArgListNode; + BOOL Replaced; + int B_Stack; + +#ifdef CHECK + if (!term_IsTerm(Atom) || !term_IsTerm(TermS) || + !term_IsTerm(TermT) || term_Equal(Atom, TermS)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_ReplaceSubtermBy: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + /*fputs("\nWe look for: ",stdout);term_Print(TermS); + fputs("\nin: ",stdout);term_Print(Atom); + */ + + Replaced = FALSE; + TermS = term_Copy(TermS); + + if (!term_Equal(Atom, TermS) && !list_Empty(term_ArgumentList(Atom))) { + + B_Stack = stack_Bottom(); + stack_Push(term_ArgumentList(Atom)); + + while (!stack_Empty(B_Stack)) { + ArgListNode = stack_Top(); + Atom = (TERM)list_Car(ArgListNode); + stack_RplacTop(list_Cdr(ArgListNode)); + + if (term_Equal(Atom, TermS)) { + Replaced = TRUE; + list_Rplaca(ArgListNode, term_Copy(TermT)); + term_Delete(Atom); + } + else + if (term_IsComplex(Atom)) + stack_Push(term_ArgumentList(Atom)); + + while (!stack_Empty(B_Stack) && list_Empty(stack_Top())) + stack_Pop(); + } + } + term_Delete(TermS); + return Replaced; +} + + +void term_ReplaceVariable(TERM Term, SYMBOL Symbol, TERM Repl) +/************************************************************** + INPUT: A term, a variable symbol and a replacement term. + RETURNS: void + EFFECT: All variables with <Symbol> in <Term> are replaced + with copies of <Repl> + CAUTION: Destructive +***************************************************************/ +{ + LIST Scan; + +#ifdef CHECK + if (!term_IsTerm(Term) || !term_IsTerm(Repl) || !symbol_IsVariable(Symbol)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_ReplaceVariable: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (symbol_Equal(term_TopSymbol(Term), Symbol)) { + term_RplacTop(Term,term_TopSymbol(Repl)); + term_RplacArgumentList(Term,term_CopyTermList(term_ArgumentList(Repl))); + } + else + for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) + term_ReplaceVariable(list_Car(Scan),Symbol,Repl); +} + +void term_ExchangeVariable(TERM Term, SYMBOL Old, SYMBOL New) +/************************************************************** + INPUT: A term, and two variable symbols. + RETURNS: void + EFFECT: All variables <Old> in <Term> are replaced with <New> + CAUTION: Destructive +***************************************************************/ +{ + LIST Scan; + +#ifdef CHECK + if (!term_IsTerm(Term) || !symbol_IsVariable(Old) || !symbol_IsVariable(New)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_ExchangeVariable: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (symbol_Equal(term_TopSymbol(Term), Old)) + term_RplacTop(Term,New); + else + for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) + term_ExchangeVariable(list_Car(Scan),Old,New); +} + + +BOOL term_SubstituteVariable(SYMBOL Symbol, TERM Repl, TERM* Term) +/****************************************************** + INPUT: A Symbol which has to be found in the Term, + a term which is the replacement for the + 'Symbol', and a term in which the substitu- + tions take place. + RETURNS: A boolean value which is TRUE, if any sub- + stitutions were made. + SUMMARY: term_Substitute works recursively and repl. + every occurence of 'Symbol' in 'Term' by + 'Repl'. + CAUTION: FUNCTION IS DESTRUCTIVE ON 'Term'. REPLACE- + MENT IS COPIED EACH TIME A SUB. TAKES PLACE +*******************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(*Term) || !term_IsTerm(Repl) || !symbol_IsSymbol(Symbol)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_SubstituteVariable: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (symbol_Equal(term_TopSymbol(*Term), Symbol)) { + + TERM New; + New = term_Copy(Repl); + (*Term)->symbol = Repl->symbol; + (*Term)->args = term_ArgumentList(New); + + /* Free Top-Node of New, as the symbol has been written */ + /* into the node pointed to by `Term'. */ + memory_Free(New, sizeof(TERM_NODE)); + return TRUE; + + } else { + + BOOL Result; + LIST List; + + Result = FALSE; + for (List = term_ArgumentList(*Term); + list_Exist(List); List = list_Cdr(List)) + if (term_SubstituteVariable(Symbol, Repl, (TERM*) &(List->car))) + Result = TRUE; + return Result; + } +} + + +static int term_CompareByConstants(TERM Left, TERM Right) +/************************************************************** + INPUT: Two terms. + RETURNS: 1 if left term < right term + 0 if left term = right term + -1 if left term > right term + EFFECT: The terms are compared by their multisets of + constants. The frequency of elements in the + multisets is a multiset itself. The frequencies + are sorted and the resulting sorted multisets + compared. +***************************************************************/ +{ + LIST lconsts, rconsts; + int result; + + /* Get multiset of constants. */ + + lconsts = term_ListOfConstants(Left); + rconsts = term_ListOfConstants(Right); + + result = list_CompareMultisetsByElementDistribution(lconsts, rconsts); + + list_Delete(lconsts); + list_Delete(rconsts); + + return result; +} + +static int term_CompareByFunctions(TERM Left, TERM Right) +/************************************************************** + INPUT: Two terms. + RETURNS: 1 if left term < right term + 0 if left term = right term + -1 if left term > right term + EFFECT: The terms are compared by their multisets of + functions. The frequency of elements in the + multisets is a multiset itself. The frequencies + are sorted and the resulting sorted multisets + compared. +***************************************************************/ +{ + LIST lfuns, rfuns; + int result; + + /* Get multiset of functions. */ + + lfuns = term_ListOfFunctions(Left); + rfuns = term_ListOfFunctions(Right); + + result = list_CompareMultisetsByElementDistribution(lfuns, rfuns); + + list_Delete(lfuns); + list_Delete(rfuns); + + return result; +} + +static int term_CompareByVariables(TERM Left, TERM Right) +/************************************************************** + INPUT: Two terms. + RETURNS: 1 if left term < right term + 0 if left term = right term + -1 if left term > right term + EFFECT: The terms are compared by their multisets of + variables. The frequency of elements in the + multisets is a multiset itself. The frequencies + are sorted and the resulting sorted multisets + compared. +***************************************************************/ +{ + LIST lvars, rvars; + int result; + + /* Get multiset of variables. */ + + lvars = term_ListOfVariables(Left); + rvars = term_ListOfVariables(Right); + + result = list_CompareMultisetsByElementDistribution(lvars, rvars); + + list_Delete(lvars); + list_Delete(rvars); + + return result; +} + +LIST term_ListOfConstants(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: A list of constants. + EFFECT: Creates a list of constants used in a term. If no + constants are used in a term, it returns an empty + list. +***************************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_ListOfConstants: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (symbol_IsConstant(term_TopSymbol(Term))) + return list_List((POINTER) term_TopSymbol(Term)); + else { + LIST result; + LIST scan; + + result = list_Nil(); + for (scan = term_ArgumentList(Term); + !list_Empty(scan); + scan = list_Cdr(scan)) { + /* Append to the smaller list for efficiency. + A subterm's list of constants will usually + be smaller than the intermediate result. + */ + result = list_Nconc(term_ListOfConstants((TERM) list_Car(scan)), result); + } + + return result; + } +} + +LIST term_ListOfFunctions(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: A list of functions. + EFFECT: Creates a list of functions used in a term. If no + functions are used in a term, it returns an empty + list. +***************************************************************/ +{ + LIST result; + LIST scan; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_ListOfFunctions: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + result = list_Nil(); + + /* If the term starts with a function, add the function symbol + to the result. + */ + if (symbol_IsFunction(term_TopSymbol(Term))) { + result = list_Nconc(result, list_List((POINTER) term_TopSymbol(Term))); + } + + /* A function can utilize other functions, so + traverse the argument list for further + functions. + */ + for (scan = term_ArgumentList(Term); + !list_Empty(scan); + scan = list_Cdr(scan)) { + /* Append to the smaller list for efficiency. + A subterm's list of functions will usually + be smaller than the intermediate result. + */ + result = list_Nconc(term_ListOfFunctions((TERM) list_Car(scan)), result); + } + + return result; +} + +void term_CountSymbols(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: None. + EFFECT: Counts the non-variable symbols in the term, and + increases their counts accordingly. +***************************************************************/ +{ + LIST scan; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_CountSymbols: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + /* If the term starts with a function, increase the count for + the function symbol. + */ + if (symbol_IsFunction(term_TopSymbol(Term))) { + SYMBOL S; + + S = term_TopSymbol(Term); + symbol_SetCount(S, symbol_GetCount(S) + 1); + } + + /* A function can utilize other functions, so + traverse the argument list for further + function symbols. + */ + for (scan = term_ArgumentList(Term); + !list_Empty(scan); + scan = list_Cdr(scan)) { + term_CountSymbols((TERM) list_Car(scan)); + } +} + +static int term_CompareByArity(TERM Left, TERM Right) +/************************************************************** + INPUT: Two terms. + RETURNS: 1 if left term < right term + 0 if left term = right term + -1 if left term > right term + EFFECT: Terms are compared top down, left to right with + respect to the arity of their signature symbols, + where variables in addition are defined to be smaller + than constants. +***************************************************************/ +{ + NAT lval, rval; + SYMBOL lsymb, rsymb; + LIST largs, rargs; + int result; + + result = 0; + + /* Compare top symbols first */ + lsymb = term_TopSymbol(Left); + rsymb = term_TopSymbol(Right); + + if (symbol_IsVariable(lsymb)) { + if (symbol_IsVariable(rsymb)) + return 0; + else + return 1; + } + else + if (symbol_IsVariable(rsymb)) + return -1; + + lval = symbol_Arity(lsymb); + rval = symbol_Arity(rsymb); + + if (lval > rval) + return -1; + + if (lval < rval) + return 1; + + /* If top symbol arities are equal, compare subterms left to right */ + largs = term_ArgumentList(Left); + rargs = term_ArgumentList(Right); + + while(!list_Empty(largs)) { + result = term_CompareByArity(list_Car(largs), list_Car(rargs)); + if (result != 0) + break; + + largs = list_Cdr(largs); + rargs = list_Cdr(rargs); + } + + return result; +} + +int term_CompareBySymbolOccurences(TERM Left, TERM Right) +/************************************************************** + INPUT: Two terms. + RETURNS: 1 if left term < right term + 0 if left term = right term + -1 if left term > right term + EFFECT: Terms are compared top down, left to right with + respect to the frequency of their symbols. +***************************************************************/ +{ + unsigned long lval, rval; + SYMBOL lsymb, rsymb; + LIST largs, rargs; + int result; + + result = 0; + + /* Compare top symbols first */ + lsymb = term_TopSymbol(Left); + rsymb = term_TopSymbol(Right); + + if (symbol_IsFunction(lsymb)) { + if (symbol_IsFunction(rsymb)) { + + lval = symbol_GetCount(lsymb); + rval = symbol_GetCount(rsymb); + + if (lval > rval) + return -1; + + if (lval < rval) + return 1; + + /* If top symbol arities are equal, compare subterms left to right */ + largs = term_ArgumentList(Left); + rargs = term_ArgumentList(Right); + + while(!list_Empty(largs)) { + result = term_CompareBySymbolOccurences(list_Car(largs), + list_Car(rargs)); + if (result != 0) + break; + + largs = list_Cdr(largs); + rargs = list_Cdr(rargs); + } + } + else { + return -1; + } + } + else { + if (symbol_IsFunction(rsymb)) { + return 1; + } + } + + return result; +} + +int term_CompareAbstract(TERM Left, TERM Right) +/************************************************************** + INPUT: Two terms. + RETURNS: 1 if left term < right term + 0 if left term = right term + -1 if left term > right term + EFFECT: Compares two terms using an internal array of term + comparison functions. As soon as a term is found to + compare greater than the other, the result of the + comparison is returned. If all term comparison + functions yield an "equal", then 0 is returned. +***************************************************************/ +{ + int result; + int i; + int functions; + + typedef int (*TERM_COMPARE_FUNCTION) (TERM, TERM); + + static const TERM_COMPARE_FUNCTION term_compare_functions [] = { + term_CompareByArity, + term_CompareBySymbolOccurences, + term_CompareByConstants, + term_CompareByVariables, + term_CompareByFunctions + }; + +#ifdef CHECK + if (!(term_IsTerm(Left) && term_IsTerm(Right))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_CompareAbstract: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + result = 0; + functions = sizeof(term_compare_functions)/sizeof(TERM_COMPARE_FUNCTION); + + for (i = 0; i < functions; i++) { + result = term_compare_functions[i](Left, Right); + + if ( result != 0) { + return result; + } + } + + return result; +} + +BOOL term_CompareAbstractLEQ(TERM Left, TERM Right) +/************************************************************** + INPUT: Two terms. + RETURNS: TRUE if left term <= right term, FALSE otherwise. + EFFECT: Terms are compared top down, left to right with + respect to the arity of their signature symbols, + where variables in addition are defined to be smaller + than constants. +***************************************************************/ +{ + return (term_CompareAbstract(Left, Right) >= 0); +} + + +NAT term_ComputeSize(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: The number of symbols in the term. + EFFECT: None +***************************************************************/ +{ + NAT Weight; + LIST Scan; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_ComputeSize: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Weight = 1; + for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) + Weight += term_ComputeSize((TERM)list_Car(Scan)); + return Weight; +} + +NAT term_RootDistance(TERM Term) +/************************************************************** + INPUT: A term with establised father links. + RETURNS: The distance from <Term> to its root father term. + EFFECT: None +***************************************************************/ +{ + NAT Distance; + + Distance = 0; + + while (term_Superterm(Term) != (TERM)NULL) { + Distance++; + Term = term_Superterm(Term); + } + + return Distance; +} + +BOOL term_RootDistanceSmaller(TERM Term1, TERM Term2) +/************************************************************** + INPUT: Two terms with establised father links. + RETURNS: TRUE iff root distance of <Term1> is smaller than + root distance of <Term2> + EFFECT: None +***************************************************************/ +{ + return (term_RootDistance(Term1)<term_RootDistance(Term2)); +} + +void term_InstallSize(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: None + EFFECT: Sets for every subterm the size. +***************************************************************/ +{ + NAT Weight; + LIST Scan; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_InstallSize: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Weight = 1; + for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) { + term_InstallSize((TERM)list_Car(Scan)); + Weight += term_Size((TERM)list_Car(Scan)); + }; + term_SetSize(Term, Weight); +} + +NAT term_Depth(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: The depth of the term. + EFFECT: None +***************************************************************/ +{ + NAT Depth,Help; + LIST Scan; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_Depth: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Depth = 0; + for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) { + Help = term_Depth(list_Car(Scan)); + if (Help > Depth) + Depth = Help; + } + return (Depth+1); +} + +BOOL term_ContainsSymbol(TERM Term, SYMBOL Symbol) +/************************************************************** + INPUT: A term and a symbol. + RETURNS: TRUE, if the symbol occurs somewhere in the term, + FALSE otherwise. +***************************************************************/ +{ + int Stack; + +#ifdef CHECK + if (!term_IsTerm(Term) || !symbol_IsSymbol(Symbol)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_ContainsSymbol: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Stack = stack_Bottom(); + + do { + if (term_TopSymbol(Term) == Symbol) { + stack_SetBottom(Stack); /* Clean up the stack */ + return TRUE; + } + else + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + + if (!stack_Empty(Stack)) { + Term = list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); + + return FALSE; +} + +TERM term_FindSubterm(TERM Term, SYMBOL Symbol) +/************************************************************** + INPUT: A term and a symbol. + RETURNS: If the symbol occurs in the Term the subterm is returned. + NULL otherwise. +***************************************************************/ +{ + int stack; + +#ifdef CHECK + if (!term_IsTerm(Term) || !symbol_IsSymbol(Symbol)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_FindSubterm: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + stack = stack_Bottom(); + + do { + if (term_TopSymbol(Term) == Symbol) { + stack_SetBottom(stack); /* Clean up the stack */ + return Term; + } else if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + + while (!stack_Empty(stack) && list_Empty(stack_Top())) + stack_Pop(); + + if (!stack_Empty(stack)) { + Term = list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(stack)); + + return NULL; +} + +static int term_SharingList(TERM Term, LIST List) +/************************************************************** + INPUT: A term and a list cell. + RETURNS: The number of times <List> occurs in <Term> + EFFECT: None +***************************************************************/ +{ + LIST Scan; + int n; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_SharingList: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + n = 0; + + for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) { + if (Scan == List) + n++; + n += term_SharingList(list_Car(Scan), List); + } + + return n; +} + + +static int term_SharingTerm(TERM Term, TERM CompareTerm) +/************************************************************** + INPUT: A term and a compare term + RETURNS: The number of occurrences of <CompareTerm> in <Term> + EFFECT: None +***************************************************************/ +{ + LIST Scan; + int n; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_SharingTerm: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + n = 0; + + if (Term == CompareTerm) + n = 1; + + for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) + n += term_SharingTerm(list_Car(Scan),CompareTerm); + + return n; +} + + +BOOL term_Sharing(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: TRUE iff the term shares list cells or subterms. + EFFECT: None +***************************************************************/ +{ + LIST Scan; + int stack; + TERM ActTerm; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_Sharing: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + stack = stack_Bottom(); + stack_Push(Term); + + while (!stack_Empty(stack)) { + ActTerm = (TERM)stack_Top(); + stack_Pop(); + + if (term_SharingTerm(Term,ActTerm)>1) + return TRUE; + + if (term_IsComplex(Term)) { + for (Scan = term_ArgumentList(ActTerm); + !list_Empty(Scan); + Scan=list_Cdr(Scan)) + if (term_SharingList(Term, Scan) > 1) + return TRUE; + else + stack_Push(list_Car(Scan)); + } + } + + return FALSE; +} + + +void term_AddFatherLinks(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: void. + EFFECT: The super term links of Term are cleared and then all + its subterms are set. +***************************************************************/ +{ + LIST Scan; + TERM ActTerm; + + term_RplacSuperterm(Term,(TERM)NULL); + + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + ActTerm = (TERM)list_Car(Scan); + term_AddFatherLinks(ActTerm); + term_RplacSuperterm(ActTerm,Term); + } + +} + +BOOL term_FatherLinksEstablished(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: TRUE iff all father links in Term are established. + EFFECT: None. +***************************************************************/ +{ + LIST Scan; + + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (Term != term_Superterm(list_Car(Scan)) || !term_FatherLinksEstablished(list_Car(Scan))) + return FALSE; + + return TRUE; +} + +TERM term_TopLevelTerm(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: The top level father of the term. + EFFECT: The father links have to be established! +***************************************************************/ +{ + while (term_Superterm(Term)) + Term = term_Superterm(Term); + return Term; +} + + +BOOL term_HasPointerSubterm(TERM Term, TERM Subterm) +/************************************************************** + INPUT: Two terms. + RETURNS: TRUE, if <Term> has <Subterm> as a subterm. + CAUTION: Only term pointers are compared, term_Equal isn't used. +***************************************************************/ +{ + if (Term == Subterm) + return TRUE; + else { + LIST scan = term_ArgumentList(Term); + + while (!list_Empty(scan)) { + if (term_HasPointerSubterm((TERM) list_Car(scan), Subterm)) + return TRUE; + scan = list_Cdr(scan); + } + } + + return FALSE; +} + +BOOL term_HasSubterm(TERM Term, TERM Subterm) +/************************************************************** + INPUT: Two terms. + RETURNS: TRUE, if <Term> has <Subterm> as a subterm. + CAUTION: term_Equal is used. +***************************************************************/ +{ + if (term_Equal(Term,Subterm)) + return TRUE; + else { + LIST Scan; + Scan = term_ArgumentList(Term); + + while (!list_Empty(Scan)) { + if (term_HasSubterm((TERM) list_Car(Scan), Subterm)) + return TRUE; + Scan = list_Cdr(Scan); + } + } + + return FALSE; +} + +BOOL term_HasProperSuperterm(TERM Term, TERM Super) +/********************************************************** + INPUT : Two terms. + RETURNS : TRUE iff Super can be reached from Term by following + the superterm member of the TERM structure. + CAUTION : not reflexive +**********************************************************/ +{ + if (Term == Super) + return FALSE; + while (Term != (TERM) NULL) { + if (Term == Super) /* Pointer equality ! */ + return TRUE; + else + Term = term_Superterm(Term); + } + return FALSE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * TERM OUTPUT FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +void term_Print(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: none. + SUMMARY: Prints the term to stdout. + CAUTION: Uses the other term output functions. +***************************************************************/ +{ + if (term_IsComplex(Term)) { + putchar('('); + symbol_Print(term_TopSymbol(Term)); + putchar(' '); + term_TermListPrint(term_ArgumentList(Term)); + putchar(')'); + + } else if (term_IsVariable(Term)) { + + symbol_Print(term_TopSymbol(Term)); + + } else { + + /* term_IsConstant(Term) */ + putchar('('); + symbol_Print(term_TopSymbol(Term)); + putchar(')'); + } +} + +static void term_PrettyPrintIntern(TERM Term, int Depth) +/************************************************************** + INPUT: A term and a depth parameter for indentation. + RETURNS: none. + SUMMARY: Prints the term hopefully more pretty to stdout. +***************************************************************/ +{ + int i; + LIST scan; + + + for (i=0; i < Depth; i++) + fputs(" ", stdout); + if (symbol_IsJunctor(term_TopSymbol(Term))) { + if (term_IsComplex(Term)) { + symbol_Print(term_TopSymbol(Term)); + putchar('('); + fputs("\n", stdout); + for (scan=term_ArgumentList(Term); !list_Empty(scan); scan= list_Cdr(scan)) { + term_PrettyPrintIntern((TERM) list_Car(scan), Depth+1); + if (!list_Empty(list_Cdr(scan))) + fputs(",\n", stdout); + } + putchar(')'); + } + else { + if (term_IsVariable(Term)) { + symbol_Print(term_TopSymbol(Term)); + } + else { + putchar('('); + symbol_Print(term_TopSymbol(Term)); + putchar(')'); + } + } + } + else { + term_PrintPrefix(Term); + } +} + +void term_PrettyPrint(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: none. + SUMMARY: Prints the term hopefully more pretty to stdout. +***************************************************************/ +{ + term_PrettyPrintIntern(Term, 0); +} + + +void term_FPrint(FILE* File,TERM Term) +/************************************************************** + INPUT: A file and a term. + RETURNS: none. + SUMMARY: Prints the term to the file. + CAUTION: Uses the other term output functions. +***************************************************************/ +{ + if (term_IsComplex(Term)) { + putc('(', File); + symbol_FPrint(File,term_TopSymbol(Term)); + putc(' ', File); + term_TermListFPrint(File,term_ArgumentList(Term)); + putc(')', File); + + } else if (term_IsVariable(Term)) { + + symbol_FPrint(File,term_TopSymbol(Term)); + + } else { + + /* term_IsConstant(Term) */ + putc('(', File); + symbol_FPrint(File,term_TopSymbol(Term)); + putc(')', File); + } +} + + +void term_TermListPrint(LIST List) +/************************************************************** + INPUT: A list of terms. + RETURNS: None. +***************************************************************/ +{ + for (; !list_Empty(List); List=list_Cdr(List)) { + term_Print(list_Car(List)); fflush(stdout); + if (!list_Empty(list_Cdr(List))) + putchar(' '); + } +} + + +void term_TermListFPrint(FILE* File, LIST List) +/************************************************************** + INPUT: A list of terms. + RETURNS: None. +***************************************************************/ +{ + for (; !list_Empty(List); List=list_Cdr(List)) { + term_FPrint(File,list_Car(List)); + if (!list_Empty(list_Cdr(List))) + putc(' ', File); + } +} + + +void term_PrintPrefix(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: none. + SUMMARY: Prints the term in prefix notation to stdout. + CAUTION: Uses the other term output functions. +***************************************************************/ +{ + if (term_IsComplex(Term)) { + symbol_Print(term_TopSymbol(Term)); + putchar('('); + term_TermListPrintPrefix(term_ArgumentList(Term)); + putchar(')'); + + } else + symbol_Print(term_TopSymbol(Term)); +} + + +void term_FPrintPrefix(FILE* File, TERM Term) +/************************************************************** + INPUT: A file and a term. + RETURNS: none. + SUMMARY: Prints the term in prefix notation to the file. + CAUTION: Uses the other term output functions. +***************************************************************/ +{ + if (term_IsComplex(Term)) { + symbol_FPrint(File,term_TopSymbol(Term)); + putc('(', File); + term_TermListFPrintPrefix(File,term_ArgumentList(Term)); + putc(')', File); + + } else + symbol_FPrint(File,term_TopSymbol(Term)); +} + + +void term_TermListPrintPrefix(LIST List) +/************************************************************** + INPUT: A list of terms. + RETURNS: None. +***************************************************************/ +{ + for (; !list_Empty(List); List=list_Cdr(List)) { + term_PrintPrefix(list_Car(List)); + if (!list_Empty(list_Cdr(List))) + putchar(','); + } +} + + +void term_TermListFPrintPrefix(FILE* File, LIST List) +/************************************************************** + INPUT: A list of terms. + RETURNS: None. +***************************************************************/ +{ + for (; !list_Empty(List); List=list_Cdr(List)) { + term_FPrintPrefix(File,list_Car(List)); + if (!list_Empty(list_Cdr(List))) + putc(',', File); + } +} + + + +void term_FPrintOtterPrefix(FILE* File, TERM Term) +/************************************************************** + INPUT: A file and a term. + RETURNS: none. + SUMMARY: Prints the term in prefix notation to the file. + CAUTION: Uses the other term_Output functions. +***************************************************************/ +{ + if (term_IsComplex(Term)) { + symbol_FPrintOtter(File, term_TopSymbol(Term)); + putc('(', File); + term_TermListFPrintOtterPrefix(File, term_ArgumentList(Term)); + putc(')', File); + } else + symbol_FPrintOtter(File, term_TopSymbol(Term)); +} + + +void term_TermListFPrintOtterPrefix(FILE* File, LIST List) +/************************************************************** + INPUT: A list of terms. + RETURNS: None. +***************************************************************/ +{ + for (; !list_Empty(List); List=list_Cdr(List)) { + term_FPrintOtterPrefix(File,list_Car(List)); + if (!list_Empty(list_Cdr(List))) + putc(',', File); + } +} + + +void term_FPrintPosition(FILE* File, TERM TopTerm, TERM Subterm) +/************************************************************** + INPUT: An output file and two terms where <Subterm> is a subterm + of <TopTerm>. + RETURNS: Nothing. + SUMMARY: The position of <Subterm> relative to <TopTerm> is + printed to the output file. A simple top-down search + is done, so the superterm pointers are not needed. + Note that we compare terms with respect to pointers! + If <Subterm> isn't a subterm of <TopTerm> at all, + this causes an error message followed by a core dump. +***************************************************************/ +{ + NAT pos; + LIST Scan; + + if (TopTerm == Subterm) + return; + + for (Scan = term_ArgumentList(TopTerm), pos = 1; !list_Empty(Scan); + Scan = list_Cdr(Scan), pos++) { + if (term_HasPointerSubterm(list_Car(Scan), Subterm)) { + fprintf(File, "%u", pos); + if (Subterm != list_Car(Scan)) { + putc('.', File); + term_FPrintPosition(File, list_Car(Scan), Subterm); + } + return; + } + } + misc_StartErrorReport(); + misc_ErrorReport("\n In term_FPrintPosition: Term isn't subterm of the other one."); + misc_FinishErrorReport(); +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * HIGH LEVEL FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +NAT term_Bytes(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: The number of bytes occupied by the term. + EFFECT: None +***************************************************************/ +{ + NAT Bytes; + LIST Scan; + + Bytes = sizeof(TERM_NODE) + list_Bytes(term_ArgumentList(Term)); + for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) + Bytes += term_Bytes((TERM)list_Car(Scan)); + return Bytes; +} + + +LIST term_ListOfVariables(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: The list of variables occurring in the term. + Note that there may be many terms with same variable symbol. +***************************************************************/ +{ + LIST Stack, Variables; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_ListOfVariables: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Variables = list_Nil(); + Stack = list_StackBottom(); + do { + if (term_IsComplex(Term)) + Stack = list_Push(term_ArgumentList(Term),Stack); + else + if (term_IsVariable(Term)) + Variables = list_Cons(Term, Variables); + while (!list_StackEmpty(Stack) && list_Empty(list_Top(Stack))) + Stack = list_Pop(Stack); + if (!list_StackEmpty(Stack)) { + Term = (TERM)list_Car(list_Top(Stack)); + list_RplacTop(Stack, list_Cdr(list_Top(Stack))); + } + } while (!list_StackEmpty(Stack)); + return Variables; +} + + +void term_MarkVariables(TERM Term, NAT Mark) +/************************************************************** + INPUT: A term. + RETURNS: Nothing. + EFFECT: All variables from <Term> are marked with <Mark>. + CAUTION: The term module must be in a binding phase (started with + term_StartBinding)! +***************************************************************/ +{ + int Stack; + +#ifdef CHECK + if (!term_InBindingPhase()) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_MarkVariables:"); + misc_ErrorReport(" Called while not in binding phase."); + misc_FinishErrorReport(); + } +#endif + + Stack = stack_Bottom(); + do { + if (term_IsComplex(Term)) { + stack_Push(term_ArgumentList(Term)); + } + else if (term_IsVariable(Term)) + term_CreateBinding(term_TopSymbol(Term), Mark); + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Stack)) { + Term = (TERM)list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); +} + + +LIST term_VariableSymbols(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: The list of variable symbols occurring in the term. +***************************************************************/ +{ + LIST Variables; + int Stack; + SYMBOL Top; + NAT ActMark; + +#ifdef CHECK + if (!term_IsTerm(Term) || term_InBindingPhase()) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_VariableSymbols: Illegal input or context."); + misc_FinishErrorReport(); + } +#endif + + term_StartBinding(); + + Variables = list_Nil(); + Stack = stack_Bottom(); + ActMark = term_ActMark(); + do { + if (term_IsComplex(Term)) { + stack_Push(term_ArgumentList(Term)); + } + else { + Top = term_TopSymbol(Term); + if (symbol_IsVariable(Top) && !term_VarIsMarked(Top, ActMark)) { + Variables = list_Cons((POINTER)Top, Variables); + term_CreateBinding(Top, ActMark); + } + } + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Stack)) { + Term = (TERM)list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); + + term_StopBinding(); + + return Variables; +} + + +NAT term_NumberOfVarOccs(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: The list of variable symbols occurring in the term. +***************************************************************/ +{ + NAT Result; + int Stack; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_NumberOfVarOccs: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Result = 0; + Stack = stack_Bottom(); + do { + if (term_IsComplex(Term)) { + stack_Push(term_ArgumentList(Term)); + } + else { + if (symbol_IsVariable(term_TopSymbol(Term))) + Result++; + } + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Stack)) { + Term = (TERM)list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); + + return Result; +} + +NAT term_NumberOfSymbolOccurrences(TERM Term, SYMBOL Symbol) +/************************************************************** + INPUT: A term and a symbol. + RETURNS: The number of occurrences of <Symbol> in <Term> +***************************************************************/ +{ + NAT Result; + LIST Scan; + +#ifdef CHECK + if (!term_IsTerm(Term) || !symbol_IsSymbol(Symbol)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_NumberOfSymbolOccurrences: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Result = 0; + + if (symbol_Equal(term_TopSymbol(Term),Symbol)) + Result++; + + for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) + Result += term_NumberOfSymbolOccurrences(list_Car(Scan), Symbol); + + return Result; +} + + +BOOL term_ContainsFunctions(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: TRUE iff the term contains a function symbol +***************************************************************/ +{ + int Stack; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_ContainsFunctions: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Stack = stack_Bottom(); + do { + if (term_IsComplex(Term)) { + if (symbol_IsFunction(term_TopSymbol(Term)) && !symbol_IsConstant(term_TopSymbol(Term))) { + stack_SetBottom(Stack); + return TRUE; + } + stack_Push(term_ArgumentList(Term)); + } + + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Stack)) { + Term = (TERM)list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); + + return FALSE; +} + +BOOL term_ContainsVariable(TERM Term, SYMBOL Var) +/************************************************************** + INPUT: A term and a variable symbol. + RETURNS: TRUE iff the term contains the variable symbol +***************************************************************/ +{ + int Stack; + +#ifdef CHECK + if (!term_IsTerm(Term) || !symbol_IsSymbol(Var)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_ContainsVariable: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Stack = stack_Bottom(); + do { + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + else + if (symbol_Equal(term_TopSymbol(Term),Var)) { + stack_SetBottom(Stack); + return TRUE; + } + + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Stack)) { + Term = (TERM)list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); + + return FALSE; +} + +SYMBOL term_MaxVar(TERM Term) +/********************************************************* + INPUT: A term. + RETURNS: The maximal variable in <Term>, NULL otherwise +********************************************************/ +{ + LIST Scan; + int Stack; + SYMBOL Result; + +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_MaxVar: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + Result = (SYMBOL)NULL; + Stack = stack_Bottom(); + + if (term_IsStandardVariable(Term)) { + if (term_TopSymbol(Term)>Result) + Result = term_TopSymbol(Term); + } + else + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + + while (!stack_Empty(Stack)) { + Scan = stack_Top(); + Term = (TERM)list_Car(Scan); + stack_RplacTop(list_Cdr(Scan)); + + if (term_IsStandardVariable(Term)) { + if (term_TopSymbol(Term)>Result) + Result = term_TopSymbol(Term); + } + else + if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + } + + return Result; +} + + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * Renaming * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +void term_StartMinRenaming(void) +/************************************************************** + INPUT: None + EFFECT: Initializes the term and symbol modules for min co var renaming +***************************************************************/ +{ + symbol_ResetStandardVarCounter(); + term_NewMark(); +} + + +void term_StartMaxRenaming(SYMBOL MaxVar) +/************************************************************** + INPUT: A variable symbol. + EFFECT: Initializes the term and symbol modules for renaming above <MaxVar> +***************************************************************/ +{ + symbol_SetStandardVarCounter(MaxVar); + term_NewMark(); +} + + +TERM term_Rename(TERM Term) +/************************************************************** + INPUT: A Term. + RETURNS: The destructively renamed term. + EFFECT: All co variables are destructively renamed in <TERM> +***************************************************************/ +{ + int Stack; + SYMBOL Top; + NAT ActMark; + TERM ActTerm; + +#ifdef CHECK + if (!term_IsTerm(Term) || term_InBindingPhase()) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_Rename: Illegal input or context."); + misc_FinishErrorReport(); + } +#endif + + term_StartBinding(); + + Stack = stack_Bottom(); + ActMark = term_OldMark(); + ActTerm = Term; + do { + if (term_IsComplex(ActTerm)) { + stack_Push(term_ArgumentList(ActTerm)); + } + else { + Top = term_TopSymbol(ActTerm); + if (symbol_IsVariable(Top)) { + if (!term_VarIsMarked(Top, ActMark)) + term_CreateValueBinding(Top, ActMark, (POINTER)symbol_CreateStandardVariable()); + term_RplacTop(ActTerm,(SYMBOL)term_BindingValue(Top)); + } + } + + while (!stack_Empty(Stack) && list_Empty(stack_Top())) + stack_Pop(); + if (!stack_Empty(Stack)) { + ActTerm = (TERM)list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(Stack)); + + term_StopBinding(); + + return Term; +} + +SYMBOL term_GetRenamedVarSymbol(SYMBOL Var) +/************************************************************** + INPUT: A variable symbol. + RETURNS: The renamed variable for symbol for <var> with respect + to the current renaming. If it does not exist, <var> + itself is returned. + EFFECT: None. +***************************************************************/ +{ + NAT ActMark; + +#ifdef CHECK + if (!symbol_IsStandardVariable(Var)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_GetRenamedVarSymbol: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + ActMark = term_OldMark(); + + if (term_VarIsMarked(Var, ActMark)) + return (SYMBOL)term_BindingValue(Var); + + return Var; +} + + +static LIST term_MakePseudoLinear(TERM Term, NAT Depth, NAT Mark) +/************************************************************** + INPUT: A Term and a variable and the current depth. + RETURNS: A list of pairs (<oldvar>,<newvar>) + EFFECT: The term is destructively made pseudo_linear. +***************************************************************/ +{ + LIST Result,Scan; + SYMBOL Top; + + Result = list_Nil(); + + if (term_IsComplex(Term)) + for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) + Result = list_Nconc(term_MakePseudoLinear(list_Car(Scan),Depth+1,Mark), + Result); + else { + Top = term_TopSymbol(Term); + if (symbol_IsVariable(Top)) { + if (term_VarIsMarked(Top, Mark)) { + if (Depth != (NAT)term_BindingValue(Top)) + term_RplacTop(Term,symbol_CreateStandardVariable()); + Result = list_Cons(list_PairCreate((POINTER)Top, + (POINTER)term_TopSymbol(Term)), + Result); + } + else { + term_CreateValueBinding(Top, Mark, (POINTER)Depth); + } + } + } + + return Result; +} + + +LIST term_RenamePseudoLinear(TERM Term, SYMBOL Var) +/************************************************************** + INPUT: A Term and a variable. + RETURNS: A list of pairs (<oldvar>,<newvar>) + EFFECT: The term is destructively renamed. +***************************************************************/ +{ + NAT Mark; + LIST Result; + +#ifdef CHECK + if (!term_IsTerm(Term) || !symbol_IsVariable(Var) || term_InBindingPhase()) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_RenamePseudoLinear: Illegal input or context."); + misc_FinishErrorReport(); + } +#endif + + term_StartBinding(); + symbol_SetStandardVarCounter(Var); + + term_NewMark(); + Mark = term_ActMark(); + Result = term_MakePseudoLinear(Term,0,Mark); + + term_StopBinding(); + + return Result; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * STAMP FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +NAT term_GetStampID(void) +/************************************************************** + INPUT: None + RETURNS: An identifier that must be used for some stamp functions + EFFECT: Each module using the term stamp has to request an + identifier that is needed for function term_StampOverflow + The purpose of this identifier is to synchronize + different modules in case of an overflow of the variable + term_STAMP. +***************************************************************/ +{ + if (term_STAMPUSERS >= term_MAXSTAMPUSERS) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n In term_GetStampID: no more free stamp IDs."); + misc_UserErrorReport("\n You have to increase the constant term_MAXSTAMPUSERS."); + misc_FinishUserErrorReport(); + } + + return term_STAMPUSERS++; +} + + +BOOL term_StampOverflow(NAT ID) +/************************************************************** + INPUT: The identifier of the calling module as returned by + the function term_GetStampID. + RETURNS: True if an overflow of the variable term_STAMP occurred + for the module with the identifier ID. + CAUTION: If an overflow occurred for a module you can test that + only once!!! After the first test the overflow flag + is cleared for that module. +***************************************************************/ +{ + BOOL Result = FALSE; + NAT i; + +#ifdef CHECK + if (ID >= term_MAXSTAMPUSERS) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_StampOverflow: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + if (term_STAMP == NAT_MAX) { + term_STAMP = 0; + /* set overflow flag for all other modules */ + for (i = 0; i < term_MAXSTAMPUSERS; i++) + term_STAMPOVERFLOW[i] = TRUE; + term_STAMPOVERFLOW[ID] = FALSE; + Result = TRUE; + } else if (term_STAMPOVERFLOW[ID]) { + term_STAMPOVERFLOW[ID] = FALSE; + Result = TRUE; + } + return Result; +} + +void term_SetTermSubtermStamp(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: void. + EFFECT: Sets the current stamp to <Term> and its subterms. +***************************************************************/ +{ +#ifdef CHECK + if (!term_IsTerm(Term)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_SetTermSubtermStamp: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + term_SetTermStamp(Term); + list_Apply((void (*)(POINTER)) term_SetTermSubtermStamp, + term_ArgumentList(Term)); +} + +LIST term_ListOfAtoms(TERM Term, SYMBOL Predicate) +/************************************************************** + INPUT: A term and a predicate symbol. + RETURNS: A list of pointers to all atoms in Term with + predicate symbol <Predicate>. +***************************************************************/ +{ + if (symbol_Equal(term_TopSymbol(Term), Predicate)) + return list_List(Term); + else { + LIST Result, List; + + Result = list_Nil(); + for (List = term_ArgumentList(Term); !list_Empty(List); List = list_Cdr(List)) + Result = list_Nconc(Result, term_ListOfAtoms(list_Car(List), Predicate)); + return Result; + } +} + +/* Currently only in CHECK mode */ +#ifdef CHECK + +void term_StartStamp(void) +/************************************************************** + INPUT: None + RETURNS: Nothing + EFFECT: The stamp is prepared for a new term traversal. +***************************************************************/ +{ + if (term_STAMPBLOCKED) { + /* Error: the Stamp is already used */ + misc_StartErrorReport(); + misc_ErrorReport("\n In term_StartStamp: Illegal context, term stamp is already used."); + misc_FinishErrorReport(); + } + else { + term_STAMP++; + term_STAMPBLOCKED = TRUE; + } +} + +#endif + +LIST term_FindAllAtoms(TERM Term, SYMBOL Predicate) +/********************************************************************** + INPUT: A term Term and a symbol Predicate. + RETURN: A list of all atoms of Term with Symbol as top symbol. +***********************************************************************/ +{ + int stack; + LIST Result; + +#ifdef CHECK + if (!term_IsTerm(Term) || !symbol_IsPredicate(Predicate)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In term_FindAllPredicates: Illegal input."); + misc_FinishErrorReport(); + } +#endif + + stack = stack_Bottom(); + Result = list_Nil(); + + do { + if (term_TopSymbol(Term) == Predicate) { + Result = list_Cons(Term, Result); + } else if (term_IsComplex(Term)) + stack_Push(term_ArgumentList(Term)); + + while (!stack_Empty(stack) && list_Empty(stack_Top())) + stack_Pop(); + + if (!stack_Empty(stack)) { + Term = list_Car(stack_Top()); + stack_RplacTop(list_Cdr(stack_Top())); + } + } while (!stack_Empty(stack)); + + return Result; +} + +BOOL term_CheckTermIntern(TERM Term, BOOL Links) +/************************************************************************** + INPUT: A term and a boolean. + RETURN: True iff 1) the arity of each top symbol is equal to the number + of arguments of symbol's term. + and 2) either all father links are set correctly iff Links is TRUE + or none is set iff Links is FALSE. + COMMENT: Intern function of term_CheckTerm. +***************************************************************************/ +{ + LIST Scan; + SYMBOL Top; + + if (!term_IsTerm(Term)) + return FALSE; + + Top = term_TopSymbol(Term); + if (symbol_IsSignature(Top) && + symbol_Arity(Top) != -1 && + symbol_Arity(Top) != (int)list_Length(term_ArgumentList(Term))) + return FALSE; + + if (symbol_IsVariable(Top) && !list_Empty(term_ArgumentList(Term))) + return FALSE; + + if (Links) { + for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (term_Superterm(list_Car(Scan)) != Term || + !term_CheckTermIntern(list_Car(Scan), Links)) + return FALSE; + } + } + else { + for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + if (term_Superterm(list_Car(Scan)) != term_Null() || + !term_CheckTermIntern(list_Car(Scan), Links)) + return FALSE; + } + } + return TRUE; +} + +BOOL term_CheckTerm(TERM Term) +/******************************************************************************** + INPUT : A term Term. + RETURN: TRUE iff eihter all or no father links are set AND + the length of any argument list matches the arity of the respective symbol +*********************************************************************************/ +{ + if (term_IsComplex(Term) && + term_Superterm(term_FirstArgument(Term)) != term_Null()) + /* check father links as well */ + return term_CheckTermIntern(Term, TRUE); + else + return term_CheckTermIntern(Term, FALSE); +} diff --git a/test/spass/term.h b/test/spass/term.h new file mode 100644 index 0000000000000000000000000000000000000000..3acb2371197c7224142f2301dc2eeb4b9ac7afea --- /dev/null +++ b/test/spass/term.h @@ -0,0 +1,612 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * TERMS * */ +/* * * */ +/* * $Module: TERM * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + + +#ifndef _TERM_ +#define _TERM_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "symbol.h" +#include "stack.h" + +/**************************************************************/ +/* Structures */ +/**************************************************************/ + +/* In CHECK mode you can block the stamp for all terms, + so no other function can use the macro term_IncStamp(), + which must be used for initialization at the beginning + of a new traversal */ + +typedef struct term { + SYMBOL symbol; + union { + LIST termlist; + struct term* term; + } super; + LIST args; + NAT stamp; + NAT size; +} *TERM, TERM_NODE; + + +/* Data Structures and Macros for Marking of variables, used in */ +/* all functions extracting variables from terms. */ + +extern NAT term_MARK; +extern POINTER term_BIND[symbol__MAXVARIABLES][2]; + +#ifdef CHECK +extern BOOL term_BINDPHASE; +static __inline__ void term_StartBinding(void) { term_BINDPHASE=TRUE; } +static __inline__ void term_StopBinding(void) { term_BINDPHASE=FALSE; } +static __inline__ BOOL term_InBindingPhase(void) { return term_BINDPHASE; } +#else +static __inline__ void term_StartBinding(void) { } +static __inline__ void term_StopBinding(void) { } +#endif + +static __inline__ NAT term_NullMark(void) +{ + return 0; +} + + +static __inline__ NAT term_BindingMark(SYMBOL Var) +{ + return (NAT) term_BIND[symbol_VarIndex(Var)][0]; +} + + +static __inline__ void term_SetBindingMark(SYMBOL Var, NAT Mark) +{ + term_BIND[symbol_VarIndex(Var)][0] = (POINTER) Mark; +} + + +static __inline__ POINTER term_BindingValue(SYMBOL Var) +{ + return term_BIND[symbol_VarIndex(Var)][1]; +} + + +static __inline__ void term_SetBindingValue(SYMBOL Var, POINTER Value) +{ + term_BIND[symbol_VarIndex(Var)][1] = Value; +} + +static __inline__ void term_CreateBinding(SYMBOL Var, NAT Mark) +{ + term_SetBindingMark(Var, Mark); +} + +static __inline__ void term_ClearBinding(SYMBOL Var) +{ + term_SetBindingMark(Var, term_NullMark()); +} + +static __inline__ void term_CreateValueBinding(SYMBOL Var, NAT Mark, POINTER Value) +{ + term_SetBindingMark(Var, Mark); + term_SetBindingValue(Var, Value); +} + + +static __inline__ BOOL term_VarIsMarked(SYMBOL Var, NAT Mark) +{ + return term_BindingMark(Var) >= Mark; +} + + +static __inline__ NAT term_ActMark(void) +{ + NAT MarkVar; + if (term_MARK == NAT_MAX) { + int i; + for (i = 0; i < symbol_MaxVars(); i++) + term_BIND[i][0] = (POINTER) term_NullMark(); + term_MARK = 1; + } + MarkVar = term_MARK++; + return MarkVar; +} + + +static __inline__ void term_NewMark(void) +{ + if (term_MARK == NAT_MAX) { + int i; + for (i = 0; i < symbol_MaxVars(); i++) + term_BIND[i][0] = (POINTER) term_NullMark(); + term_MARK = 1; + } + term_MARK++; +} + + +static __inline__ NAT term_OldMark(void) +{ + return term_MARK - 1; +} + + +/**************************************************************/ +/* Macros */ +/**************************************************************/ + +static __inline__ TERM term_Null(void) +{ + return (TERM)NULL; +} + +static __inline__ SYMBOL term_TopSymbol(TERM T) +{ + return T->symbol; +} + + +static __inline__ void term_RplacTop(TERM T, SYMBOL S) +{ + T->symbol = S; +} + + +static __inline__ LIST term_SupertermList(TERM T) +{ + return T->super.termlist; +} + + +static __inline__ void term_RplacSupertermList(TERM T, LIST L) +{ + T->super.termlist = L; +} + + +static __inline__ LIST term_AtomsLiterals(TERM T) +{ + return T->super.termlist; +} + + +static __inline__ TERM term_Superterm(TERM T) +{ + return T->super.term; +} + + +static __inline__ void term_RplacSuperterm(TERM T1, TERM T2) +{ + T1->super.term = T2; +} + + +static __inline__ BOOL term_IsVariable(TERM T) +{ + return symbol_IsVariable(term_TopSymbol(T)); +} + + +static __inline__ BOOL term_IsStandardVariable(TERM T) +{ + return symbol_IsStandardVariable(term_TopSymbol(T)); +} + + +static __inline__ BOOL term_IsIndexVariable(TERM T) +{ + return symbol_IsIndexVariable(term_TopSymbol(T)); +} + + +static __inline__ LIST term_ArgumentList(TERM T) +{ + return T->args; +} + + +static __inline__ void term_RplacArgumentList(TERM T, LIST A) +{ + T->args = A; +} + + +static __inline__ BOOL term_IsComplex(TERM T) +{ + return term_ArgumentList(T) != NULL; +} + + +static __inline__ BOOL term_IsConstant(TERM T) +{ + return !term_IsComplex(T) && !term_IsVariable(T); +} + + +static __inline__ BOOL term_IsAtom(TERM T) +{ + return symbol_IsPredicate(term_TopSymbol(T)); +} + +static __inline__ BOOL term_IsDeclaration(TERM Term) +/************************************************************** + INPUT: A term. + RETURNS: TRUE, if the term is a monadic atom, FALSE otherwise. +***************************************************************/ +{ + return (term_IsAtom(Term) && symbol_IsBaseSort(term_TopSymbol(Term))); +} + + +static __inline__ TERM term_FirstArgument(TERM T) +{ + return (TERM) list_First(T->args); +} + + +static __inline__ void term_RplacFirstArgument(TERM T1, TERM T2) +{ + list_Rplaca(T1->args, T2); +} + + +static __inline__ TERM term_SecondArgument(TERM T) +{ + return (TERM) list_Second(T->args); +} + + +static __inline__ void term_RplacSecondArgument(TERM T1, TERM T2) +{ + list_RplacSecond(T1->args, T2); +} + + +static __inline__ void term_Free(TERM T) +{ + memory_Free((char*) T, sizeof(TERM_NODE)); +} + + +static __inline__ BOOL term_EqualTopSymbols(TERM T, TERM S) +{ + return symbol_Equal(term_TopSymbol(T), term_TopSymbol(S)); +} + + +static __inline__ void term_EqualitySwap(TERM T) +{ + TERM Aux; + Aux = term_FirstArgument(T); + list_Rplaca(term_ArgumentList(T), (POINTER) term_SecondArgument(T)); + list_Rplaca(list_Cdr(term_ArgumentList(T)), (POINTER) Aux); +} + + +/**************************************************************/ +/* Macros and Variables for the term's stamp */ +/**************************************************************/ + +/* Maximum number of modules that use the term module's stamp */ +#define term_MAXSTAMPUSERS 20 + +extern NAT term_STAMP; +extern BOOL term_STAMPBLOCKED; + +static __inline__ NAT term_Stamp(void) +{ + return term_STAMP; +} + +static __inline__ BOOL term_StampBlocked(void) +{ + return term_STAMPBLOCKED; +} + + +#ifdef CHECK + +/* In CHECK mode 'term_StartStamp' is a real function defined in */ +/* 'term.c'. */ + +static __inline__ void term_StopStamp(void) +{ + term_STAMPBLOCKED = FALSE; +} + +#else + +/* Attention: */ +/* You should check for Overflow before calling this function !!!!! */ +/* Use "term_StampOverflow" to do this. */ +/* If an overflow occurred, you have to reset the stamp of all terms */ +/* you're using. */ +static __inline__ void term_StartStamp(void) +{ + term_STAMP++; +} + +static __inline__ void term_StopStamp(void) +{ } + +#endif + + +static __inline__ NAT term_TermStamp(TERM T) +{ + return T->stamp; +} + +static __inline__ void term_SetTermStamp(TERM T) +{ + T->stamp = term_STAMP; +} + +static __inline__ NAT term_Size(TERM T) +{ + return T->size; +} + +static __inline__ void term_SetSize(TERM T, NAT s) +{ + T->size = s; +} + +static __inline__ BOOL term_AlreadyVisited(TERM T) +{ + return T->stamp == term_STAMP; +} + +static __inline__ BOOL term_HasTermStamp(TERM T) +{ + return T->stamp == term_STAMP; +} + +static __inline__ void term_ResetTermStamp(TERM T) +{ + T->stamp = 0; +} + +static __inline__ BOOL term_StampAlreadyReset(TERM T) +{ + return T->stamp == 0; +} + + +/**************************************************************/ +/* Functions on Term Creation And Deletion */ +/**************************************************************/ + +void term_Init(void); + +TERM term_Create(SYMBOL, LIST); +TERM term_CreateAddFather(SYMBOL, LIST); +TERM term_CreateStandardVariable(void); +void term_Delete(TERM); +void term_DeleteIterative(TERM); + +/**************************************************************/ +/* Term Comparisons */ +/**************************************************************/ + +BOOL term_Equal(TERM, TERM); +BOOL term_EqualIterative(TERM, TERM); /* Unused */ +BOOL term_VariableEqual(TERM, TERM); +BOOL term_IsGround(TERM); +BOOL term_IsTerm(TERM); +BOOL term_IsTermList(LIST); +BOOL term_AllArgsAreVar(TERM); +int term_CompareBySymbolOccurences(TERM, TERM); +int term_CompareAbstract(TERM, TERM); +BOOL term_CompareAbstractLEQ(TERM, TERM); + + +/**************************************************************/ +/* Low Level Term Functions */ +/**************************************************************/ + +TERM term_Copy(TERM); +TERM term_CopyIterative(TERM); /* Unused */ +TERM term_CopyWithEmptyArgListNode(TERM, LIST, LIST*); +void term_PrintWithEmptyArgListNode(TERM); +BOOL term_ReplaceSubtermBy(TERM, TERM, TERM); +void term_ReplaceVariable(TERM, SYMBOL, TERM); +void term_ExchangeVariable(TERM, SYMBOL, SYMBOL); +BOOL term_SubstituteVariable(SYMBOL, TERM, TERM*); +NAT term_ComputeSize(TERM); +void term_InstallSize(TERM); +NAT term_Depth(TERM); +BOOL term_ContainsSymbol(TERM, SYMBOL); +BOOL term_Sharing(TERM); +void term_AddFatherLinks(TERM); +BOOL term_FatherLinksEstablished(TERM); +TERM term_TopLevelTerm(TERM); +BOOL term_HasPointerSubterm(TERM, TERM); +BOOL term_HasSubterm(TERM, TERM); +BOOL term_HasProperSuperterm(TERM, TERM); +TERM term_FindSubterm(TERM, SYMBOL); +LIST term_FindAllAtoms(TERM, SYMBOL); +BOOL term_CheckTerm(TERM); +NAT term_RootDistance(TERM); +BOOL term_RootDistanceSmaller(TERM,TERM); + +static __inline__ LIST term_CopyTermList(LIST List) +/************************************************************** + INPUT: A list of TERMs. + RETURNS: A deep copy of the list, i.e. the terms are copied, too. +***************************************************************/ +{ + return list_CopyWithElement(List, (POINTER (*)(POINTER))term_Copy); +} + +static __inline__ void term_CopyTermsInList(LIST List) +/************************************************************** + INPUT: A list of TERMs. + EFFECT: Replaces every term in the list with its copy. +***************************************************************/ +{ + list_NMapCar(List, (POINTER (*)(POINTER)) term_Copy); +} + +static __inline__ void term_DeleteTermList(LIST List) +/************************************************************** + INPUT: A list of TERMs. + RETURNS: Nothing. + EFFECT: The list is freed together with its elements. +***************************************************************/ +{ + list_DeleteWithElement(List, (void (*)(POINTER))term_Delete); +} + +static __inline__ BOOL term_ListContainsTerm(LIST List, TERM Term) +/************************************************************** + INPUT: A list of TERMs. + RETURNS: TRUE, if <List> contains <Term>, FALSE otherwise. + Terms are compared with respect to the term_Equal function. +***************************************************************/ +{ + return list_Member(List, Term, (BOOL (*)(POINTER,POINTER))term_Equal); +} + +static __inline__ LIST term_DeleteDuplicatesFromList(LIST List) +/************************************************************** + INPUT: A list of TERMs. + RETURNS: The list where duplicate terms are removed. + EFFECT: Terms are compared with respect to the term_Equal function. + The duplicate terms are not deleted. +***************************************************************/ +{ + return list_DeleteDuplicates(List, (BOOL (*)(POINTER, POINTER))term_Equal); +} + + +static __inline__ LIST term_DestroyDuplicatesInList(LIST Terms) +/************************************************************** + INPUT: A list of terms. + RETURNS: The list where all duplicate terms are removed. + EFFECTS: The terms are compared with respect to the term_Equal function. + The duplicate terms are deleted, too. +***************************************************************/ +{ + return list_DeleteDuplicatesFree(Terms, (BOOL (*)(POINTER,POINTER))term_Equal, + (void (*)(POINTER))term_Delete); +} + + + +/**************************************************************/ +/* Term Input and Output Functions */ +/**************************************************************/ + +void term_Print(TERM); +void term_PrettyPrint(TERM); +void term_FPrint(FILE*, TERM); +void term_TermListPrint(LIST); +void term_TermListFPrint(FILE*, LIST); + + +void term_PrintPrefix(TERM); +void term_FPrintPrefix(FILE*, TERM); +void term_TermListPrintPrefix(LIST); +void term_TermListFPrintPrefix(FILE*, LIST); + +void term_FPrintOtterPrefix(FILE*, TERM); +void term_TermListFPrintOtterPrefix(FILE*, LIST); + +void term_FPrintPosition(FILE*,TERM,TERM); + +static __inline__ void term_PrintPosition(TERM TopTerm, TERM Subterm) +{ + term_FPrintPosition(stdout, TopTerm, Subterm); +} + +/**************************************************************/ +/* High Level Term Functions */ +/**************************************************************/ + +void term_ToCoVariables(TERM); +NAT term_Bytes(TERM); + +void term_MarkVariables(TERM, NAT); +void term_CountSymbols(TERM); +LIST term_ListOfVariables(TERM); +LIST term_VariableSymbols(TERM); +LIST term_ListOfAtoms(TERM,SYMBOL); +LIST term_ListOfConstants(TERM); +LIST term_ListOfFunctions(TERM); +NAT term_NumberOfVarOccs(TERM); +NAT term_NumberOfSymbolOccurrences(TERM, SYMBOL); +BOOL term_ContainsFunctions(TERM); +BOOL term_ContainsVariable(TERM,SYMBOL); +SYMBOL term_MaxVar(TERM); + +void term_StartMinRenaming(void); +void term_StartMaxRenaming(SYMBOL); +TERM term_Rename(TERM); +SYMBOL term_GetRenamedVarSymbol(SYMBOL); + +LIST term_RenamePseudoLinear(TERM, SYMBOL); + +/**************************************************************/ +/* Stamp Functions */ +/**************************************************************/ + +/* Currently only in CHECK mode */ +#ifdef CHECK +void term_StartStamp(void); +#endif + +void term_SetTermSubtermStamp(TERM T); + +NAT term_GetStampID(void); +BOOL term_StampOverflow(NAT); + + +#endif diff --git a/test/spass/terminator.c b/test/spass/terminator.c new file mode 100644 index 0000000000000000000000000000000000000000..73352043745062e19bccbc46a03d95eba1f3a55c --- /dev/null +++ b/test/spass/terminator.c @@ -0,0 +1,319 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * TERMINATOR * */ +/* * * */ +/* * $Module: REDRULES * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/* $RCSfile$ */ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "terminator.h" +#include "list.h" + + +static LIST red_GetTerminatorPartnerLits(TERM Atom, LITERAL Lit, + BOOL UnitsOnly, LIST IndexList) +/************************************************************** + INPUT: An atom, a literal, a boolean flag and a list of SHARED_INDEXes. + RETURNS: A list of literals with sign complementary to <Lit> + that are unifiable with <Atom>. The literals are searched + in all SHARED_INDEXes from <IndexList>. Additionally, + if <Unitsonly> is true, only literals from unit clauses + are returned. + EFFECT: <Atom> is a copy of <Lit> where some substitution + was applied and equality literals might have been swapped. + <Lit> is just needed to check whether the unifiable + literals are complementary. +***************************************************************/ +{ + LIST Result, Unifiers, LitScan; + LITERAL NextLit; + + Result = list_Nil(); + for ( ; !list_Empty(IndexList); IndexList = list_Cdr(IndexList)) { + Unifiers = st_GetUnifier(cont_LeftContext(), + sharing_Index(list_Car(IndexList)), + cont_RightContext(), Atom); + for ( ; !list_Empty(Unifiers); Unifiers = list_Pop(Unifiers)) { + if (!term_IsVariable(list_Car(Unifiers))) { + for (LitScan = sharing_NAtomDataList(list_Car(Unifiers)); + !list_Empty(LitScan); LitScan = list_Cdr(LitScan)) { + NextLit = list_Car(LitScan); + if (clause_LiteralsAreComplementary(Lit, NextLit) && + (!UnitsOnly || clause_Length(clause_LiteralOwningClause(NextLit))==1)) + /* The partner literals must have complementary sign and + if <UnitsOnly> == TRUE they must be from unit clauses. */ + Result = list_Cons(NextLit, Result); + } + } + } + } + return Result; +} + + +static CLAUSE red_CreateTerminatorEmptyClause(LIST FoundMap, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A list of pairs (l1, l2), where l1 and l2 are unifiable + literals with complementary sign and a flag store. + More accurately, a substitution s exists, + such that l1 s = l2 s for all pairs (l1,l2) in + <FoundMap>. + For all literals l from the involved clauses + there exists one pair (l1,l2) in <FoundMap> + with l1=l or l2=l. + The flags store and the precedence are needed to create + the new clause. + RETURNS: A newly created empty clause, where the data + (parents,...) is set according to <FoundMap>. +***************************************************************/ +{ + CLAUSE Result, PClause; + LITERAL Lit; + LIST Parents; + NAT depth; + + Result = clause_Create(list_Nil(), list_Nil(), list_Nil(), Flags, Precedence); + Parents = list_Nil(); + depth = 0; + for (; !list_Empty(FoundMap); FoundMap = list_Cdr(FoundMap)) { + Lit = list_PairSecond(list_Car(FoundMap)); + PClause = clause_LiteralOwningClause(Lit); + Parents = list_Cons(PClause, Parents); + depth = misc_Max(depth, clause_Depth(PClause)); + clause_AddParentClause(Result, clause_Number(PClause)); + clause_AddParentLiteral(Result, clause_LiteralGetIndex(Lit)); + + Lit = list_PairFirst(list_Car(FoundMap)); + PClause = clause_LiteralOwningClause(Lit); + Parents = list_Cons(PClause, Parents); + depth = misc_Max(depth, clause_Depth(PClause)); + clause_AddParentClause(Result, clause_Number(PClause)); + clause_AddParentLiteral(Result, clause_LiteralGetIndex(Lit)); + } + clause_SetFromTerminator(Result); + clause_SetDepth(Result, depth+1); + clause_SetSplitDataFromList(Result, Parents); + list_Delete(Parents); + return Result; +} + + +static BOOL red_TerminatorLitIsBetter(LITERAL L1, NAT S1, LITERAL L2, NAT S2) +/************************************************************** + INPUT: Two literals and its sizes wrt. some substitution. + RETURNS: TRUE, if <L1> is 'better' than <L2>, FALSE otherwise. + EFFECT: 1. Positive literals are 'better' than negative literals + 2. If both literals have the same sign, the bigger literal + is better. + This is an heuristic that has shown to be useful in practice. + This function is used as parameter for the function + clause_MoveBestLiteralToFront. +***************************************************************/ +{ + if ((clause_LiteralIsNegative(L2) && clause_LiteralIsPositive(L1)) || + /* The following conditions do the same as this condition: */ + /* (!clause_LiteralsAreComplementary(L1, L2) && S1 > S2) */ + (clause_LiteralIsPositive(L1) && S1 > S2) || + (clause_LiteralIsNegative(L2) && S1 > S2)) + return TRUE; + else + return FALSE; +} + + +static CLAUSE red_SearchTerminator(NAT n, LIST RestLits, LIST FoundMap, + SUBST Subst, SYMBOL GlobalMaxVar, + LIST IndexList, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A natural number, a list of literals, a list of pairs, + a substitution, the maximum variable occurring in all + involved clauses, a list of SHARED_INDEXes, a flag store + and a precedence. + RETURNS: An empty clause, if a terminator situation was found, + NULL otherwise. + EFFECT: This recursive function implements the search for + a terminator situation with at most <n> non-unit clauses. + <RestLits> is the lists of literals actually missing + a complementary partner literal. + <FoundMap> is a list of pairs (l1,l2), where l1 and l2 + are complementary, unifiable literals. + <Subst> is the common substitution of all those pairs. + <GlobalMaxVar> is the maximum variable from all + involved clauses. + To enable the search all involved clauses are made + variable-disjoint. + At the moment the function stops, if ANY terminator + situation occurred. This might not be desirable + if splitting is enabled, since there might be other + terminator situations resulting in an empty clause + of lower split level. + The flag store and the precedence are needed to create + the new clause. +***************************************************************/ +{ + if (list_Empty(RestLits)) { + /* We found a terminator situation, so stop the recursion */ + return red_CreateTerminatorEmptyClause(FoundMap, Flags, Precedence); + } else { + CLAUSE Result, PClauseCopy; + LITERAL Lit, PLit; + SYMBOL NewMaxVar; + SUBST NewSubst, RightSubst; + TERM AtomCopy; + LIST ClashList, ToDoList; + BOOL Swapped; + NAT Limit; + int PLitInd; + + Swapped = FALSE; + Result = clause_Null(); + clause_MoveBestLiteralToFront(RestLits, Subst, GlobalMaxVar, + red_TerminatorLitIsBetter); + Lit = list_Car(RestLits); + RestLits = list_Cdr(RestLits); + AtomCopy = subst_Apply(Subst, term_Copy(clause_LiteralAtom(Lit))); + + /* The following 'endless' loop runs twice for equality literals */ + /* and only once for other literals. */ + while (TRUE) { + ClashList = red_GetTerminatorPartnerLits(AtomCopy, Lit, n==0, IndexList); + for (; !list_Empty(ClashList) && Result==NULL; + ClashList = list_Pop(ClashList)) { + PLit = list_Car(ClashList); + PLitInd = clause_LiteralGetIndex(PLit); + PClauseCopy = clause_Copy(clause_LiteralOwningClause(PLit)); + Limit = clause_Length(PClauseCopy) == 1 ? n : n-1; + + clause_RenameVarsBiggerThan(PClauseCopy, GlobalMaxVar); + + PLit = clause_GetLiteral(PClauseCopy, PLitInd); + FoundMap = list_Cons(list_PairCreate(Lit, PLit), FoundMap); + ToDoList = clause_GetLiteralListExcept(PClauseCopy, PLitInd); + ToDoList = list_Nconc(ToDoList, list_Copy(RestLits)); + + NewMaxVar = clause_SearchMaxVar(PClauseCopy); + if (symbol_GreaterVariable(GlobalMaxVar, NewMaxVar)) + NewMaxVar = GlobalMaxVar; + + cont_Check(); + if (!unify_UnifyNoOC(cont_LeftContext(), AtomCopy, + cont_RightContext(), clause_LiteralAtom(PLit))) { + misc_StartErrorReport(); + misc_ErrorReport("\n In red_SearchTerminator: Unification failed."); + misc_FinishErrorReport(); + } + subst_ExtractUnifier(cont_LeftContext(), &NewSubst, + cont_RightContext(), &RightSubst); + cont_Reset(); + + /* The domains of both substitutions are disjoint */ + /* so we do just a simple union operation. */ + NewSubst = subst_NUnion(NewSubst, RightSubst); + RightSubst = NewSubst; + NewSubst = subst_Compose(NewSubst, subst_Copy(Subst)); + subst_Delete(RightSubst); + + Result = red_SearchTerminator(Limit, ToDoList, FoundMap, NewSubst, + NewMaxVar, IndexList, Flags, Precedence); + + clause_Delete(PClauseCopy); + subst_Delete(NewSubst); + list_Delete(ToDoList); + list_PairFree(list_Car(FoundMap)); + FoundMap = list_Pop(FoundMap); + } + /* loop control */ + if (!fol_IsEquality(AtomCopy) || Swapped || Result!=NULL) + break; + else { + list_Delete(ClashList); + term_EqualitySwap(AtomCopy); + Swapped = TRUE; + } + } + /* cleanup */ + term_Delete(AtomCopy); + /* <ClashList> may be non-empty since the loop stops */ + /* if a terminator was found. */ + list_Delete(ClashList); + + return Result; + } +} + + +CLAUSE red_Terminator(CLAUSE RedClause, NAT n, SHARED_INDEX WoIndex, + SHARED_INDEX UsIndex, FLAGSTORE Flags, + PRECEDENCE Precedence) +/************************************************************** + INPUT: A clause, two shared indexes, a number <n> + restricting the number of non-unit clauses in + a possible terminator situation, a flag store + and a precedence. + RETURNS: An empty clause if a terminator with at most <n> + non-unit clauses is found, NULL otherwise. + EFFECT: See also description of red_SearchTerminator. +***************************************************************/ +{ + LIST Rest, IndexList; + CLAUSE Result; + + if (clause_Length(RedClause) > 1) /* non-unit clause */ + n--; + + /* Pass the indexes as a list to sub-functions */ + IndexList = list_Cons(WoIndex, list_List(UsIndex)); + Rest = clause_GetLiteralList(RedClause); + Result = red_SearchTerminator(n, Rest, list_Nil(), subst_Nil(), + clause_MaxVar(RedClause), IndexList, Flags, + Precedence); + + /* cleanup */ + list_Delete(IndexList); + list_Delete(Rest); + + return Result; +} diff --git a/test/spass/terminator.h b/test/spass/terminator.h new file mode 100644 index 0000000000000000000000000000000000000000..8ddf32d3b1fe4510c3e1ffb945bb994635561639 --- /dev/null +++ b/test/spass/terminator.h @@ -0,0 +1,58 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * TERMINATOR * */ +/* * * */ +/* * $Module: REDRULES * */ +/* * * */ +/* * Copyright (C) 1999, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + +/* $RCSfile$ */ + +#ifndef _TERMINATOR_ +#define _TERMINATOR_ + + +#include "misc.h" +#include "symbol.h" +#include "clause.h" +#include "sharing.h" +#include "flags.h" + +CLAUSE red_Terminator(CLAUSE,NAT,SHARED_INDEX,SHARED_INDEX,FLAGSTORE,PRECEDENCE); + +#endif diff --git a/test/spass/top.c b/test/spass/top.c new file mode 100644 index 0000000000000000000000000000000000000000..073add9a4bcdf43a44d4fe85205f7450bb494ab8 --- /dev/null +++ b/test/spass/top.c @@ -0,0 +1,1648 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * TOP MODULE OF SPASS * */ +/* * * */ +/* * $Module: TOP * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 35442 $ * */ +/* $State$ * */ +/* $Date: 2007-03-28 17:24:40 -0700 (Wed, 28 Mar 2007) $ * */ +/* $Author: jeffc $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +/*** MAIN LOOP *************************************************/ + + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "dfg.h" +#include "defs.h" +#include "ia.h" +#include "rules-inf.h" +#include "rules-sort.h" +#include "rules-split.h" +#include "terminator.h" +#include "rules-red.h" +#include "analyze.h" +#include "clock.h" +#include "stringsx.h" +#include "options.h" +#include "context.h" +#include "cnf.h" +#include "search.h" +#include "hasharray.h" +#include "closure.h" +#include <errno.h> +#include <stdlib.h> + + +/**************************************************************/ +/* Types and Variables */ +/**************************************************************/ + +static const char *top_InputFile; + +static OPTID top_RemoveFileOptId; + +typedef enum {top_PROOF, top_COMPLETION, top_RESOURCE} top_SEARCHRESULT; + + +/**************************************************************/ +/* Catch Signals Section */ +/**************************************************************/ + +#if (defined(SPASS_SIGNALS)) +#include <signal.h> + +static PROOFSEARCH *top_PROOFSEARCH; + +static void top_SigHandler(int Signal) +/************************************************************** + INPUT: + RETURNS: + EFFECT: +***************************************************************/ +{ + if (Signal == SIGSEGV || Signal == SIGBUS) { + puts("\n\n\tSPASS is going to crash. This is probably caused by a"); + puts("\tbug in SPASS. Please send a copy of the input file(s) together"); + puts("\twith the used options to weidenb@mpi-sb.mpg.de, and someone will"); + puts("\ttry to fix the problem.\n"); + abort(); + } + + if (Signal == SIGINT || Signal == SIGTERM) { + clock_StopPassedTime(clock_OVERALL); + printf("\nSPASS %s ", misc_VERSION); + puts("\nSPASS beiseite: Ran out of time. SPASS was killed."); + printf("Problem: %s ", + (top_InputFile != (char*)NULL ? top_InputFile : "Read from stdin.")); + printf("\nSPASS derived %d clauses, backtracked %d clauses " + "and kept %d clauses.", + (*top_PROOFSEARCH == (PROOFSEARCH)NULL ? 0 : prfs_DerivedClauses(*top_PROOFSEARCH)), + (*top_PROOFSEARCH == (PROOFSEARCH)NULL ? 0 : prfs_BacktrackedClauses(*top_PROOFSEARCH)), + (*top_PROOFSEARCH == (PROOFSEARCH)NULL ? 0 : prfs_KeptClauses(*top_PROOFSEARCH))); + printf("\nSPASS allocated %lu KBytes.", memory_DemandedBytes()/1024); + fputs("\nSPASS spent\t", stdout); + clock_PrintTime(clock_OVERALL); + fputs(" on the problem.\n\t\t", stdout); + clock_PrintTime(clock_INPUT); + fputs(" for the input.\n\t\t", stdout); + clock_PrintTime(clock_CNF); + fputs(" for the FLOTTER CNF translation.\n\t\t", stdout); + clock_PrintTime(clock_INFERENCE); + fputs(" for inferences.\n\t\t", stdout); + clock_PrintTime(clock_BACKTRACK); + fputs(" for the backtracking.\n\t\t", stdout); + clock_PrintTime(clock_REDUCTION); + puts(" for the reduction."); + } + + if (opts_IsSet(top_RemoveFileOptId)) + remove(top_InputFile); + + exit(EXIT_FAILURE); +} + +#endif + + +/**************************************************************/ +/* Clause Selection Functions */ +/**************************************************************/ + +static CLAUSE top_SelectClauseDepth(LIST List, FLAGSTORE Flags) +/************************************************************** + INPUT: A list of clauses and a flag store. + RETURNS: A clause selected from the list. + EFFECT: This function selects a clause from the list according + to the following criteria: + 1. minimal depth + 2. minimal weight + 3a. maximal number of variable occurrences, if the flag + 'PrefVar' is TRUE + 3b. minimal number of variable occurrences, if 'PrefVar' + is FALSE +***************************************************************/ +{ + CLAUSE Result; + NAT Vars,NewVars,Weight,Depth,NewDepth; + + Result = (CLAUSE)list_Car(List); + Depth = clause_Depth(Result); + Weight = clause_Weight(Result); + Vars = clause_NumberOfVarOccs(Result); + List = list_Cdr(List); + + while (!list_Empty(List)) { + NewDepth = clause_Depth(list_Car(List)); + if (NewDepth <= Depth) { + if (NewDepth < Depth || clause_Weight(list_Car(List)) < Weight) { + Depth = NewDepth; + Result = (CLAUSE)list_Car(List); + Weight = clause_Weight(Result); + Vars = clause_NumberOfVarOccs(list_Car(List)); + } + else + if (clause_Weight(list_Car(List)) == Weight) { + NewVars = clause_NumberOfVarOccs(list_Car(List)); + if (flag_GetFlagValue(Flags, flag_PREFVAR)) { + if (Vars < NewVars) { + Depth = NewDepth; + Result = (CLAUSE)list_Car(List); + Weight = clause_Weight(Result); + Vars = NewVars; + } + } + else + if (Vars > NewVars) { + Depth = NewDepth; + Result = (CLAUSE)list_Car(List); + Weight = clause_Weight(Result); + Vars = NewVars; + } + } + } + List = list_Cdr(List); + } + + return Result; +} + + +static CLAUSE top_SelectMinimalWeightClause(LIST List, FLAGSTORE Flags) +/************************************************************** + INPUT: A list of clauses and a flag store. + RETURNS: A clause selected from the list. + EFFECT: This function selects a clause with minimal weight. + If more than one clause has minimal weight and the flag + 'PrefVar' is TRUE, a clause with maximal number of variable + occurrences is selected. If 'PrefVar' is FALSE, a clause with + minimal number of variable occurrences is selected. + If two clauses are equal with respect to the two criteria + the clause with the smaller list position is selected. + CAUTION: THE LIST HAS TO BY SORTED BY WEIGHT IN ASCENDING ORDER! +***************************************************************/ +{ + CLAUSE Result; + NAT Vars, NewVars, Weight; + +#ifdef CHECK + /* Check invariant: List has to be sorted by weight (ascending) */ + LIST Scan; + Weight = clause_Weight(list_Car(List)); + for (Scan = list_Cdr(List); !list_Empty(Scan); Scan = list_Cdr(Scan)) { + NAT NewWeight; + NewWeight = clause_Weight(list_Car(Scan)); + if (NewWeight < Weight) { + misc_StartErrorReport(); + misc_ErrorReport("\n In top_SelectMinimalConWeightClause: clause list "); + misc_ErrorReport("isn't sorted by weight"); + misc_FinishErrorReport(); + } + Weight = NewWeight; + } +#endif + + Result = (CLAUSE)list_Car(List); + Weight = clause_Weight(Result); + Vars = clause_NumberOfVarOccs(Result); + List = list_Cdr(List); + + while (!list_Empty(List)) { + if (clause_Weight(list_Car(List)) == Weight) { + NewVars = clause_NumberOfVarOccs(list_Car(List)); + if (flag_GetFlagValue(Flags, flag_PREFVAR)) { + if (Vars < NewVars) { + Result = (CLAUSE)list_Car(List); + Weight = clause_Weight(Result); + Vars = NewVars; + } + } + else + if (Vars > NewVars) { + Result = (CLAUSE)list_Car(List); + Weight = clause_Weight(Result); + Vars = NewVars; + } + } + else + return Result; + List = list_Cdr(List); + } + return Result; +} + + +static CLAUSE top_SelectMinimalConWeightClause(LIST List, FLAGSTORE Flags) +/************************************************************** + INPUT: A non-empty list of clauses and a flag store. + RETURNS: A clause selected from the list. + EFFECT: This function selects a clause from the list in a + similar way as the function top_SelectMinimalWeightClause. + The only difference is that conjecture clauses are + preferred over axiom clauses, because their weight + is divided by a factor given by the flag 'PrefCon'. +***************************************************************/ +{ + CLAUSE Result; + NAT NewWeight,Weight, NewVars, Vars, Factor; + + Result = (CLAUSE)list_Car(List); + Factor = flag_GetFlagValue(Flags, flag_PREFCON); + Weight = clause_Weight(Result); + if (clause_GetFlag(Result, CONCLAUSE)) + Weight = Weight / Factor; + Vars = clause_NumberOfVarOccs(list_Car(List)); + List = list_Cdr(List); + + while (!list_Empty(List)) { + NewWeight = clause_Weight(list_Car(List)); + if (clause_GetFlag(list_Car(List),CONCLAUSE)) + NewWeight = NewWeight / Factor; + if (NewWeight < Weight) { + Weight = NewWeight; + Result = list_Car(List); + Vars = clause_NumberOfVarOccs(list_Car(List)); + } + else { + if (NewWeight == Weight) { + NewVars = clause_NumberOfVarOccs(list_Car(List)); + if (flag_GetFlagValue(Flags, flag_PREFVAR)) { + if (Vars < NewVars) { + Result = (CLAUSE)list_Car(List); + Weight = NewWeight; + Vars = NewVars; + } + } + else + if (Vars > NewVars) { + Result = (CLAUSE)list_Car(List); + Weight = NewWeight; + Vars = NewVars; + } + } + } + + List = list_Cdr(List); + } + return Result; +} + + +/*static CLAUSE top_SelectClauseDepth(LIST List)*/ +/************************************************************** + INPUT: A list of clauses. + RETURNS: A clause selected from the list. + EFFECT: +***************************************************************/ +/*{ + CLAUSE Result; + int Min, Depth; + + Result = (CLAUSE)list_Car(List); + Depth = clause_Depth(Result); + Min = Depth * clause_Weight(Result); + List = list_Cdr(List); + + if (Depth == 0) + return Result; + + while (!list_Empty(List)) { + Depth = clause_Depth(list_Car(List)); + if (Min > Depth * clause_Weight(list_Car(List))) { + Result = list_Car(List); + if (Depth == 0) + return Result; + Min = clause_Depth(Result) * clause_Weight(Result); + } + List = list_Cdr(List); + } + + return Result; +}*/ + + +static LIST top_GetLiteralsForSplitting(CLAUSE Clause) +/************************************************************** + INPUT: A clause. + RETURNS: A list of succedent literal indices where every single + literal doesn't share any variables with other literals. + If the clause is horn, an empty list is returned. +***************************************************************/ +{ + LIST* Variables; /* An array, mapping literal index to list of variables */ + int i, j; + BOOL Stop; + LIST Failed, Result; + + Result = list_Nil(); + + /* Special case: horn clause */ + if (clause_IsHornClause(Clause)) + return Result; + + /* Special case: clause is ground, so return all succedent literals */ + if (clause_IsGround(Clause)) { + for (i = clause_LastSuccedentLitIndex(Clause); + i >= clause_FirstSuccedentLitIndex(Clause); i--) + Result = list_Cons((POINTER)i, Result); + return Result; + } + + Variables = memory_Malloc(sizeof(LIST) * clause_Length(Clause)); + /* Initialize the array */ + for (i = clause_FirstLitIndex(); i <= clause_LastLitIndex(Clause); i++) + Variables[i] = term_VariableSymbols(clause_GetLiteralAtom(Clause, i)); + + /* <Failed> is the set of literals that share variables with other literals */ + Failed = list_Nil(); + for (i = clause_LastSuccedentLitIndex(Clause); + i >= clause_FirstSuccedentLitIndex(Clause); i--) { + if (list_Empty(Variables[i])) + Result = list_Cons((POINTER)i, Result); + else if (!list_PointerMember(Failed, (POINTER)i)) { + /* We don't know yet whether the literal shares variables */ + Stop = FALSE; + for (j = clause_FirstLitIndex(); + j <= clause_LastLitIndex(Clause) && !Stop; j++) { + if (i != j && list_HasIntersection(Variables[i], Variables[j])) { + Stop = TRUE; /* Literal isn´t candidate for "optimal" splitting */ + Failed = list_Cons((POINTER)i, Failed); + Failed = list_Cons((POINTER)j, Failed); + } + } + if (!Stop) + Result = list_Cons((POINTER)i, Result); + } + } + + /* Cleanup */ + for (i = clause_FirstLitIndex(); i <= clause_LastLitIndex(Clause); i++) + list_Delete(Variables[i]); + memory_Free(Variables, sizeof(LIST) * clause_Length(Clause)); + list_Delete(Failed); + return Result; +} + + +static int top_GetOptimalSplitLiteralIndex(PROOFSEARCH Search, CLAUSE Clause, + BOOL Usables) +/************************************************************** + INPUT: A proofsearch object, a clause and a boolean flag. + RETURNS: The index of the positive literal from <Clause> + with the greatest number of instances (maybe 0) within + the WorkedOff/Usable sets of the proof search object. + The literal mustn't share any variables with other literals. + If the clause doesn't have a suitable literal, a negative + number is returned. + EFFECT: If <Usables> is FALSE, only the number of instances + within the WorkedOff set is considered, otherwise + the number of instances within both clause sets is considered. +***************************************************************/ +{ + LIST SplitLits; + LITERAL Literal; + NAT Count, MaxInstances; + int Result; + + MaxInstances = -1; + SplitLits = top_GetLiteralsForSplitting(Clause); + Result = -1; + + for ( ; !list_Empty(SplitLits); SplitLits = list_Pop(SplitLits)) { + Literal = clause_GetLiteral(Clause, (int)list_Car(SplitLits)); + /* Count the number of instances */ + Count = prfs_GetNumberOfInstances(Search, Literal, Usables); + if (Count > MaxInstances) { + Result = (int)list_Car(SplitLits); + MaxInstances = Count; + } + } + return Result; +} + + +/* EK: hier lassen oder nach search.c oder nach rules-split.c? */ +static CLAUSE top_GetPowerfulSplitClause(PROOFSEARCH Search, BOOL Usables, + int* LitIndex) +/************************************************************** + INPUT: A proofsearch object, a boolean flag and a pointer to a literal + index which is used as return value. + RETURNS: A clause from the usable set that was selected as given clause. + Iff no suitable clause was found NULL is returned and <*LitIndex> + is set to -1. + Iff a suitable clause was found, this clause is returned and + <*LitIndex> is set to the index of the "optimal" literal. + EFFECT: This function selects a clause from the "usable" set and + a literal that are "optimal" for the application of the splitting + rule with respect to the following criteria: + 1) the literal must occur in the succedent of the non-horn clause, + 2) the literal mustn't share any variables with other literals, + 3) the clause must have a solved constraint, + 4) the atom must have the maximum number of instances + a) within the set of "workedoff" clauses, iff <Usables>=FALSE + b) within the set of "usable" and "workedoff" clauses, + iff "Usables"=TRUE + 5) the atom must have at least one instance in another clause. +***************************************************************/ +{ + LIST Scan, SplitLits; + NAT MaxNrOfInstances, NrOfInstances; + CLAUSE Clause, OptimalClause; + TERM Atom; + SHARED_INDEX WOIndex, UsIndex; + + OptimalClause = NULL; + *LitIndex = -1; + MaxNrOfInstances = 0; + WOIndex = prfs_WorkedOffSharingIndex(Search); + UsIndex = prfs_UsableSharingIndex(Search); + + /* Prepare the term stamp */ + if (term_StampOverflow(sharing_StampID(WOIndex))) + sharing_ResetAllTermStamps(WOIndex); + if (Usables && term_StampOverflow(sharing_StampID(UsIndex))) + sharing_ResetAllTermStamps(UsIndex); + term_StartStamp(); + + for (Scan = prfs_UsableClauses(Search); !list_Empty(Scan); + Scan = list_Cdr(Scan)) { + Clause = list_Car(Scan); + if (clause_HasSolvedConstraint(Clause) && !clause_IsHornClause(Clause)) { + /* Get a list of splittable literal indices */ + SplitLits = top_GetLiteralsForSplitting(Clause); + for ( ; !list_Empty(SplitLits); SplitLits = list_Pop(SplitLits)) { + LITERAL Literal; + + Literal = clause_GetLiteral(Clause, (int)list_Car(SplitLits)); + Atom = clause_LiteralAtom(Literal); + if (!term_AlreadyVisited(Atom)) { + /* Don't visit atom more than once */ + term_SetTermStamp(Atom); + /* Count the number of instances */ + NrOfInstances = prfs_GetNumberOfInstances(Search, Literal, Usables); + if (NrOfInstances > MaxNrOfInstances || OptimalClause == NULL || + (NrOfInstances == MaxNrOfInstances && + /* Prefer shorter clauses for splitting! */ + clause_Length(Clause) < clause_Length(OptimalClause))) { + OptimalClause = Clause; + MaxNrOfInstances = NrOfInstances; + *LitIndex = (int)list_Car(SplitLits); + } + } + } + } + } + term_StopStamp(); + + /* The splittable literal must have at least one instance to be useful */ + /* reducing other clauses. If <Usables> is TRUE, the literal must even */ + /* have two instances, since the literal of the given clause is in the */ + /* usable index, too. */ + if (MaxNrOfInstances == 0 || (Usables && MaxNrOfInstances == 1)) { + *LitIndex = -1; + OptimalClause = NULL; + } + + return OptimalClause; +} + + +static LIST top_FullReductionSelectGivenComputeDerivables(PROOFSEARCH Search, + CLAUSE *SplitClause, + int *Counter) +/************************************************************** + INPUT: A proof search object, a pointer to a clause resulting from a + previous splitting step, and a pointer to an integer counter. + RETURNS: A list of derived clauses. + EFFECT: In this function a clause is selected from the set of + "usable" clauses. After a clause was selected as "given clause", + inferences between the given clause and the "worked off" clauses + are made. The selection works as follows: + 1) If <*SplitClause> is not NULL, the split clause + is selected as "given clause". <*SplitClause> should result + from splitting + 2) If <*SplitClause> is NULL, we try to find a clause that is + "optimal" for splitting. This is done by selecting a literal + <L> in a clause, such that <L> is variable-disjoint from + the rest of the clause, and the atom of <L> has the maximum + number of instances within the set of "usable" and "workoff" + clauses. + 3) If the previous steps failed, a clause is selected by weight + or by depth, depending on the parameters "WDRatio", "PrefVar" + and "PrefCon". Then splitting is tried on the selected clause. + If the clause is a non-horn clause, we try to find a positive + literal <L> and a set of negative literals <N>, such that <N> + and <L> are variable disjoint from the rest of the clause. +***************************************************************/ +{ + CLAUSE GivenClause, TerminatorClause; + LIST Derivables, SplitLits; + FLAGSTORE Flags; + PRECEDENCE Precedence; + int LitIndex; + + GivenClause = NULL; + Derivables = list_Nil(); + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + /* 1) If the last given clause was split or if backtracking was applied, */ + /* then choose the clause resulting from the splitting step as */ + /* given clause. */ + /* ATTENTION: Since the <SplitClause> might have been reduced since */ + /* the time the variable was set, we have to check whether */ + /* <SplitClause> is still element of the set of usable clauses. */ + if (*SplitClause != NULL && + list_PointerMember(prfs_UsableClauses(Search), *SplitClause)) + GivenClause = *SplitClause; + + *SplitClause = NULL; + + if (GivenClause == NULL) { + if (prfs_SplitCounter(Search) != 0) + /* 2) Try to find an "optimal" splitting clause, that doesn't share */ + /* variables with any other literal. */ + GivenClause = top_GetPowerfulSplitClause(Search, FALSE, &LitIndex); + + if (GivenClause != NULL) { + /* Found "optimal" split clause, so apply splitting */ + SplitLits = list_List(clause_GetLiteral(GivenClause, LitIndex)); + *SplitClause = prfs_DoSplitting(Search, GivenClause, SplitLits); + list_Delete(SplitLits); + } else { + /* 3) Splitting wasn't applied, so use the other strategies */ + if ((*Counter) % flag_GetFlagValue(Flags, flag_WDRATIO) == 0) + GivenClause = top_SelectClauseDepth(prfs_UsableClauses(Search), Flags); + else { + if (flag_GetFlagValue(Flags, flag_PREFCON) != flag_PREFCONUNCHANGED) + GivenClause = top_SelectMinimalConWeightClause(prfs_UsableClauses(Search), + Flags); + else + GivenClause = top_SelectMinimalWeightClause(prfs_UsableClauses(Search), + Flags); + } + (*Counter)++; /* EK: hier lassen, oder eine Klammerebene nach aussen? */ + } + } + + if (*SplitClause == NULL && prfs_SplitCounter(Search) != 0) { + /* Try to find the "optimal" literal for splitting the clause. */ + /* This makes sense for a clause that is the right part of a */ + /* splitting step. */ + LitIndex = top_GetOptimalSplitLiteralIndex(Search, GivenClause, FALSE); + if (LitIndex >= 0) { + SplitLits = list_List(clause_GetLiteral(GivenClause, LitIndex)); + *SplitClause = prfs_DoSplitting(Search, GivenClause, SplitLits); + list_Delete(SplitLits); + } else { + /* Optimal splitting wasn't possible, so try the old-style splitting. */ + /* Here a split is done if a positive literal doesn't share variables */ + /* with another POSITIVE literal. */ + *SplitClause = prfs_PerformSplitting(Search, GivenClause); + } + } + + prfs_ExtractUsable(Search, GivenClause); + + if (flag_GetFlagValue(Flags, flag_PGIVEN)) { + fputs("\n\tGiven clause: ", stdout); + clause_Print(GivenClause); + fflush(stdout); + } + + if (*SplitClause != NULL) + Derivables = list_List(*SplitClause); + else { + /* No splitting was applied */ + if (flag_GetFlagValue(Flags, flag_RTER) != flag_RTEROFF) { + clock_StartCounter(clock_REDUCTION); + TerminatorClause = red_Terminator(GivenClause, + flag_GetFlagValue(Flags, flag_RTER), + prfs_WorkedOffSharingIndex(Search), + prfs_UsableSharingIndex(Search), Flags, + Precedence); + clock_StopAddPassedTime(clock_REDUCTION); + + if (TerminatorClause != NULL) { + /* An empty clause was derived by the "terminator" rule */ + Derivables = list_List(TerminatorClause); + prfs_InsertUsableClause(Search, GivenClause); + } + } + if (list_Empty(Derivables)) { + /* No splitting was applied, no empty clause was found by terminator */ + clause_SelectLiteral(GivenClause, Flags); + /*clause_SetSpecialFlags(GivenClause,ana_SortDecreasing());*/ + prfs_InsertWorkedOffClause(Search, GivenClause); + clock_StartCounter(clock_INFERENCE); + Derivables = inf_DerivableClauses(Search, GivenClause); + clock_StopAddPassedTime(clock_INFERENCE); + } + } + + prfs_IncDerivedClauses(Search, list_Length(Derivables)); + + return Derivables; +} + + +static LIST top_LazyReductionSelectGivenComputeDerivables(PROOFSEARCH Search, + CLAUSE *SplitClause, + int *Counter) +/************************************************************** + INPUT: A proof search object, a pointer to a clause resulting from a + previous splitting step, and a pointer to an integer counter. + RETURNS: A list of derived clauses. + EFFECT: In this function a clause is selected from the set of + "usable" clauses. After a clause was selected as "given clause", + inferences between the given clause and the "worked off" clauses + are made. Take a look at the description of the function + top_FullReduction... for more details. + This function is more complicated than the other function, + since clauses in the set of usable clauses may be reducible. + Because of this fact, the selection of the given clause + has to be done in a loop. After picking a "candidate" clause + the clause is inter-reduced with the "worked off" set. + If the candidate still exists after the reduction it is + selected as given clause, else another usable clause is picked + as candidate. +***************************************************************/ +{ + CLAUSE GivenClause, TerminatorClause; + LIST Derivables; + FLAGSTORE Flags; + PRECEDENCE Precedence; + int LitIndex; + + GivenClause = (CLAUSE)NULL; + TerminatorClause = (CLAUSE)NULL; + Derivables = list_Nil(); + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + + while (GivenClause == (CLAUSE)NULL && + !list_Empty(prfs_UsableClauses(Search))) { + /* The selected clause may be redundant */ + + if (*SplitClause != NULL && + list_PointerMember(prfs_UsableClauses(Search), *SplitClause)) + GivenClause = *SplitClause; + + *SplitClause = NULL; + + /* Try selecting a clause that is optimal for splitting */ + if (GivenClause == NULL) { + if (prfs_SplitCounter(Search) != 0) { + GivenClause = top_GetPowerfulSplitClause(Search, FALSE, &LitIndex); + /* The value of <LitIndex> isn't used here. */ + } + + if (GivenClause == NULL) { + /* No optimal clause for splitting found */ + if ((*Counter) % flag_GetFlagValue(Flags, flag_WDRATIO) == 0) + GivenClause = top_SelectClauseDepth(prfs_UsableClauses(Search), Flags); + else { + if (flag_GetFlagValue(Flags, flag_PREFCON) != flag_PREFCONUNCHANGED) + GivenClause = top_SelectMinimalConWeightClause(prfs_UsableClauses(Search), + Flags); + else + GivenClause = top_SelectMinimalWeightClause(prfs_UsableClauses(Search), + Flags); + } + (*Counter)++; + } + } + prfs_ExtractUsable(Search, GivenClause); + + /* Reduce the selected clause */ + clock_StartCounter(clock_REDUCTION); + GivenClause = red_CompleteReductionOnDerivedClause(Search, GivenClause, + red_WORKEDOFF); + clock_StopAddPassedTime(clock_REDUCTION); + } + + if (GivenClause == (CLAUSE)NULL) + /* Set of usable clauses is empty */ + return list_Nil(); + + + if (clause_IsEmptyClause(GivenClause)) { + Derivables = list_List(GivenClause); + return Derivables; + } + else { + /* Reduce Workedoff clauses with selected clause */ + clock_StartCounter(clock_REDUCTION); + Derivables = red_BackReduction(Search, GivenClause, red_WORKEDOFF); + clock_StopAddPassedTime(clock_REDUCTION); + } + + /* Print selected clause */ + if (flag_GetFlagValue(Flags, flag_PGIVEN)) { + fputs("\n\tGiven clause: ", stdout); + clause_Print(GivenClause); + fflush(stdout); + } + + /* Try splitting */ + if (prfs_SplitCounter(Search) != 0) { + /* First try "optimal" splitting on the selected clause */ + LitIndex = top_GetOptimalSplitLiteralIndex(Search, GivenClause, FALSE); + + if (LitIndex >= 0) { + LIST SplitLits; + + SplitLits = list_List(clause_GetLiteral(GivenClause, LitIndex)); + *SplitClause = prfs_DoSplitting(Search, GivenClause, SplitLits); + list_Delete(SplitLits); + } else { + /* Try the old splitting that allows negative literals */ + /* sharing variables with the selected positive literal. */ + *SplitClause = prfs_PerformSplitting(Search, GivenClause); + } + } + + if (*SplitClause != NULL) { + Derivables = list_Cons(*SplitClause, Derivables); + } else { + /* Try terminator reduction only for a clause that wasn't splitted. */ + if (flag_GetFlagValue(Flags, flag_RTER) != flag_RTEROFF) { + TerminatorClause = red_Terminator(GivenClause, + flag_GetFlagValue(Flags, flag_RTER), + prfs_WorkedOffSharingIndex(Search), + prfs_UsableSharingIndex(Search), + Flags, Precedence); + if (TerminatorClause != NULL) { + Derivables = list_Cons(TerminatorClause, Derivables); + prfs_InsertUsableClause(Search, GivenClause); + } + } + if (TerminatorClause == (CLAUSE)NULL) { + clause_SelectLiteral(GivenClause, Flags); + /* clause_SetSpecialFlags(GivenClause,ana_SortDecreasing());*/ + prfs_InsertWorkedOffClause(Search, GivenClause); + clock_StartCounter(clock_INFERENCE); + Derivables = list_Nconc(Derivables, + inf_DerivableClauses(Search, GivenClause)); + clock_StopAddPassedTime(clock_INFERENCE); + } + } + + prfs_IncDerivedClauses(Search, list_Length(Derivables)); + + return Derivables; +} + + +static PROOFSEARCH top_ProofSearch(PROOFSEARCH Search, LIST ProblemClauses, + FLAGSTORE InputFlags, LIST UserPrecedence, int *BoundApplied) +/************************************************************** + INPUT: A proof search object, a list of clauses, a flag store + containing the flags from the command line and from + the input file, a list containing the precedence as + specified by the user, and a pointer to an integer. + RETURNS: The same proof search object + EFFECTS: +***************************************************************/ +{ + LIST Scan,EmptyClauses,Derivables; + LIST UsedEmptyClauses; + CLAUSE SplitClause,HighestLevelEmptyClause; + FLAGSTORE Flags; + PRECEDENCE Precedence; + int Counter, ActBound, BoundMode, BoundLoops; + + HighestLevelEmptyClause = (CLAUSE)NULL; + UsedEmptyClauses = list_Nil(); + EmptyClauses = list_Nil(); + Derivables = list_Nil(); + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + Counter = 1; + + clock_InitCounter(clock_REDUCTION); + clock_InitCounter(clock_BACKTRACK); + clock_InitCounter(clock_INFERENCE); + + /* Important ! Recomputes Weight ! */ + ana_AnalyzeProblem(Search, ProblemClauses); + if (flag_GetFlagValue(Flags, flag_AUTO)) { + prfs_InstallFiniteMonadicPredicates(Search, ProblemClauses, ana_FinMonPredList()); + ana_AutoConfiguration(ProblemClauses, Flags, Precedence); + /* File and input flags have higher precedence */ + flag_TransferSetFlags(InputFlags, Flags); + } + + /* Rearrange automatically determined precedence according to user's specification. */ + symbol_RearrangePrecedence(Precedence, UserPrecedence); + + for (Scan = ProblemClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) + clause_OrientAndReInit(list_Car(Scan), Flags, Precedence); + + /* Must be called after ana_AnalyzeProblem and Reorientation */ + ana_AnalyzeSortStructure(ProblemClauses, Flags, Precedence); + + if (flag_GetFlagValue(Flags, flag_AUTO)) { + ana_ExploitSortAnalysis(Flags); + /* File and input flags have higher precedence */ + flag_TransferSetFlags(InputFlags, Flags); + } + prfs_SetSplitCounter(Search, flag_GetFlagValue(Flags, flag_SPLITS)); + + ActBound = flag_GetFlagValue(Flags, flag_BOUNDSTART); + BoundMode = flag_GetFlagValue(Flags, flag_BOUNDMODE); + BoundLoops = flag_GetFlagValue(Flags, flag_BOUNDLOOPS); + *BoundApplied = -1; + + if (flag_GetFlagValue(Flags, flag_PPROBLEM)) { + puts(""); + puts("--------------------------SPASS-START-----------------------------"); + puts("Input Problem:"); + clause_ListPrint(ProblemClauses); + ana_Print(Flags, Precedence); + } + + if (flag_GetFlagValue(Flags, flag_SORTS) != flag_SORTSOFF) { + BOOL Strong; + Strong = (flag_GetFlagValue(Flags, flag_SORTS) == flag_SORTSMONADICALL); + for (Scan = ProblemClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) + clause_SetSortConstraint((CLAUSE)list_Car(Scan),Strong,Flags, Precedence); + } + + if (flag_GetFlagValue(Flags, flag_RINPUT)) { + clock_StartCounter(clock_REDUCTION); + EmptyClauses = red_ReduceInput(Search, ProblemClauses); + clock_StopAddPassedTime(clock_REDUCTION); + if (list_Empty(EmptyClauses) && flag_GetFlagValue(Flags, flag_SATINPUT)) + EmptyClauses = red_SatInput(Search); + } + else { + for (Scan=ProblemClauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) + prfs_InsertUsableClause(Search, list_Car(Scan)); + } + Derivables = list_Nil(); + + if (ana_SortRestrictions() || + (ana_UnsolvedSortRestrictions() && + flag_GetFlagValue(Flags,flag_SORTS) == flag_SORTSMONADICALL)) { + if (flag_GetFlagValue(Flags, flag_RSST)) + prfs_SetStaticSortTheory(Search,sort_ApproxStaticSortTheory(prfs_UsableClauses(Search),Flags,Precedence)); + prfs_SetDynamicSortTheory(Search,sort_TheoryCreate()); + } + + /* Fix literal order in clauses in the usable set. + Since they are shared, we have to extract them from + the sharing before fixing them. Afterwards, we have to + insert them in the sharing again. + */ + for (Scan = prfs_UsableClauses(Search); + !list_Empty(Scan); + Scan = list_Cdr(Scan)) { + CLAUSE clause; + clause = list_Car(Scan); + clause_MakeUnshared(clause,prfs_UsableSharingIndex(Search)); + clause_FixLiteralOrder(clause, Flags, Precedence); + clause_InsertIntoSharing(clause, prfs_UsableSharingIndex(Search), + prfs_Store(Search), prfs_Precedence(Search)); + } + + /* Calculate the frequency counts for the symbols in the usable set. */ + for (Scan = prfs_UsableClauses(Search); + !list_Empty(Scan); + Scan = list_Cdr(Scan)) { + CLAUSE clause; + clause = list_Car(Scan); + + clause_CountSymbols(clause); + } + + /* Sort usable set. */ + prfs_SetUsableClauses(Search, + list_Sort(prfs_UsableClauses(Search), + (BOOL (*) (void *, void *)) clause_CompareAbstractLEQ)); + + if (flag_GetFlagValue(Flags, flag_SOS)) { + Derivables = list_Copy(prfs_UsableClauses(Search)); + for (Scan=Derivables;!list_Empty(Scan);Scan=list_Cdr(Scan)) + if (!clause_GetFlag(list_Car(Scan), CONCLAUSE)) + prfs_MoveUsableWorkedOff(Search,list_Car(Scan)); + list_Delete(Derivables); + } + + if (flag_GetFlagValue(Flags, flag_PPROBLEM)) { + puts("\nProcessed Problem:"); + puts("\nWorked Off Clauses:"); + clause_ListPrint(prfs_WorkedOffClauses(Search)); + puts("\nUsable Clauses:"); + clause_ListPrint(prfs_UsableClauses(Search)); + } + + while ((list_Empty(EmptyClauses) || !prfs_SplitStackEmpty(Search)) && + prfs_Loops(Search) != 0 && + ((*BoundApplied != -1) || !list_Empty(prfs_UsableClauses(Search))) && + (flag_GetFlagValue(Flags,flag_TIMELIMIT) == flag_TIMELIMITUNLIMITED || + flag_GetFlagValue(Flags,flag_TIMELIMIT) > clock_GetSeconds(clock_OVERALL))) { + + Derivables = list_Nil(); + SplitClause = (CLAUSE)NULL; + *BoundApplied = -1; + + while ((list_Empty(EmptyClauses) || !prfs_SplitStackEmpty(Search)) && + prfs_Loops(Search) != 0 && + (!list_Empty(prfs_UsableClauses(Search)) || !list_Empty(EmptyClauses)) && + (flag_GetFlagValue(Flags,flag_TIMELIMIT) == flag_TIMELIMITUNLIMITED || + flag_GetFlagValue(Flags,flag_TIMELIMIT) > clock_GetSeconds(clock_OVERALL))) { + + if (!list_Empty(EmptyClauses)) { + /* Backtracking */ + clock_StartCounter(clock_BACKTRACK); + Derivables = split_Backtrack(Search, HighestLevelEmptyClause, + &SplitClause); + clock_StopAddPassedTime(clock_BACKTRACK); + prfs_IncBacktrackedClauses(Search, list_Length(Derivables)); + + if (prfs_SplitStackEmpty(Search)) + Derivables = list_Nconc(EmptyClauses, Derivables); + else { + for ( ; !list_Empty(EmptyClauses); EmptyClauses = list_Pop(EmptyClauses)) + if (list_Car(EmptyClauses) != HighestLevelEmptyClause) + clause_Delete(list_Car(EmptyClauses)); + prfs_InsertDocProofClause(Search, HighestLevelEmptyClause); + /* Keep HighestLevelEmptyClause for finding the terms required */ + /* for the proof. */ + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) + UsedEmptyClauses = list_Cons(HighestLevelEmptyClause, UsedEmptyClauses); + if (flag_GetFlagValue(Flags, flag_DOCSPLIT)) + printf("\n\t Split Backtracking level %d:",prfs_ValidLevel(Search)); + } + EmptyClauses = list_Nil(); + HighestLevelEmptyClause = (CLAUSE)NULL; + } + else { /* no empty clause found */ + +#ifdef CHECK + if (!prfs_Check(Search)) { + misc_StartErrorReport(); + misc_ErrorReport("\n In top_ProofSearch: Illegal state of search in SPASS.\n"); + misc_FinishErrorReport(); + } + if (!ana_Equations()) + red_CheckSplitSubsumptionCondition(Search); +#endif + + if (flag_GetFlagValue(Flags, flag_FULLRED)) + Derivables = top_FullReductionSelectGivenComputeDerivables(Search, &SplitClause, &Counter); + else + Derivables = top_LazyReductionSelectGivenComputeDerivables(Search, &SplitClause, &Counter); + } + + /* Print the derived clauses, if required */ + if (flag_GetFlagValue(Flags, flag_PDER)) + for (Scan=Derivables; !list_Empty(Scan); Scan=list_Cdr(Scan)) { + fputs("\nDerived: ", stdout); + clause_Print(list_Car(Scan)); + } + + /* Partition the derived clauses into empty and non-empty clauses */ + Derivables = split_ExtractEmptyClauses(Derivables, &EmptyClauses); + + /* Apply reduction rules */ + clock_StartCounter(clock_REDUCTION); + if (flag_GetFlagValue(Flags, flag_FULLRED)) { + EmptyClauses = + list_Nconc(EmptyClauses, + red_CompleteReductionOnDerivedClauses(Search, Derivables, + red_ALL, ActBound, + BoundMode, + BoundApplied)); + } else { + EmptyClauses = + list_Nconc(EmptyClauses, + red_CompleteReductionOnDerivedClauses(Search, Derivables, + red_WORKEDOFF, + ActBound, BoundMode, + BoundApplied)); + } + clock_StopAddPassedTime(clock_REDUCTION); + + + if (!list_Empty(EmptyClauses)) { + HighestLevelEmptyClause = split_SmallestSplitLevelClause(EmptyClauses); + if (flag_GetFlagValue(Flags, flag_PEMPTYCLAUSE)) { + fputs("\nEmptyClause: ", stdout); + clause_Print(HighestLevelEmptyClause); + } + } + prfs_DecLoops(Search); + } + + if (ActBound != flag_BOUNDSTARTUNLIMITED && + BoundMode != flag_BOUNDMODEUNLIMITED) { + BoundLoops--; + if (BoundLoops == flag_BOUNDLOOPSMIN) + ActBound = flag_BOUNDSTARTUNLIMITED; + else + ActBound = *BoundApplied; + if (*BoundApplied != -1) { + prfs_SwapIndexes(Search); + if (flag_GetFlagValue(Flags,flag_PBINC)) + printf("\n\n\t ---- New Clause %s Bound: %2d ----\n", + (BoundMode==flag_BOUNDMODERESTRICTEDBYDEPTH) ? "Term Depth" : "Weight",ActBound); + } + } + } + prfs_SetEmptyClauses(Search, EmptyClauses); + prfs_SetUsedEmptyClauses(Search, UsedEmptyClauses); + + return Search; +} + + +static void top_Flotter(int argc, const char* argv[], LIST InputClauses) +/************************************************************** + INPUT: + RETURNS: Nothing. + EFFECT: +***************************************************************/ +{ + FILE *Output; + char *description; + const char *creator = "\n\tCNF generated by FLOTTER " misc_VERSION " *}"; + int size; + int creator_size; + + if (argc < opts_Indicator()+2) + Output = stdout; + else + Output = misc_OpenFile(argv[opts_Indicator()+1],"w"); + + creator_size = (int)strlen(creator); + size = (int)strlen(dfg_ProblemDescription()) + creator_size; + description = (char*)memory_Malloc(sizeof(char)*size); + strncpy(description,dfg_ProblemDescription(),size-creator_size-3); + strcpy(description+size-creator_size-3, creator); + + + clause_FPrintCnfDFGProblem(Output, dfg_ProblemName(), dfg_ProblemAuthor(), + dfg_ProblemStatusString(), description, InputClauses); + + fputs("\nFLOTTER needed\t", stdout); + clock_PrintTime(clock_INPUT); + puts(" for the input."); + fputs("\t\t", stdout); + clock_PrintTime(clock_CNF); + fputs(" for the CNF translation.", stdout); + + + if (Output != stdout) + misc_CloseFile(Output,argv[opts_Indicator()+1]); + memory_Free(description, sizeof(char)*size); +} + +static BOOL top_CalledFlotter(const char* Call) +{ + int length; + length = strlen(Call); + return string_Equal((Call + (length > 7 ? length - 7 : 0)), "FLOTTER"); +} + + + +/**************************************************************/ +/* Main Function */ +/**************************************************************/ + +int main(int argc, const char* argv[]) +{ + LIST InputClauses,Scan,Axioms,Conjectures, Sorts, QueryClauses, + LabelClauses, QueryPair, ProblemClauses, Labellist, Sortlabellist, + Symblist, UserPrecedence; + PROOFSEARCH Search, FlotterSearch; + /* <InputFlags> are the flags from the problem file and the command line. */ + FLAGSTORE InputFlags, Flags; + /* <InputPrecedence> is the precedence after reading the problem file. */ + PRECEDENCE InputPrecedence, Precedence; + FILE* InputStream; + HASH TermLabelToClauselist, ClauseToTermLabellist; + top_SEARCHRESULT Result; + + Search = (PROOFSEARCH)NULL; + +#if (defined(SPASS_SIGNALS)) + top_PROOFSEARCH = &Search; + signal(SIGINT, top_SigHandler); + signal(SIGTERM, top_SigHandler); + signal(SIGSEGV, top_SigHandler); + signal(SIGBUS, top_SigHandler); +#endif + + clock_Init(); + clock_StartCounter(clock_OVERALL); + memory_Init(memory__UNLIMITED); + atexit(memory_FreeAllMem); + symbol_Init(TRUE); + stack_Init(); + hash_Init(); + sort_Init(); + term_Init(); + + InputPrecedence = symbol_CreatePrecedence(); + fol_Init(TRUE, InputPrecedence); + cont_Init(); + unify_Init(); + flag_Init(); + subs_Init(); + clause_Init(); + red_Init(); + ren_Init(); + dp_Init(); + opts_Init(); + ana_Init(); + cc_Init(); + + /* Build proof search object to store definitions in */ + Search = prfs_Create(); + InputFlags = flag_CreateStore(); + + /* declare all options */ + opts_DeclareSPASSFlagsAsOptions(); + top_RemoveFileOptId = opts_Declare("rf", opts_NOARGTYPE); + + if (!opts_Read(argc, argv)) + return EXIT_FAILURE; + + /* Check whether flag_STDIN is set in the command line */ + flag_InitStoreByDefaults(InputFlags); + opts_SetFlags(InputFlags); + + if (argc < opts_Indicator()+1 && !flag_GetFlagValue(InputFlags,flag_STDIN)) { + /* No input file, no stdin input */ + printf("\n\t %s %s",argv[0],misc_VERSION); + if (top_CalledFlotter(argv[0]) || + flag_GetFlagValue(InputFlags, flag_FLOTTER)) + puts("\n\t Usage: FLOTTER [options] [<input-file>] [<output-file>]\n"); + else + puts("\n\t Usage: SPASS [options] [<input-file>] \n"); + puts("Possible options:\n"); + opts_PrintSPASSNames(); + return EXIT_FAILURE; + } + FlotterSearch = NULL; + + Axioms = Conjectures = Sorts = Labellist = Sortlabellist = UserPrecedence = list_Nil(); + + if (flag_GetFlagValue(InputFlags, flag_STDIN)) { + top_InputFile = (char*)NULL; + InputStream = stdin; + } else { + top_InputFile = argv[opts_Indicator()]; + InputStream = misc_OpenFile(top_InputFile, "r"); + } + + clock_StartCounter(clock_INPUT); + flag_CleanStore(InputFlags); /* Mark all flags as unset */ + + /* Now add flags from file to InputFlags and set precedence */ + InputClauses = dfg_DFGParser(InputStream, InputFlags, InputPrecedence, &Axioms, + &Conjectures, &Sorts, &UserPrecedence); + + /* Add/overwrite with command line flags */ + opts_SetFlags(InputFlags); + Flags = prfs_Store(Search); + Precedence = prfs_Precedence(Search); + /* The Flags were initialized with the default flag values. */ + /* This values are now overwritten by command line flags and flags */ + /* from the input file. */ + flag_TransferSetFlags(InputFlags, Flags); + /* From now on the input flags are not changed! */ + + /* Transfer input precedence to search object */ + symbol_TransferPrecedence(InputPrecedence, Precedence); + + + /* Complain about missing input clauses/formulae when in */ + /* non-interactive mode */ + if (!flag_GetFlagValue(Flags, flag_INTERACTIVE) && list_Empty(Axioms) && + list_Empty(Conjectures) && list_Empty(InputClauses)) { + misc_StartUserErrorReport(); + misc_UserErrorReport("\n No formulae and clauses found in input file!\n"); + misc_FinishUserErrorReport(); + } + + cnf_Init(Flags); /* Depends on Strong Skolemization Flag */ + + /* DocProof is required for interactive mode */ + if (flag_GetFlagValue(Flags, flag_INTERACTIVE)) { + flag_SetFlagValue(Flags, flag_DOCPROOF, flag_DOCPROOFON); + } + + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) + prfs_AddDocProofSharingIndex(Search); + + /* Create necessary hasharrays */ + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) { + TermLabelToClauselist = hsh_Create(); + ClauseToTermLabellist = hsh_Create(); + } + else { + TermLabelToClauselist = NULL; + ClauseToTermLabellist = NULL; + } + + /* Build conjecture formula and negate it: Conjectures are taken disjunctively!!*/ + for (Scan = Conjectures; !list_Empty(Scan); Scan = list_Cdr(Scan)) + list_Rplacd(list_Car(Scan), (LIST)term_Create(fol_Not(), + list_List(list_PairSecond(list_Car(Scan))))); + + clock_StopPassedTime(clock_INPUT); + + if (top_InputFile) { + misc_CloseFile(InputStream,top_InputFile); + if (opts_IsSet(top_RemoveFileOptId)) + remove(top_InputFile); + } + + clock_StartCounter(clock_CNF); + + if (list_Empty(InputClauses)) { + NAT Termcount; + + Termcount = 0; + + /* Create labels for formulae without them */ + for (Scan = Axioms; !list_Empty(Scan); Scan = list_Cdr(Scan), Termcount++) { + if (list_PairFirst(list_Car(Scan)) == NULL) { + char L[100]; + char* Label; + sprintf(L, "axiom%d", Termcount); + Label = string_StringCopy(L); + list_Rplaca(list_Car(Scan), Label); + if (flag_GetFlagValue(Flags, flag_DOCPROOF) && + flag_GetFlagValue(Flags, flag_PLABELS)) { + printf("\nAdded label %s for axiom \n", Label); + fol_PrettyPrintDFG((TERM) list_PairSecond(list_Car(Scan))); + } + } + } + Termcount = 0; + for (Scan = Sorts; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + char L[100]; + char* Label; + sprintf(L, "declaration%d", Termcount); + Label = string_StringCopy(L); + list_Rplaca(list_Car(Scan), Label); + if (flag_GetFlagValue(Flags, flag_DOCPROOF) && + flag_GetFlagValue(Flags, flag_PLABELS)) { + printf("\nAdded label %s for declaration \n", Label); + fol_PrettyPrintDFG((TERM) list_PairSecond(list_Car(Scan))); + } + Sortlabellist = list_Cons(Label, Sortlabellist); + } + Axioms = list_Nconc(Axioms, Sorts); + + + if (flag_GetFlagValue(Flags, flag_APPLYDEFS) != flag_APPLYDEFSOFF) { + def_ExtractDefsFromTermlist(Search, Axioms, Conjectures); + Conjectures = def_ApplyDefinitionToTermList(prfs_Definitions(Search), + Conjectures, Flags, + Precedence); + } + + /* We must keep the list of symbols because they can't be freed in cnf_Flotter */ + Symblist = list_Nil(); + + /* Axioms is list of pairs, conjectures is list of terms */ + /* A ProofSearch object is only returned and the symbols kept in Symblist + if flag_INTERACTIVE is set */ + FlotterSearch = cnf_Flotter(Axioms,Conjectures,&InputClauses, &Labellist, + TermLabelToClauselist, ClauseToTermLabellist, + Flags, Precedence, &Symblist); + + InputClauses = clause_ListSortWeighed(InputClauses); + clause_SetCounter(1); + for (Scan = InputClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) { + clause_NewNumber(list_Car(Scan)); + } + } + else { + dfg_DeleteFormulaPairList(Axioms); + dfg_DeleteFormulaPairList(Sorts); + dfg_DeleteFormulaPairList(Conjectures); + if (flag_GetFlagValue(Flags, flag_APPLYDEFS) != flag_APPLYDEFSOFF) { + /* Extract list of definitions */ + def_ExtractDefsFromClauselist(Search, InputClauses); + def_FlattenDefinitionsDestructive(Search); + for (Scan=prfs_Definitions(Search); !list_Empty(Scan); Scan=list_Cdr(Scan)) + InputClauses = def_ApplyDefToClauselist(Search, (DEF) list_Car(Scan), + InputClauses, TRUE); + } + } + + clock_StopPassedTime(clock_CNF); + + if (top_CalledFlotter(argv[0]) || flag_GetFlagValue(Flags, flag_FLOTTER)) { + top_Flotter(argc,argv,InputClauses); + flag_SetFlagValue(Flags, flag_TIMELIMIT, 0); /* Exit No Output */ + flag_SetFlagValue(Flags, flag_INTERACTIVE, flag_INTERACTIVEOFF); + flag_SetFlagValue(Flags, flag_PPROBLEM, flag_PPROBLEMOFF); + } + + memory_Restrict(flag_GetFlagValue(Flags, flag_MEMORY)); + + do { + LIST deflist; + int BoundApplied; + ProblemClauses = list_Nil(); + LabelClauses = list_Nil(); + Result = top_RESOURCE; + + if (flag_GetFlagValue(Flags, flag_INTERACTIVE)) { + QueryPair = ia_GetNextRequest(InputStream, Flags); + /* A pair (<formula,labellist>) */ + /* Get list of clauses derivable from formulae with labels in labellist */ + if (list_Empty(QueryPair)) { + break; + } + for (Scan=list_PairSecond(QueryPair);!list_Empty(Scan);Scan=list_Cdr(Scan)) { + LIST l; + l = hsh_GetWithCompareFunc(TermLabelToClauselist, list_Car(Scan), + (BOOL (*)(POINTER, POINTER)) cnf_LabelEqual, + (unsigned long (*)(POINTER)) hsh_StringHashKey); + + l = list_PointerDeleteDuplicates(list_Copy(l)); + LabelClauses = list_Nconc(l, LabelClauses); + } + /* Get list of clauses derivable from sorts */ + for (Scan=Sortlabellist; !list_Empty(Scan); Scan=list_Cdr(Scan)) { + LIST l; + l = hsh_GetWithCompareFunc(TermLabelToClauselist, list_Car(Scan), + (BOOL (*)(POINTER, POINTER)) cnf_LabelEqual, + (unsigned long (*)(POINTER)) hsh_StringHashKey); + + l = list_PointerDeleteDuplicates(list_Copy(l)); + LabelClauses = list_Nconc(l, LabelClauses); + } + + /* For labelclauses copies are introduced */ + /* So an update to the clause to term mapping is necessary */ + for (Scan=LabelClauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) { + CLAUSE C; + LIST l; + C = (CLAUSE) list_Car(Scan); + l = list_Copy(hsh_Get(ClauseToTermLabellist, C)); + l = cnf_DeleteDuplicateLabelsFromList(l); + list_Rplaca(Scan, clause_Copy(C)); + hsh_PutList(ClauseToTermLabellist, list_Car(Scan), l); + } + QueryClauses = cnf_QueryFlotter(FlotterSearch, list_PairFirst(QueryPair), + &Symblist); + ProblemClauses = list_Nconc(QueryClauses, LabelClauses); + + for (Scan=list_PairSecond(QueryPair); !list_Empty(Scan); Scan= list_Cdr(Scan)) + string_StringFree(list_Car(Scan)); /* Free the label strings */ + list_Delete(list_PairSecond(QueryPair)); + list_PairFree(QueryPair); + clock_InitCounter(clock_OVERALL); + clock_StartCounter(clock_OVERALL); + } + else { + ProblemClauses = InputClauses; + InputClauses = list_Nil(); + } + + + prfs_SetSplitCounter(Search,flag_GetFlagValue(Flags, flag_SPLITS)); + prfs_SetLoops(Search,flag_GetFlagValue(Flags, flag_LOOPS)); + prfs_SetBacktrackedClauses(Search, 0); + BoundApplied = -1; + Search = top_ProofSearch(Search, ProblemClauses, InputFlags, UserPrecedence, &BoundApplied); + + if ((flag_GetFlagValue(Flags, flag_TIMELIMIT) == flag_TIMELIMITUNLIMITED || + flag_GetFlagValue(Flags, flag_TIMELIMIT) > clock_GetSeconds(clock_OVERALL)) && + prfs_Loops(Search) != 0 && + (BoundApplied == -1 || !list_Empty(prfs_EmptyClauses(Search)))) { + if (list_Empty(prfs_EmptyClauses(Search))) + Result = top_COMPLETION; + else + Result = top_PROOF; + } + + if (flag_GetFlagValue(Flags, flag_TIMELIMIT) != 0) { + /* Stop SPASS immediately */ + printf("\nSPASS %s ", misc_VERSION); + fputs("\nSPASS beiseite: ", stdout); + switch (Result) { + case top_RESOURCE: + if (prfs_Loops(Search) != 0) + fputs("Ran out of time.", stdout); + else + fputs("Maximal number of loops exceeded.", stdout); + break; + case top_PROOF: + fputs("Proof found.", stdout); + break; + default: /* Completion */ + fputs("Completion found.", stdout); + } + printf("\nProblem: %s ", + (top_InputFile != (char*)NULL ? top_InputFile : "Read from stdin.")); + if (flag_GetFlagValue(Flags, flag_PSTATISTIC)) { + clock_StopPassedTime(clock_OVERALL); + printf("\nSPASS derived %d clauses,", prfs_DerivedClauses(Search)); + printf(" backtracked %d clauses", prfs_BacktrackedClauses(Search)); + printf(" and kept %d clauses.", prfs_KeptClauses(Search)); + printf("\nSPASS allocated %lu KBytes.", memory_DemandedBytes()/1024); + fputs("\nSPASS spent\t", stdout); + clock_PrintTime(clock_OVERALL); + fputs(" on the problem.\n\t\t", stdout); + clock_PrintTime(clock_INPUT); + fputs(" for the input.\n\t\t", stdout); + clock_PrintTime(clock_CNF); + fputs(" for the FLOTTER CNF translation.\n\t\t", stdout); + clock_PrintTime(clock_INFERENCE); + fputs(" for inferences.\n\t\t", stdout); + clock_PrintTime(clock_BACKTRACK); + fputs(" for the backtracking.\n\t\t", stdout); + clock_PrintTime(clock_REDUCTION); + puts(" for the reduction."); + } + if (Result != top_PROOF && + flag_GetFlagValue(Flags, flag_FPMODEL) != flag_FPMODELOFF) { + FILE *Output; + char name[100]; + const char * creator = "{*SPASS " misc_VERSION " *}"; + BOOL PrintPotProductive; + + strcpy(name, (top_InputFile != (char*)NULL ? top_InputFile : "SPASS")); + if (Result == top_COMPLETION) + strcat(name, ".model"); + else + strcat(name, ".clauses"); + Output = misc_OpenFile(name,"w"); + PrintPotProductive = (flag_GetFlagValue(Flags, flag_FPMODEL) == + flag_FPMODELPOTENTIALLYPRODUCTIVECLAUSES); + if (Result == top_COMPLETION) + clause_FPrintCnfFormulasDFGProblem(Output, PrintPotProductive, + "{*Completion_by_SPASS*}", + creator, "satisfiable", + dfg_ProblemDescription(), + prfs_WorkedOffClauses(Search), + list_Nil(), Flags, Precedence); + else + clause_FPrintCnfFormulasDFGProblem(Output, PrintPotProductive, + "{*Clauses_generated_by_SPASS*}", + creator, "unknown", + dfg_ProblemDescription(), + prfs_WorkedOffClauses(Search), + prfs_UsableClauses(Search), Flags, + Precedence); + misc_CloseFile(Output, name); + if (Result == top_COMPLETION) + printf("\nCompletion printed to: %s\n", name); + else + printf("\nClauses printed to: %s\n", name); + } + + if (flag_GetFlagValue(Flags, flag_DOCPROOF) && Result != top_RESOURCE) { + if (Result == top_COMPLETION) { + puts("\n\n The saturated set of worked-off clauses is :"); + clause_ListPrint(prfs_WorkedOffClauses(Search)); + } + else { + LIST UsedClauses, UsedTerms; + if (!top_InputFile) + top_InputFile = "SPASS"; + UsedClauses = dp_PrintProof(Search, prfs_EmptyClauses(Search), + top_InputFile); + /* Find terms required for proof */ + UsedTerms = list_Nil(); + + for (Scan = UsedClauses; !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (clause_IsFromInput((CLAUSE) list_Car(Scan))) { + LIST L; + L = hsh_Get(ClauseToTermLabellist, list_Car(Scan)); + L = list_Copy(L); + L = cnf_DeleteDuplicateLabelsFromList(L); + UsedTerms = list_Nconc(UsedTerms, L); + } + list_Delete(UsedClauses); + UsedTerms = cnf_DeleteDuplicateLabelsFromList(UsedTerms); + fputs("\nFormulae used in the proof :", stdout); + for (Scan = UsedTerms; !list_Empty(Scan); Scan = list_Cdr(Scan)) + if (!(strncmp((char*) list_Car(Scan), "_SORT_", 6) == 0)) + printf(" %s", (char*) list_Car(Scan)); + putchar('\n'); + list_Delete(UsedTerms); + } + } + } + + /* Delete mapping for the clause copies of the labelclauses */ + for (Scan = LabelClauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) + hsh_DelItem(ClauseToTermLabellist, list_Car(Scan)); + + list_Delete(ProblemClauses); + + fflush(stdout); + + /* Keep definitions */ + deflist = prfs_Definitions(Search); + prfs_SetDefinitions(Search, list_Nil()); + prfs_Clean(Search); + prfs_SetDefinitions(Search, deflist); + + symbol_TransferPrecedence(InputPrecedence, Precedence); + if (flag_GetFlagValue(Flags, flag_PPROBLEM)) + fputs("\n--------------------------SPASS-STOP------------------------------", stdout); + } while (flag_GetFlagValue(Flags, flag_INTERACTIVE) && + (flag_GetFlagValue(Flags, flag_TIMELIMIT) != 0)); + + for (Scan = InputClauses; !list_Empty(Scan); Scan=list_Cdr(Scan)) + clause_OrientAndReInit(list_Car(Scan), Flags, Precedence); + + /* Cleanup Flotter data structures */ + if (flag_GetFlagValue(Flags, flag_INTERACTIVE)) { + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) + list_Delete(Symblist); + else + symbol_DeleteSymbolList(Symblist); + /* symbol_ResetSkolemIndex(); */ + if (FlotterSearch != NULL) + prfs_Delete(FlotterSearch); + } + if (flag_GetFlagValue(Flags, flag_PFLAGS)) { + putchar('\n'); + flag_Print(Flags); + } + if (flag_GetFlagValue(Flags, flag_DOCPROOF)) { + hsh_Delete(TermLabelToClauselist); + hsh_Delete(ClauseToTermLabellist); + } + for (Scan = Labellist; !list_Empty(Scan); Scan = list_Cdr(Scan)) + string_StringFree(list_Car(Scan)); + list_Delete(Labellist); + list_Delete(Sortlabellist); + list_Delete(UserPrecedence); + + cnf_Free(Flags); + + prfs_Delete(Search); + clause_DeleteClauseList(InputClauses); + flag_DeleteStore(InputFlags); + symbol_DeletePrecedence(InputPrecedence); + + cc_Free(); + ana_Free(); + sort_Free(); + unify_Free(); + cont_Free(); + fol_Free(); + symbol_FreeAllSymbols(); + dfg_Free(); + opts_Free(); +#ifdef CHECK + memory_Print(); + memory_PrintLeaks(); +#endif + putchar('\n'); + return 0; +} diff --git a/test/spass/unify.c b/test/spass/unify.c new file mode 100644 index 0000000000000000000000000000000000000000..14cc7a6a75f5db24d3e6a9890e347be90f9acdcc --- /dev/null +++ b/test/spass/unify.c @@ -0,0 +1,857 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * STANDARD UNIFICATION * */ +/* * * */ +/* * $Module: UNIFY * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "unify.h" + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INITIALIZATION * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +void unify_Init(void) +/********************************************************** + INPUT: None. + RETURNS: None. + EFFECT: Initializes the unify module. +********************************************************/ +{ + +} + +void unify_Free(void) +/********************************************************** + INPUT: None. + RETURNS: None. + EFFECT: Frees internal structures of the unify module. +********************************************************/ +{ + +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * MISC FUNCTIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * OCCUR CHECK * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +BOOL unify_OccurCheckCom(SYMBOL Top, CONTEXT Context, TERM Term) +/********************************************************** + INPUT: A variable symbol, a context, and a term. + RETURNS: TRUE if there is a occur check failure with respect + to the variable symbol <Top> and <Term>. + The search is started in <Term> +***********************************************************/ +{ + int Bottom; + LIST Args; + + Bottom = stack_Bottom(); + + for (;;) { + + if (term_IsVariable(Term)) { + if (symbol_Equal(Top, term_TopSymbol(Term))) { + stack_SetBottom(Bottom); + return TRUE; + } else if (cont_VarIsBound(Context, term_TopSymbol(Term))) { + Term = cont_ContextBindingTerm(Context, term_TopSymbol(Term)); + continue; + } + + } else if (term_IsComplex(Term)) { + + Args = term_ArgumentList(Term); + if (!list_Empty(list_Cdr(Args))) + stack_Push(list_Cdr(Args)); + + Term = list_Car(Args); + continue; + } + + if (stack_Empty(Bottom)) + return FALSE; + else { + Args = (LIST)stack_PopResult(); + Term = list_Car(Args); + if (!list_Empty(list_Cdr(Args))) + stack_Push(list_Cdr(Args)); + } + } +} + + +BOOL unify_OccurCheck(CONTEXT CTop, SYMBOL Top, CONTEXT CTerm, TERM Term) +/********************************************************** + INPUT: A context, a variable symbol, a context, and a term. + RETURNS: TRUE if there is a occur check failure with respect + to the variable symbol <Top> and <Term>. + The search is started in <Term> +***********************************************************/ +{ + int Bottom; + LIST Args; + SYMBOL TermTop; + + Bottom = stack_Bottom(); + + for (;;) { + + if (term_IsVariable(Term)) { + + TermTop = term_TopSymbol(Term); + + if ((CTop == CTerm) && (symbol_Equal(Top, TermTop))) { + stack_SetBottom(Bottom); + return TRUE; + } else if (cont_VarIsBound(CTerm, TermTop)) { + Term = cont_ContextBindingTerm(CTerm, TermTop); + CTerm = cont_ContextBindingContext(CTerm, TermTop); + continue; + } + } else if (term_IsComplex(Term)) { + + Args = term_ArgumentList(Term); + if (!list_Empty(list_Cdr(Args))) { + stack_Push(CTerm); + stack_Push(list_Cdr(Args)); + } + Term = list_Car(Args); + continue; + + } + + if (stack_Empty(Bottom)) + return FALSE; + else { + Args = (LIST)stack_PopResult(); + Term = list_Car(Args); + CTerm = (CONTEXT)stack_Top(); + if (list_Empty(list_Cdr(Args))) + stack_Pop(); + else + stack_Push(list_Cdr(Args)); + } + } +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * UNIFICATION * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +BOOL unify_Unify(CONTEXT CtL, TERM TermL, CONTEXT CtR, TERM TermR) +/********************************************************** + INPUT: Two terms which may contain the same variable symbols. + Equal variable symbols are interpreted different in + <TermL> and <TermR>, respectively. + RETURNS: TRUE, if <TermL> and <TermR> are unifiable, FALSE otherwise. + CAUTION: None. +***********************************************************/ +{ + CONTEXT CHelp; + LIST ArgsL, ArgsR; + int Bottom; + BOOL Bound; + + Bound = FALSE; + Bottom = stack_Bottom(); + + for (;;) { + + while (term_IsVariable(TermL) && + cont_VarIsBound(CtL, term_TopSymbol(TermL))) { + CHelp = cont_ContextBindingContext(CtL, term_TopSymbol(TermL)); + TermL = cont_ContextBindingTerm(CtL, term_TopSymbol(TermL)); + CtL = CHelp; + } + + while (term_IsVariable(TermR) && + cont_VarIsBound(CtR, term_TopSymbol(TermR))) { + CHelp = cont_ContextBindingContext(CtR, term_TopSymbol(TermR)); + TermR = cont_ContextBindingTerm(CtR, term_TopSymbol(TermR)); + CtR = CHelp; + } + + /* Caution: Bindings from variable to variable are made with priority + from the right context into the left context. */ + + if (term_IsVariable(TermL)) { + if (term_IsVariable(TermR)) { + if (!(CtL == CtR && term_EqualTopSymbols(TermL, TermR))) + Bound = cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); + } else if (Bound && unify_OccurCheck(CtL, term_TopSymbol(TermL), CtR, TermR)) { + stack_SetBottom(Bottom); + return FALSE; + } else + Bound = cont_CreateBinding(CtL, term_TopSymbol(TermL), CtR, TermR); + + } else if (term_IsVariable(TermR)) { + if (Bound && unify_OccurCheck(CtR, term_TopSymbol(TermR), CtL, TermL)) { + stack_SetBottom(Bottom); + return FALSE; + } else + Bound = cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); + + } else if (term_EqualTopSymbols(TermL, TermR)) { + if (term_IsComplex(TermL) && TermL != TermR) { + ArgsL = term_ArgumentList(TermL); + ArgsR = term_ArgumentList(TermR); + if (!list_Empty(list_Cdr(ArgsL))) { + stack_Push(CtL); + stack_Push(CtR); + stack_Push(list_Cdr(ArgsL)); + stack_Push(list_Cdr(ArgsR)); + } + TermL = list_Car(ArgsL); + TermR = list_Car(ArgsR); + continue; + } + } else { + stack_SetBottom(Bottom); + return FALSE; + } + + if (stack_Empty(Bottom)) + return TRUE; + else { + ArgsR = stack_PopResult(); + ArgsL = stack_PopResult(); + TermR = list_Car(ArgsR); + TermL = list_Car(ArgsL); + CtR = (CONTEXT)stack_Top(); + CtL = (CONTEXT)stack_NthTop(1); + if (list_Empty(list_Cdr(ArgsL))) + stack_NPop(2); + else { + stack_Push(list_Cdr(ArgsL)); + stack_Push(list_Cdr(ArgsR)); + } + } + } +} + +BOOL unify_UnifyCom(CONTEXT Context, TERM TermL, TERM TermR) +/********************************************************** + INPUT: Two terms which may contain the same variable symbols. + Equal variable symbols are interpreted equally in + <TermL> and <TermR>, respectively. + RETURNS: TRUE, if <TermL> and <TermR> are unifiable, FALSE otherwise. + CAUTION: None. +***********************************************************/ +{ + LIST ArgsL, ArgsR; + int Bottom; + + Bottom = stack_Bottom(); + + for (;;) { + + while (term_IsVariable(TermL) && + cont_VarIsBound(Context, term_TopSymbol(TermL))) + TermL = cont_ContextBindingTerm(Context, term_TopSymbol(TermL)); + + while (term_IsVariable(TermR) && + cont_VarIsBound(Context, term_TopSymbol(TermR))) + TermR = cont_ContextBindingTerm(Context, term_TopSymbol(TermR)); + + if (term_EqualTopSymbols(TermL, TermR)) { + if (term_IsComplex(TermL) && TermL != TermR) { + ArgsL = term_ArgumentList(TermL); + ArgsR = term_ArgumentList(TermR); + if (!list_Empty(list_Cdr(ArgsL))) { + stack_Push(list_Cdr(ArgsL)); + stack_Push(list_Cdr(ArgsR)); + } + TermL = list_Car(ArgsL); + TermR = list_Car(ArgsR); + continue; + } + } else if (term_IsVariable(TermL)) { + if (term_IsVariable(TermR)) + cont_CreateBinding(Context, term_TopSymbol(TermL), Context, TermR); + else if (unify_OccurCheckCom(term_TopSymbol(TermL), Context, TermR)) { + stack_SetBottom(Bottom); + return FALSE; + } else + cont_CreateBinding(Context, term_TopSymbol(TermL), Context, TermR); + + } else if (term_IsVariable(TermR)) { + if (unify_OccurCheckCom(term_TopSymbol(TermR), Context, TermL)) { + stack_SetBottom(Bottom); + return FALSE; + } else + cont_CreateBinding(Context, term_TopSymbol(TermR), Context, TermL); + + } else { + stack_SetBottom(Bottom); + return FALSE; + } + + if (stack_Empty(Bottom)) + return TRUE; + else { + ArgsR = stack_PopResult(); + ArgsL = stack_PopResult(); + TermR = list_Car(ArgsR); + TermL = list_Car(ArgsL); + if (!list_Empty(list_Cdr(ArgsL))) { + stack_Push(list_Cdr(ArgsL)); + stack_Push(list_Cdr(ArgsR)); + } + } + } +} + + + +BOOL unify_UnifyNoOC(CONTEXT CtL, TERM TermL, CONTEXT CtR, TERM TermR) +/********************************************************** + INPUT: Two terms which may contain the same variable symbols. + Equal variable symbols are interpreted different in + <TermL> and <TermR>, respectively. + RETURNS: TRUE, if <TermL> and <TermR> are unifiable, FALSE otherwise. + CAUTION: None. +***********************************************************/ +{ + CONTEXT CHelp; + LIST ArgsL, ArgsR; + int Bottom; + + Bottom = stack_Bottom(); + + for (;;) { + + while (term_IsVariable(TermL) && + cont_VarIsBound(CtL, term_TopSymbol(TermL))) { + CHelp = cont_ContextBindingContext(CtL, term_TopSymbol(TermL)); + TermL = cont_ContextBindingTerm(CtL, term_TopSymbol(TermL)); + CtL = CHelp; + } + + while (term_IsVariable(TermR) && + cont_VarIsBound(CtR, term_TopSymbol(TermR))) { + CHelp = cont_ContextBindingContext(CtR, term_TopSymbol(TermR)); + TermR = cont_ContextBindingTerm(CtR, term_TopSymbol(TermR)); + CtR = CHelp; + } + + /* Caution: Bindings from variable to variable are made with priority + from the right context into the left context. */ + + if (term_IsVariable(TermL)) { + if (term_IsVariable(TermR)) { + if (!(CtL == CtR && term_EqualTopSymbols(TermL, TermR))) + cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); + } else + cont_CreateBinding(CtL, term_TopSymbol(TermL), CtR, TermR); + + } else if (term_IsVariable(TermR)) + cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); + + else if (term_EqualTopSymbols(TermL, TermR)) { + if (term_IsComplex(TermL) && TermL != TermR) { + ArgsL = term_ArgumentList(TermL); + ArgsR = term_ArgumentList(TermR); + if (!list_Empty(list_Cdr(ArgsL))) { + stack_Push(CtL); + stack_Push(CtR); + stack_Push(list_Cdr(ArgsL)); + stack_Push(list_Cdr(ArgsR)); + } + TermL = list_Car(ArgsL); + TermR = list_Car(ArgsR); + continue; + } + } else { + stack_SetBottom(Bottom); + return FALSE; + } + + if (stack_Empty(Bottom)) + return TRUE; + else { + ArgsR = stack_PopResult(); + ArgsL = stack_PopResult(); + TermR = list_Car(ArgsR); + TermL = list_Car(ArgsL); + CtR = (CONTEXT) stack_Top(); + CtL = (CONTEXT) stack_NthTop(1); + if (list_Empty(list_Cdr(ArgsL))) + stack_NPop(2); + else { + stack_Push(list_Cdr(ArgsL)); + stack_Push(list_Cdr(ArgsR)); + } + } + } +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * UNIFICATION WITH FULL OCCUR CHECK (recursive) * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +BOOL unify_UnifyAllOC(CONTEXT IndexContext, CONTEXT CtL, TERM TermL, CONTEXT CtR, TERM TermR) +{ + while (term_IsVariable(TermL)) { + SYMBOL TermTop; + + TermTop = term_TopSymbol(TermL); + + if (cont_VarIsBound(CtL, TermTop)) { + CONTEXT CHelp; + + CHelp = cont_ContextBindingContext(CtL, TermTop); + TermL = cont_ContextBindingTerm(CtL, TermTop); + CtL = CHelp; + } else + break; + } + + while (term_IsVariable(TermR)) { + SYMBOL TermTop; + + TermTop = term_TopSymbol(TermR); + + if (cont_VarIsBound(CtR, TermTop)) { + CONTEXT CHelp; + + CHelp = cont_ContextBindingContext(CtR, TermTop); + TermR = cont_ContextBindingTerm(CtR, TermTop); + CtR = CHelp; + } else + break; + } + + if (term_IsVariable(TermL)) { + + if (term_IsVariable(TermR)) { + if ((CtL != CtR || !term_EqualTopSymbols(TermL, TermR))) { + if (term_IsIndexVariable(TermL)) + cont_CreateBinding(CtL, term_TopSymbol(TermL), CtR, TermR); + else + if (term_IsIndexVariable(TermR) || (CtR == IndexContext)) + cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); + else + cont_CreateBinding(CtL, term_TopSymbol(TermL), CtR, TermR); + } + return TRUE; + } + else + if (unify_OccurCheck(CtL, term_TopSymbol(TermL), CtR, TermR)) + return FALSE; + else { + cont_CreateBinding(CtL, term_TopSymbol(TermL), CtR, TermR); + return TRUE; + } + } + else + if (term_IsVariable(TermR)) { + if (unify_OccurCheck(CtR, term_TopSymbol(TermR), CtL, TermL)) + return FALSE; + else { + cont_CreateBinding(CtR, term_TopSymbol(TermR), CtL, TermL); + return TRUE; + } + } + else + if (term_EqualTopSymbols(TermL, TermR)) { + if (term_IsComplex(TermL)) { + LIST ArgL, ArgR; + for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); + !list_Empty(ArgL); + ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) + if (!unify_UnifyAllOC(IndexContext, CtL, list_Car(ArgL), CtR, list_Car(ArgR))) + return FALSE; + } + return TRUE; + } + else + return FALSE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * GENERALIZATION TEST * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +BOOL unify_Match(CONTEXT Context, TERM TermL, TERM TermR) +{ + if (term_IsVariable(TermL)) { + if (cont_VarIsBound(Context, term_TopSymbol(TermL))) + return term_Equal(cont_ContextBindingTerm(Context, term_TopSymbol(TermL)), TermR); + else { + cont_CreateBinding(Context, term_TopSymbol(TermL), cont_InstanceContext(), TermR); + return TRUE; + } + } else if (term_EqualTopSymbols(TermL, TermR)) { + if (term_IsComplex(TermL)) { + LIST ArgL; + LIST ArgR; + for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); + !list_Empty(ArgL); + ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) + if (!unify_Match(Context, list_Car(ArgL), list_Car(ArgR))) + return FALSE; + } + return TRUE; + } else + return FALSE; +} + +BOOL unify_MatchFlexible(CONTEXT Context, TERM TermL, TERM TermR) +/************************************************************** + INPUT: Two terms where symbols with flexible arity are allowed. + RETURNS: TRUE if <TermL> matches <TermR>. +***************************************************************/ +{ + if (term_IsVariable(TermL)) { + if (cont_VarIsBound(Context, term_TopSymbol(TermL))) + return term_Equal(cont_ContextBindingTerm(Context, term_TopSymbol(TermL)), TermR); + else { + cont_CreateBinding(Context, term_TopSymbol(TermL), cont_InstanceContext(), TermR); + return TRUE; + } + } else + if (term_EqualTopSymbols(TermL, TermR) + && list_Length(term_ArgumentList(TermL)) == list_Length(term_ArgumentList(TermR))) { + if (term_IsComplex(TermL)) { + LIST ArgL; + LIST ArgR; + for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); + !list_Empty(ArgL); + ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) + if (!unify_MatchFlexible(Context, list_Car(ArgL), list_Car(ArgR))) + return FALSE; + } + return TRUE; + } + else + return FALSE; +} + + +void unify_EstablishMatcher(CONTEXT Context, SUBST Subst) +{ + while (subst_Exist(Subst)) { + /* Index to query */ + cont_CreateBinding(Context, subst_Dom(Subst), cont_InstanceContext(), subst_Cod(Subst)); + Subst = subst_Next(Subst); + } +} + + +BOOL unify_MatchBindingsHelp(const CONTEXT IndexContext, TERM TermL, CONTEXT CtR, TERM TermR) +{ + while (term_IsVariable(TermR)) { + SYMBOL TermTop; + + TermTop = term_TopSymbol(TermR); + + if (symbol_IsIndexVariable(TermTop)) + CtR = IndexContext; + else if (CtR == cont_InstanceContext()) + break; + + if (cont_VarIsBound(CtR, TermTop)) { + CONTEXT CHelp; + + CHelp = cont_ContextBindingContext(CtR, TermTop); + TermR = cont_ContextBindingTerm(CtR, TermTop); + CtR = CHelp; + } else + break; + } + + if (term_IsVariable(TermL)) { + /* Assertion: Variables of 'TermL' are bound in the index context only. */ + + if (cont_VarIsBound(IndexContext, term_TopSymbol(TermL))) + return + cont_TermEqualModuloBindings(IndexContext, + cont_ContextBindingContext(IndexContext, + term_TopSymbol(TermL)), + cont_ContextBindingTerm(IndexContext, + term_TopSymbol(TermL)), + CtR, + TermR); + else { + cont_CreateBinding(IndexContext, term_TopSymbol(TermL), CtR, TermR); + return TRUE; + } + } else if (term_EqualTopSymbols(TermL, TermR)) { + if (term_IsComplex(TermL)) { + LIST ArgL; + LIST ArgR; + + for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); + !list_Empty(ArgL); + ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) + if (!unify_MatchBindingsHelp(IndexContext, list_Car(ArgL), CtR, list_Car(ArgR))) + return FALSE; + } + + return TRUE; + } else + return FALSE; +} + + +BOOL unify_MatchBindings(const CONTEXT IndexContext, TERM TermL, TERM TermR) +{ + return unify_MatchBindingsHelp(IndexContext, TermL, cont_InstanceContext(), TermR); +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * INSTANCE TEST * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +BOOL unify_MatchReverse(const CONTEXT IndexContext, TERM TermL, CONTEXT CtR, + TERM TermR) +/********************************************************* + INPUT: 'TermL' is in IndexContext and the codomain of a subst., + 'CtR' is the context of 'TermR' which is the codomain of a subst. + obtained by a variable binding, 'Bindings' is + the number of established bindings. + RETURNS: TRUE, if 'TermL' is an instance of 'TermR'; + FALSE, otherwise. +**********************************************************/ +{ + while (term_IsVariable(TermR)) { + SYMBOL TermTop; + + TermTop = term_TopSymbol(TermR); + + if (symbol_IsIndexVariable(TermTop)) + CtR = IndexContext; + else if (CtR == cont_InstanceContext()) + break; + + if (cont_VarIsBound(CtR, TermTop)) { + CONTEXT CHelp; + + CHelp = cont_ContextBindingContext(CtR, TermTop); + TermR = cont_ContextBindingTerm(CtR, TermTop); + CtR = CHelp; + } else + break; + } + + if (term_IsVariable(TermL)) { + if ((CtR == cont_InstanceContext()) && term_EqualTopSymbols(TermL, TermR)) + /* 'TermL' and 'TermR' are exactly the same variables (via bindings), + therefore do not bind them, just return positive. */ + return TRUE; + + else if (term_IsIndexVariable(TermL)) { + cont_CreateBinding(IndexContext, term_TopSymbol(TermL), CtR, TermR); + return TRUE; + + } else if (term_IsVariable(TermR) && + (term_IsIndexVariable(TermR) || (CtR == IndexContext))) { + cont_CreateBinding(IndexContext, term_TopSymbol(TermR), cont_InstanceContext(), TermL); + return TRUE; + + } else + return FALSE; + + } else if (term_IsVariable(TermR)) { + if (term_IsIndexVariable(TermR) || (CtR == IndexContext)) { + cont_CreateBinding(IndexContext, term_TopSymbol(TermR), cont_InstanceContext(), TermL); + return TRUE; + } else + return FALSE; + + } else if (term_EqualTopSymbols(TermL, TermR)) { + + if (term_IsComplex(TermL)) { + LIST ArgL, ArgR; + for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); + !list_Empty(ArgL); + ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) + if (!unify_MatchReverse(IndexContext, + list_Car(ArgL), + CtR, + list_Car(ArgR))) + return FALSE; + } + return TRUE; + } else + return FALSE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * VARIATION TEST * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +BOOL unify_Variation(const CONTEXT Context, TERM TermL, TERM TermR) +{ + if (term_IsVariable(TermL)) { + if (term_EqualTopSymbols(TermL, TermR)) + /* TermL and TermR are in different contexts + but both are term variables which do not need to be variated. + Index variables cannot occur in TermR + which is the term to be inserted. */ + return TRUE; + else if (term_IsIndexVariable(TermL)) { + if (cont_VarIsBound(Context, term_TopSymbol(TermL))) + return term_Equal(cont_ContextBindingTerm(Context, term_TopSymbol(TermL)), TermR); + else { + /* Index to query */ + cont_CreateBinding(Context, term_TopSymbol(TermL), Context, TermR); + return TRUE; + } + } + else + return FALSE; + + } else if (term_EqualTopSymbols(TermL, TermR)) { + if (term_IsComplex(TermL)) { + LIST ArgL; + LIST ArgR; + for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); + !list_Empty(ArgL); + ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) + if (!unify_Variation(Context, list_Car(ArgL), list_Car(ArgR))) + return FALSE; + } + return TRUE; + } else + return FALSE; +} + + +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * COMMON GENERALIZATIONS * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +TERM unify_ComGenLinear(const CONTEXT IndexContext, + SUBST* SubstL, TERM TermL, SUBST* SubstR, TERM TermR) +{ + if (term_IsIndexVariable(TermR)) { + *SubstL = subst_Add(term_TopSymbol(TermR), term_Copy(TermL), *SubstL); + + return term_Copy(TermR); + + } else if (term_EqualTopSymbols(TermL, TermR)) { + + LIST ArgList, ArgL, ArgR; + + ArgList = list_Nil(); + for (ArgL = term_ArgumentList(TermL), ArgR = term_ArgumentList(TermR); + !list_Empty(ArgL); + ArgL = list_Cdr(ArgL), ArgR = list_Cdr(ArgR)) + ArgList = list_Nconc(ArgList, + list_List(unify_ComGenLinear(IndexContext, + SubstL, + list_Car(ArgL), + SubstR, + list_Car(ArgR)))); + return term_Create(term_TopSymbol(TermL), ArgList); + + } else { + + SYMBOL Symbol; + + Symbol = cont_NextIndexVariable(IndexContext); + + *SubstL = subst_Add(Symbol, term_Copy(TermL), *SubstL); + *SubstR = subst_Add(Symbol, term_Copy(TermR), *SubstR); + + return term_Create(Symbol, list_Nil()); + } +} + diff --git a/test/spass/unify.h b/test/spass/unify.h new file mode 100644 index 0000000000000000000000000000000000000000..92c93989360ccb93053f8ed68dbc4547e58a1c24 --- /dev/null +++ b/test/spass/unify.h @@ -0,0 +1,119 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * STANDARD UNIFICATION * */ +/* * * */ +/* * $Module: UNIFY * */ +/* * * */ +/* * Copyright (C) 1996, 1997, 1998, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#ifndef _UNIFY_ +#define _UNIFY_ + +/**************************************************************/ +/* Includes */ +/**************************************************************/ + +#include "term.h" +#include "symbol.h" +#include "list.h" +#include "context.h" +#include "subst.h" + +/**************************************************************/ +/* Functions for Initialization and Controlling */ +/**************************************************************/ + +void unify_Init(void); +void unify_Free(void); + +/**************************************************************/ +/* Functions for Misc */ +/**************************************************************/ + +/**************************************************************/ +/* Functions for Occur Check */ +/**************************************************************/ + +BOOL unify_OccurCheckCom(SYMBOL, CONTEXT, TERM); +BOOL unify_OccurCheck(CONTEXT, SYMBOL, CONTEXT, TERM); + +/**************************************************************/ +/* Functions for Unification */ +/**************************************************************/ + +BOOL unify_Unify(CONTEXT, TERM, CONTEXT, TERM); +BOOL unify_UnifyCom(CONTEXT, TERM, TERM); +BOOL unify_UnifyNoOC(CONTEXT, TERM, CONTEXT, TERM); +BOOL unify_UnifyAllOC(CONTEXT, CONTEXT, TERM, CONTEXT, TERM); + +/**************************************************************/ +/* Functions for Generalization Test */ +/**************************************************************/ + +BOOL unify_Match(CONTEXT, TERM, TERM); +BOOL unify_MatchFlexible(CONTEXT, TERM, TERM); +void unify_EstablishMatcher(CONTEXT, SUBST); +BOOL unify_MatchBindings(const CONTEXT, TERM, TERM); + +/**************************************************************/ +/* Functions for Instance Test */ +/**************************************************************/ + +BOOL unify_MatchReverse(const CONTEXT, TERM, CONTEXT, TERM); + +/**************************************************************/ +/* Functions for Variation Test */ +/**************************************************************/ + +BOOL unify_Variation(const CONTEXT, TERM, TERM); + +/**************************************************************/ +/* Functions for Computing MSCGs */ +/**************************************************************/ + +TERM unify_ComGenLinear(const CONTEXT, SUBST*, TERM, SUBST*, TERM); + +/**************************************************************/ +/* Functions for Debugging */ +/**************************************************************/ + +#endif diff --git a/test/spass/vector.c b/test/spass/vector.c new file mode 100644 index 0000000000000000000000000000000000000000..bd16424a7b24661cd0c1e48a013721de397c9d05 --- /dev/null +++ b/test/spass/vector.c @@ -0,0 +1,120 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * GLOBAL SYSTEM VECTOR * */ +/* * * */ +/* * $Module: VECTOR * */ +/* * * */ +/* * Copyright (C) 1996, 2000, 2001 MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + +#include "vector.h" + +/**************************************************************/ +/* Global Variables */ +/**************************************************************/ + +VECTOR vec_VECTOR; +int vec_MAX; + + +/**************************************************************/ +/* Functions */ +/**************************************************************/ + +void vec_Swap(int i, int j) +/********************************************************** + INPUT: Two integers i and j which designate the i-th and + the j-th cell of the vector. + RETURNS: None. + CAUTION: The values in the i-th and the j-th cell in the + vector are interchanged. +********************************************************/ +{ + POINTER help; + + help = vec_GetNth(i); + vec_PutNth(i, vec_GetNth(j)); + vec_PutNth(j, help); + +} + + +void vec_PrintSel(int beg, int end, void (*ElementPrint)(POINTER)) +/********************************************************** + INPUT: An int for the start position, an int for + the end position and a print function for + elements. + RETURNS: None. + EFFECT: Writes the vector from beg to end to stdout. + CAUTION: None. +********************************************************/ +{ + int i; + + if (vec_ActMax() > 0) { + for (i = beg; i < end; i++){ + printf("Entry %d:\t",i); + ElementPrint(vec_GetNth(i)); + putchar('\n'); + } + } else + puts("Vector is empty"); +} + + +void vec_PrintAll(void (*ElementPrint)(POINTER)) +/********************************************************** + INPUT: A print function for the elements of the vector. + RETURNS: None. + EFFECT: Writes the vector to stdout. + CAUTION: None. +********************************************************/ +{ + int i; + + if (vec_ActMax() > 0) { + for (i = 0; i < vec_ActMax(); i++) { + printf("Entry %d:\t", i); + ElementPrint(vec_GetNth(i)); + putchar('\n'); + } + } else + puts("Vector is empty"); +} diff --git a/test/spass/vector.h b/test/spass/vector.h new file mode 100644 index 0000000000000000000000000000000000000000..220480489da32cd6e7e51eb90c1825e911d44f4f --- /dev/null +++ b/test/spass/vector.h @@ -0,0 +1,188 @@ +/**************************************************************/ +/* ********************************************************** */ +/* * * */ +/* * GLOBAL SYSTEM VECTOR * */ +/* * * */ +/* * $Module: VECTOR * */ +/* * * */ +/* * Copyright (C) 1996, 1998, 1999, 2000, 2001 * */ +/* * MPI fuer Informatik * */ +/* * * */ +/* * This program is free software; you can redistribute * */ +/* * it and/or modify it under the terms of the GNU * */ +/* * General Public License as published by the Free * */ +/* * Software Foundation; either version 2 of the License, * */ +/* * or (at your option) any later version. * */ +/* * * */ +/* * 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., 59 Temple * */ +/* * Place, Suite 330, Boston, MA 02111-1307 USA * */ +/* * * */ +/* * * */ +/* $Revision: 21527 $ * */ +/* $State$ * */ +/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ +/* $Author: duraid $ * */ +/* * * */ +/* * Contact: * */ +/* * Christoph Weidenbach * */ +/* * MPI fuer Informatik * */ +/* * Stuhlsatzenhausweg 85 * */ +/* * 66123 Saarbruecken * */ +/* * Email: weidenb@mpi-sb.mpg.de * */ +/* * Germany * */ +/* * * */ +/* ********************************************************** */ +/**************************************************************/ + + +/* $RCSfile$ */ + + +#ifndef _VECTOR_ +#define _VECTOR_ + +#include "misc.h" + + +/**************************************************************/ +/* Type and Variable Definitions */ +/**************************************************************/ + +#define vec_SIZE 10000 + +typedef POINTER VECTOR[vec_SIZE]; + +extern VECTOR vec_VECTOR; +extern int vec_MAX; + +/**************************************************************/ +/* Inline Functions */ +/**************************************************************/ + +/* Stack operations */ + +static __inline__ void vec_Init(void) +{ + vec_MAX = 0; +} + +static __inline__ void vec_Push(POINTER Value) +{ +#ifdef CHECK + if (vec_MAX >= vec_SIZE) { + misc_StartErrorReport(); + misc_ErrorReport("\n In vec_Push: Vector Overflow."); + misc_FinishErrorReport(); + } +#endif + + vec_VECTOR[vec_MAX++] = Value; +} + + +static __inline__ POINTER vec_GetNth(NAT Index) +{ +#ifdef CHECK + if (Index >= vec_SIZE || Index >= vec_MAX) { + misc_StartErrorReport(); + misc_ErrorReport("\n In vec_GetNth: Illegal vector access."); + misc_FinishErrorReport(); + } +#endif + + return vec_VECTOR[Index]; +} + + +static __inline__ void vec_PutNth(NAT Index, POINTER Value) +{ +#ifdef CHECK + if (Index >= vec_SIZE || Index >= vec_MAX) { + misc_StartErrorReport(); + misc_ErrorReport("\n In vec_PutNth: Illegal vector access."); + misc_FinishErrorReport(); + } +#endif + + vec_VECTOR[Index] = Value; +} + + +static __inline__ void vec_Pop(void) +{ + --vec_MAX; +} + +static __inline__ POINTER vec_PopResult(void) +{ + return vec_VECTOR[--vec_MAX]; +} + +static __inline__ void vec_PopToN(int N) +{ + vec_VECTOR[N] = vec_VECTOR[--vec_MAX]; +} + +static __inline__ void vec_NPop(int N) +{ + vec_MAX -= N; +} + +static __inline__ POINTER vec_Top(void) +{ + return vec_VECTOR[vec_MAX-1]; +} + +static __inline__ POINTER vec_NthTop(int N) +{ + return vec_VECTOR[vec_MAX-(1+N)]; +} + + +static __inline__ void vec_RplacTop(POINTER Value) +{ + vec_VECTOR[vec_MAX-1] = Value; +} + +static __inline__ void vec_RplacNthTop(int N, POINTER Value) +{ + vec_VECTOR[vec_MAX-(1+N)] = Value; +} + +static __inline__ int vec_ActMax(void) +{ + return vec_MAX; +} + +static __inline__ void vec_SetMax(int Index) +{ + vec_MAX = Index; +} + +static __inline__ BOOL vec_IsMax(int Index) +{ + return vec_MAX == Index; +} + +static __inline__ BOOL vec_IsEmpty(void) +{ + return vec_MAX == 0; +} + +/**************************************************************/ +/* Prototypes */ +/**************************************************************/ + +void vec_Swap(int, int); +void vec_PrintSel(int, int, void(*)(POINTER)); +void vec_PrintAll(void(*)(POINTER)); + +#endif