/* ----------------------------------------------------------
% (C)1992 Institute for New Generation Computer Technology
% (Read COPYRIGHT for detailed information.)
----------------------------------------------------------- */
/*=====================================================================
* cu-Prolog III (Constraint Unification Prolog)
* Copyright: Institute for New Generation Computer Technology,Japan
* 1989--91
==================================================================== */
/*--------------------------------------------------------------------
* <<<< refute.c >>>>
* Prolog refutation
--------------------------------------------------------------------*/
#include "include.h"
#include <signal.h>
#define is_dead(n) (n->n_set == NULL)
#define is_tip(n) (n->n_clause == NULL)
#define is_root(n) (n->n_link == NULL)
struct node *Psolution(), *extend(), *proceed_node();
struct node *Newnode(),*backtrack_node();
struct set *init_set();
void Trace_True(),Trace_False(),Trace_Unification(),Trace_Answer();
void Trace_True2(), Trace_False2();
int Trace_Goal();
void Pbinding();
/*
[refute]-----------------------------------
. backtrack_node
. . Trace_False2
. Trace_False
. Trace_Goal
. . print_ancestors+
. Trace_True
. is_dead.
. extend
. . [system_function]
. . init_set
. . resolve+
. . . [tunify]
. . . Trace_Unification
. is_tip.
. proceed_node
. . Trace_True2.
. . next_goal+
. . have_nextgoal+
*/
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Prolog refutation entry
+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int refute(Root,n,Status)
struct node *Root, *n;
int Status; /* UP,DOWN,BACKTRACK */
{
struct node *m;
while(1)
{
if (n == NULL || n->n_spy)
if (Trace_Goal(n)==FALSE) return(FALSE);
m = extend(n, Status);
if (!is_dead(n)) Last_BT = n;
if (m == NULL_NODE) /* fail */
{
if (n->n_spy) Trace_False(n);
if (n == Root) return(FALSE);
Status = BACKTRACK;
Last_BT = n = backtrack_node(n->n_last);
}
else if (is_tip(m)) /* nil clause */
{
if (n->n_spy) Trace_True(n);
Status = UP;
n = proceed_node(m,Last_BT);
if (n == NULL_NODE) return(TRUE);
}
else {
Status = DOWN;
n = m;
}
}
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++
head unification
+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
struct node *extend(n, status) /* extend goal */
struct node *n;
int status;
{
register struct term *sliteral; /* selected literal */
struct node *m;
register struct pair *p,*env;
if (n->n_count > Refcount) {
tprint1(" <<%d] fail! (over refute counter)\n",n->n_count);
return(NULL); /* counter over = fail */
}
if (is_tip(n)) return(n); /* no goal */
sliteral = n->n_clause->c_form;
env = n->n_env;
down(p,sliteral,env);
if (p != NULL) return(NULL); /* goal is real var */
m = Newnode(NULL_CL,n->n_constraint,
NULL_ENV,n,n);
if (is_funcsys(sliteral->type.t_func)) /* functional syspred */
{
if (system_function(sliteral, env, n) == SYSFAIL)
return(NULL);
else {
n->n_set = (struct set *)NULL;
return(m);
}
}
if (is_nofuncsys(sliteral->type.t_func)) /* sys pred. */
{
if (system_pred(sliteral, env, n, m, status) == SYSFAIL)
return(NULL);
else {
return(m);
}
/* n->n_set may be DUMMY_DEF */
}
if (is_dead(n)) return(NULL);
if (resolve(n, m, sliteral, env) == FALSE)
return(NULL); /* user pred.: resolution */
m->n_usp = usp;
m->n_hp = hp;
m->n_ep = ep;
m->n_set = init_set(m);
return(m);
}
int resolve(n0, n, sliteral, env) /* resolution: called by extend() */
struct node *n0,*n;
struct term *sliteral;
struct pair *env;
{
struct ustack *usave;
int *hsave,tunify_apply();
struct pair *esave;
register struct set *s;
register struct eclause *ec;
usave = usp;hsave = hp;esave = ep;
STAT_REFUTE++; /* statistics */
for (s = n0->n_set; s != NULL; s = s->s_link)
{
if (s->s_ground_head) /* no variable/PST in the head */
{
if (tunify(sliteral, env, s->s_clause->c_form,
NULL_ENV,0) == FALSE)
{
STAT_BACKTRACK_SHAL++; /* statistics */
hp = hsave; ep = esave;
continue;
}
if (s->s_anumber > 0)
n->n_env = Nenv((int)s->s_anumber); /* body environment */
}
else
{
if (s->s_anumber > 0)
n->n_env = Nenv((int)s->s_anumber); /* head&body env */
if (tunify_apply(sliteral, env,
s->s_clause->c_form, n->n_env,0) == FALSE){
/* undo(usave); */
hp = hsave; ep = esave;
STAT_BACKTRACK_SHAL++; /* statistics */
continue;
}
}
ec = transform(n0->n_constraint, s->s_constraint, n->n_env);
if (ec == (struct eclause *)MFAIL) {
/* constraint transformation failure */
undo(usave);hp = hsave; ep = esave;
continue;
}
n->n_constraint = ec;
n0->n_scount++;
if (n->n_spy) Trace_Unification(n0,s);
n0->n_set = s->s_link;
n->n_clause = s->s_clause->c_link;
return(TRUE);
}
return(FALSE);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++
make and process node
+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
struct node *Newnode(goal, icons, env, nlink, nlast)
struct clause *goal;
struct eclause *icons;
struct pair *env;
struct node *nlink, *nlast;
{
register struct node *n;
n = new(node);
n->n_last = nlast; /* backtrack node */
n->n_link = nlink; /* mother node */
n->n_clause = goal; /* goal */
n->n_env = env;
n->n_hp = hp;
n->n_ep = ep;
n->n_usp = usp;
if (nlink == NULL_NODE) n->n_count = 0;
else n->n_count = nlink->n_count + 1;
n->n_tmp = 0;
n->n_scount = 0;
n->n_constraint = icons;
if (goal == NULL_CL) {
n->n_set = (struct set *)NULL;
n->n_spy = 0;
}
else
n->n_set = init_set(n);
return(n);
}
struct set *init_set(n)
register struct node *n;
{
register struct term *t;
register struct func *f;
register struct pair *e,*p;
register struct set *s;
if (n->n_clause == NULL_CL) return((struct set *)NULL);
t = n->n_clause->c_form;
e = n->n_env;
down(p,t,e);
if (p != NULL) return(NULL); /* goal is var */
f = t->type.t_func;
n->n_spy = Is_Trace && isspy(f);
if (isuser(f)) {
if (((s = f->def.f_set) == (struct set *)NULL)
&& (Handle_Undefined == TRUE)) {
sprintf(nbuf,">>> %s <<< is UNDEFINED!",f->f_name);
error(nbuf);
}
else return(s);
}
else return((struct set *)NULL);
}
struct node *backtrack_node(n) /* restore stack, heap */
struct node *n;
{
if (usp > Stack_Max) Stack_Max = usp;
if (chp > Cheap_Max) Cheap_Max = chp;
if (hp > Heap_Max) Heap_Max = hp;
if (ep > Esp_Max) Esp_Max = ep;
STAT_BACKTRACK_DEEP++; /* statistics */
while (n != NULL_NODE)
{
if (n->n_spy) Trace_False2(n);
if(! is_dead(n)) {
undo(n->n_usp);
hp = n->n_hp;
ep = n->n_ep;
return(n);
}
n = n->n_last;
}
return(NULL_NODE);
}
struct node *proceed_node(n,btnode)
struct node *n,*btnode;
{
register struct node *m;
int have_nextgoal();
struct node *next_goal();
for (m = n; m != NULL; m = m->n_link)
{
if (m->n_spy) Trace_True2(m);
if (have_nextgoal(m->n_clause))
return(next_goal(m,n,btnode));
}
return(NULL_NODE);
}
int have_nextgoal(c) /* called by proceed_node() */
register struct clause *c;
{
if (c != NULL_CL && c->c_link != NULL_CL) return(TRUE);
else return(FALSE);
}
struct node *next_goal(m,oldnode,btnode) /* called by proceed_node() */
struct node *m, *oldnode,*btnode;
{
struct node *n;
n = Newnode(m->n_clause->c_link, oldnode->n_constraint,
m->n_env, m->n_link, btnode);
n->n_count = oldnode->n_count +1;
return(n);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++
print answer & binding
+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int Panswer(root, vlist) /* print solution */
struct node *root;
struct term *vlist;
{
if (!Is_Notrace) Trace_Answer(root);
Pbinding(vlist, root->n_env);
if (root->n_constraint != NULL_ECL) {
tprint0("\n where ");
Peclause(root->n_constraint);
}
if (Last_BT == NULL) {
tprint0("\n");
return(FALSE); /* no backtrack point */
}
if ((fp != stdin) || (!keyread(';')))
return(FALSE);
return(TRUE); /* more solution */
}
void Pbinding(vlist, env) /* print var binding */
struct term *vlist;
struct pair *env;
{
if (vlist == NULL_TERM) return;
Pbinding(vlink(vlist),env);
if ((strcmp(vname(vlist),"_") == 0) ||
(vlist->type.ident == VAR_PST_TYPE)) return;
tprint1(" %s = ",vname(vlist));
Pterm(vlist,env);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++
trace --- interaction with user
+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int Trace_Goal(n)
struct node *n;
{
void print_ancestors();
if (n == NULL) return(FALSE);
if (Is_Notrace) return(TRUE);
if (Last_SKIP == n) Last_SKIP = NULL_NODE;
if (Last_SKIP != NULL_NODE) return(TRUE);
tprint1(" [%d>>",n->n_count);
Pgoal(n);
if ((Is_Steptrace) || (Is_Leap && (n->n_spy)))
{
Steptrace_mode;
while(1) {
tprint0(" #<trace ?>");
switch (getchar()) {
case 'a' :
case 'A' : print_ancestors(n); getchar(); break;
case 'b' :
case 'B' : {
int *hsave;
struct pair *esave;
struct ustack *usave = utop;
hsave = hp; esave = ep;
utop = usp;
if (setjmp(unbreak_reset)) {
utop = usave; hp = hsave; ep = esave;
break;
}
while(1) {
prolog_execution();
}
}
case 'z' :
case 'Z' :
case 'q' :
case 'Q' : NL; tprint0("\n Execution Abort \n");
longjmp(reset,0);
case '?' :
case 'h' :
case 'H' :
tprint0("\na : ancestors\tb : break\th : help\tl : leap\ts : skip\n");
tprint0("<cr> : next\tq: abort\tf : fail return\n");
getchar(); break;
case 'f' :
case 'F' : return(FALSE);
case 'l' :
case 'L' : tflag = 3; return(TRUE);
case 's' :
case 'S' : Last_SKIP = n; return(TRUE);
default : Last_SKIP = NULL_NODE; return(TRUE);
}
}
}
else NL; return(TRUE);
}
void Trace_False(n)
struct node *n;
{
struct func *f;
struct pair *p, *e;
struct term *t;
if (Is_Leap) Steptrace_mode;
if (Last_SKIP == n) Last_SKIP = NULL_NODE;
if (Last_SKIP != NULL_NODE) return;
t = n->n_clause->c_form;
if (isvar(t)) {
e = n->n_env;
down(p,t,e);
}
f = t->type.t_func;
if (is_funcsys(f))
{
tprint2(" <<%d] false (%s)\n",n->n_count,f->f_name);
}
else if (is_nofuncsys(f))
{
tprint2(" <<%d] fail (%s)\n",n->n_count,f->f_name);
}
else /* user pred */
{
tprint2(" <=%d-no= fail %s.\n",n->n_count,f->f_name);
}
}
void Trace_True(n)
struct node *n;
{
struct func *f;
struct term *t;
struct pair *p, *e;
if (Is_Leap) Steptrace_mode;
if (Last_SKIP == n) Last_SKIP = NULL_NODE;
if (Last_SKIP != NULL_NODE) return;
t = n->n_clause->c_form;
e = n->n_env;
down(p,t,e);
f = t->type.t_func;
if (isuser(f)) return;
tprint1(" <<%d] ",n->n_count);
if (is_funcsys(f))
{
tprint1("true (%s)\n",f->f_name);
}
else
{
tprint1("success (%s)\n",f->f_name);
}
}
void Trace_False2(n)
struct node *n;
{
if (Is_Leap) Steptrace_mode;
if (Last_SKIP == n){
tprint1(" <<%d] fail\n",n->n_count);
Last_SKIP = NULL_NODE;
}
}
void Trace_True2(n)
struct node *n;
{
if (Last_SKIP == n){
/* tprint1(" <<%d] true",n->n_count); */
Last_SKIP = NULL_NODE;
}
}
void Trace_Unification(n,s)
struct node *n;
struct set *s;
{
if (Is_Leap) Steptrace_mode;
if (Last_SKIP != NULL_NODE) return;
tprint2(" <=%d-%d=",n->n_count, n->n_scount);
Showhorn(s->s_clause, s->s_constraint, NULL_ENV);
NL;
}
void Trace_Answer(root)
struct node *root;
{
Last_SKIP = NULL_NODE;
tprint0("success.\n");
Pclause(root->n_clause, root->n_env);
if (root->n_constraint != NULL_ECL) {
tprint0(" ; ");
Peclause(root->n_constraint);
}
NL;
}
void print_ancestors(n) /* called by Trace_goal() */
struct node *n;
{
while (n != NULL) {
tprint1(" [%d>>",n->n_count); Pgoal(n); NL;
n = n->n_link;
}
}
syntax highlighted by Code2HTML, v. 0.9.1