Sindbad~EG File Manager

Current Path : /usr/home/beeson/Otter-Lambda/otter/
Upload File :
Current File : /usr/home/beeson/Otter-Lambda/otter/resolve.c

/*
 *  resolve.c -- Resolution inference rules.
 *
 */

#include <assert.h> 
#include "header.h"
#include "bsym.h"    // Beeson's files
#include "beta.h"
#include "bterms.h"
#include "unify2.h"  // max_vars

/*************
 *
 *    struct clause *build_hyper(clash,nuc_subst,nuc_lits,nuc,
 *                                     giv_subst,giv_lits,giv_sat,nuc_pos,sat_indexes)
 *
 *    This routine constructs a hyperresolvent or UR-resolvent.
 *
 *************/

static struct clause *build_hyper(struct clash_nd *cla,
				  struct context *nuc_subst,
				  struct literal *nuc_lits,
				  struct clause *nuc,
				  struct context *giv_subst,
				  struct literal *giv_lits,
				  struct clause *giv_sat,
				  int nuc_pos,
				  int sat_indexes)
{
  struct clause *res, *sat;
  struct literal *lit, *new, *prev;
  struct clash_nd *c;
  struct int_ptr *ip1, *ip2, *ip3, *ip4;
  int i, j;
  int n = 0;

  res = get_clause();

  ip1 = get_int_ptr(); /* to be filled in by caller with name of inference rule */
  res->parents = ip1;
  /* If given clause is satellite, add number to parent list. */
  ip3 = NULL;
  if (giv_sat) {
    ip2 = get_int_ptr();
    ip2->i = giv_sat->id;
    if (Flags[ORDER_HISTORY].val && nuc_pos != 0)
      /* insert later in correct position */
      ip3 = ip2;
    else {
      ip1->next = ip2;
      ip1 = ip2;
    }
  }

  ip2 = get_int_ptr();
  ip2->i = nuc->id;
  ip1->next = ip2;

  lit = giv_lits;
  prev = NULL;
  while (lit != NULL) {
    new = get_literal();
    new->container = res;
    if (prev == NULL)
      res->first_lit = new;
    else
      prev->next_lit = new;
    prev = new;
    new->sign = lit->sign;
    new->atom = apply(lit->atom, giv_subst);
    new->atom->occ.lit = new;
    new->atom->varnum = lit->atom->varnum;  /* copy type of atom */
    lit = lit->next_lit;
  }
  lit = nuc_lits;
  while (lit != NULL) {
    new = get_literal();
    new->container = res;
    if (res->first_lit == NULL)
      res->first_lit = new;
    else
      prev->next_lit = new;
    prev = new;
    new->sign = lit->sign;
    new->atom = apply(lit->atom, nuc_subst);
    new->atom->occ.lit = new;
    new->atom->varnum = lit->atom->varnum;  /* copy type of atom */
    lit = lit->next_lit;
  }

  c = cla;
  i = 1;
  while (c != NULL) {
    if (ip3 && i == nuc_pos) {
      /* insert given clause (which is satellite) number here */
      ip2->next = ip3;
      ip2 = ip3;
    }
    ip1 = get_int_ptr();
    ip2->next = ip1;
    ip2 = ip1;
    if (c->evaluable)
      ip1->i = EVAL_RULE;
    else {
      sat = c->found_atom->occ.lit->container;
      lit = sat->first_lit;
      j = 0;
      while (lit != NULL) {
	j++;
	if (lit->atom != c->found_atom) {
	  new = get_literal();
	  new->container = res;
	  if (res->first_lit == NULL)
	    res->first_lit = new;
	  else
	    prev->next_lit = new;
	  prev = new;
	  new->sign = lit->sign;
	  new->atom = apply(lit->atom, c->subst);
	  new->atom->occ.lit = new;
	  new->atom->varnum = lit->atom->varnum;  /* type of atom */
	}
	else
	  n = j;
	lit = lit->next_lit;
      }
      ip1->i = sat->id;
      if (sat_indexes) {
	ip1 = get_int_ptr();
	ip4 = get_int_ptr();
	ip1->next = ip4;
	ip2->next = ip1;
	ip1->i = LIST_RULE-1;
	ip4->i = n;
	ip2 = ip4;
      }
    }
    i++;
    c = c->next;
  }

  if (ip3 && i == nuc_pos) {
    /* insert given clause (which is satellite) number here */
    ip2->next = ip3;
    ip2 = ip3;
  }

  if (ip3 && sat_indexes) {
    struct literal *l1, *l2;
    ip1 = get_int_ptr();
    ip4 = get_int_ptr();
    ip1->next = ip4;
    ip4->next = ip3->next;
    ip3->next = ip1;
    ip1->i = LIST_RULE-1;
    /* Need index of clashed literal in given clause (which is satellite). */
    l1 = giv_sat->first_lit;
    l2 = giv_lits;
    i = 1;
    while (l2 && l1->sign == l2->sign && l1->atom == l2->atom) {
      l1 = l1->next_lit; l2 = l2->next_lit; i++;
    }
    ip4->i = i;
  }

  return(res);

}  /* build_hyper */

/*************
 *
 *   maximal_lit()
 *
 *   true iff no predicate symbol in clause has a higher lex val.
 *
 *************/

int maximal_lit(struct literal *l1)
{
  struct literal *l2;
  int i1;

  i1 = sn_to_node(l1->atom->sym_num)->lex_val;

  for (l2 = l1->container->first_lit; l2; l2 = l2->next_lit) {
    if (l2 != l1 && l2->atom->varnum != ANSWER) {
      if (l2->sign > l1->sign)
	return(0);
      else if (l2->sign == l1->sign &&
	       sn_to_node(l2->atom->sym_num)->lex_val > i1)
	return(0);
    }
  }
  return(1);
}  /* maximal_lit */

/*************
 *
 *    clash(c_start, nuc_subst, nuc_lits, nuc, giv_subst, giv_lits, giv_sat,
 *                  sat_proc, inf_clock, nuc_pos)
 *
 *    This routine is called by both hyper and UR to clash away the
 *    marked literals of the given nucleus, and append kept resolvents
 *    to Sos.
 *
 *    c_start:    Start of the clash_structure list.  There is one node
 *                for each literal that is to be clashed away.
 *    nuc_subst:  Substitution for the nucleus.
 *    nuc_lits:   Non-clashed literals of the nucleus.
 *    nuc:        The nucleus.
 *    giv_subst:  If the given clause is a satellite, then this is its
 *                substitution; else NULL.
 *    giv_lits:   If the given clause is a satellite, then these are its
 *                non-clashed literals; else NULL.
 *    giv_sat:    If the given clause is a satellite, then this is it;
 *                else NULL.
 *    sat_proc:   procedure to identify (other) satellites:  `pos_clause'
 *                for hyper, `unit_clause' for UR.
 *    inf_clock:  Clock (HYPER_TIME or UR_TIME) to be turned off during
 *                call to `pre_process'.
 *    nuc_pos:    If not 0, giv cl is sat, and nuc_pos gives position
 *                of "missing" clash node.  To construct history.
 *    ur_box:     if not 0, UR is rule, and this is the index of the boxed literal.
 *
 *************/

static void clash(struct clash_nd *c_start,
		  struct context *nuc_subst,
		  struct literal *nuc_lits,
		  struct clause *nuc,
		  struct context *giv_subst,
		  struct literal *giv_lits,
		  struct clause *giv_sat,
		  int (*sat_proc)(struct clause *c),
		  int inf_clock,
		  int nuc_pos,
		  int ur_box)
{
  struct clash_nd *c;
  struct clash_nd *c_end = NULL;
  int found, backup, fpa_depth, sign;
  struct term *f_atom, *nuc_atom_instance;
  struct trail *tr;
  struct clause *res;
  char *s;
  int save_nextvar, save_nextvar2, save_nextvar3;  // Beeson 4.05.04
  save_nextvar2 = nuc_subst->next_var;   // Beeson 5.04.04
  save_nextvar3 = giv_subst? giv_subst->next_var : 0;
  fpa_depth = Parms[FPA_LITERALS].val;
  c = NULL;
  backup = 0;

  while (1) {  /* return from within loop */
    if (backup == 0) {
      if (c_start == NULL || (c != NULL && c->next == NULL)) {
	      /* clash is complete */
	      res = build_hyper(c_start, nuc_subst, nuc_lits, nuc,
			      giv_subst, giv_lits, giv_sat, nuc_pos,
			      (inf_clock == HYPER_TIME || inf_clock == NEG_HYPER_TIME) &&
			      Flags[BUILD_PROOF_OBJECT].val);
	      if (inf_clock == HYPER_TIME) {
	         Stats[HYPER_RES_GEN]++;
	         res->parents->i = HYPER_RES_RULE;
	      }
	      else if (inf_clock == NEG_HYPER_TIME) {
	         Stats[NEG_HYPER_RES_GEN]++;
	         res->parents->i = NEG_HYPER_RES_RULE;
	      }
	      else {
	         Stats[UR_RES_GEN]++;
	         res->parents->i = UR_RES_RULE;
	         if (Flags[BUILD_PROOF_OBJECT].val) {
	         /* Insert position of NONclashed nuc literal into history. */
	            struct int_ptr *ip1, *ip2;
	            ip1 = get_int_ptr();
	            ip2 = get_int_ptr();
	            ip1->next = ip2;
	            ip2->next = res->parents->next->next;
	            res->parents->next->next = ip1;
	            ip1->i = LIST_RULE-1;
	            ip2->i = ur_box;
	         }
	      }
	      Stats[CL_GENERATED]++;
	      if (heat_is_on()) {
	         struct clause *giv;
	         giv = (giv_sat ? giv_sat : nuc);
	         res->heat_level = giv->heat_level + 1;
	      }
	      CLOCK_STOP(inf_clock);
	      pre_process(res, 0, Sos);
	      CLOCK_START(inf_clock);
	      backup = 1;
	      c_end = c;
	      c = NULL;
         }
   else {
	   if (c == NULL)   /* just starting */
	      c = c_start;
   	else
	      c = c->next;
	   save_nextvar = c->subst->next_var;              // Beeson 5.04.04

	   nuc_atom_instance = apply(c->nuc_atom, nuc_subst);
		
	   if (c->evaluable) {
	      /* evaluate, but don't take any action yet */
	      nuc_atom_instance = convenient_demod(nuc_atom_instance);
	      s = sn_to_str(nuc_atom_instance->sym_num);
	      sign = c->nuc_atom->occ.lit->sign;
	      if (sign)
	         c->evaluation = str_ident(s, "$F");
	      else
	         c->evaluation = str_ident(s,"$T");
	      c->already_evaluated = 0;
	   }
	   else {  /* not evaluable */
	      c->u_tree = build_tree(nuc_atom_instance, UNIFY,fpa_depth, c->db);
	   }
	   zap_term(nuc_atom_instance);
     }
    }
    else {  /* backup */
      if (c_start == NULL ||
	       (c != NULL && c->prev == NULL))   /* done with this nucleus */
	       return;
      else {
	      if (c == NULL)
	         c = c_end;
	      else
	         c = c->prev;
	      if (!c->evaluable)
	         clear_subst_1(c->tr);
	         backup = 0;
	         c->subst->next_var = save_nextvar;  // Beeson 5.04.04
	         nuc_subst->next_var = save_nextvar2; // Beeson 4.05.04
	         if(giv_subst)
	             giv_subst->next_var = save_nextvar3; // Beeson 4.05.04
         }
    }

    if (backup == 0) {
      found = 0;
      if (c->evaluable) {
	      if (c->already_evaluated || !c->evaluation)
	         backup = 1;
	      else
	         /* Set flag and proceed. */
	         c->already_evaluated = 1;
      }
      else {
      
         f_atom = next_term(c->u_tree, 0);
	      tr = NULL;
	      while (f_atom && !found) {
	         memset(c->subst->bound,0,MAX_VARS*sizeof(char));  // Beeson 7.18.03
	         memset(c->subst->forbidden,0,MAX_VARS*sizeof(restrictdata));  // Beeson 7.18.03
	         c->subst->next_var = save_nextvar;   // Beeson 5.04.04
	         nuc_subst->next_var = save_nextvar2; // Beeson 5.04.04
	         if(giv_subst)                             // Beeson 5.05.04
	             giv_subst->next_var = save_nextvar3;  // Beeson 5.05.04
   	      
	         /* Sorry this test is so complicated. */
	            if (
	               /* Basic satellite test. */
	               (*sat_proc)(f_atom->occ.lit->container) &&
           	         /* order_hyper & !UR -> maximal_lit */
	                  (!Flags[ORDER_HYPER].val ||
           	         inf_clock == UR_TIME ||
	                  maximal_lit(f_atom->occ.lit)) &&
                     (
                     (Flags[LAMBDA_FLAG].val == 0 ||                       // Beeson 6.15.03
                     (                                                           // Beeson 6.15.03
                        (c->subst->next_var = nuc_subst->next_var) != 0 &&        // Beeson 6.15.03
                        (c->subst->next_var = max_vars(giv_sat, f_atom)) != 0  && // Beeson 6.15.03
                        forbid_bound(c->subst,f_atom)                             // Beeson 7.17.03
                     )                 // Beeson 6.15.03
                     )                 // Beeson 6.15.03
                     ) &&
       	         unify(c->nuc_atom,nuc_subst,f_atom,c->subst,&tr)
   		     	
	               ) {
   			
	            found = 1;
	            }
	            if (!found)
	               f_atom = next_term(c->u_tree, 0);
	         }
   		
	         if (found) {
	            c->found_atom = f_atom;
	            c->tr = tr;
	         }
	         else {
	            backup = 1;
	         }
         }
      }
  }  /* while */
}  /* clash */

/*************
 *
 *    hyper_res(c) -- hyperresolution
 *
 *    Append kept resolvents to Sos.  Each kept
 *    clause has already passed the pre_process filter (forward
 *    subsumption, etc.), been integrated, and inserted into
 *    appropriate indexes.
 *
 *************/

void hyper_res(struct clause *giv_cl)
{
  struct literal *lit, *nuc_lits, *giv_lits, *l1, *l2, *l3;
  struct context *nuc_subst, *giv_subst;
  struct clash_nd *clash_list, *c1, *c2;
  struct clause *nuc;
  int m, i, nuc_pos;
  struct term *f_atom;
  struct fpa_tree *ut;
  struct trail *tr;
  
  CLOCK_START(HYPER_TIME);
  if (num_literals(giv_cl) == 0) {
    CLOCK_STOP(HYPER_TIME);
    return;
  }
  else if (!pos_clause(giv_cl)) {  /* given clause is nucleus */
    clash_list = NULL;
    nuc_lits = NULL;
    if(Flags[LAMBDA_FLAG].val)
       nuc_subst = get_context2(giv_cl,0); // Beeson 6.13.03   
    else
       { nuc_subst = get_context();
         nuc_subst->multiplier = 0;
       }
    m = 1;
    lit = giv_cl->first_lit;
    l2 = NULL; c2 = NULL;  /* to quiet lint */
    while (lit != NULL) {
      /* positive literal || answer literal */
      if (lit->sign || lit->atom->varnum == ANSWER) {
	      l1 = get_literal();
	      if (nuc_lits == NULL)
	         nuc_lits = l1;
	      else
	         l2->next_lit = l1;
	      l2 = l1;
	      l1->sign = lit->sign;
	      l1->atom = lit->atom;
      }
      else {            /* put negative literal into clash structure */
	      c1 = get_clash_nd();
	      if (clash_list == NULL)
	         clash_list = c1;
	      else {
	         c2->next = c1;
	         c1->prev = c2;
	      }
	      c2 = c1;
	      c2->db = Fpa_clash_pos_lits;
	      if(Flags[LAMBDA_FLAG].val)  // Beeson 6.17.03
	         c2->subst = get_context2(giv_cl,m++);    // Beeson 6.17.03
	      else                              // Beeson 6.17.03 
	         { c2->subst = get_context();
	           c2->subst->multiplier = m++;
	         }
	      c2->nuc_atom = lit->atom;
	      c2->evaluable = (lit->atom->varnum == EVALUABLE);
      }
      lit = lit->next_lit;
    }
    clash(clash_list, nuc_subst, nuc_lits, giv_cl,
	  (struct context *) NULL, (struct literal *) NULL,
	  (struct clause *) NULL,
	  pos_clause, HYPER_TIME, 0, 0);
    c1 = clash_list;
    while (c1 != NULL) {
      free_context(c1->subst);
      c2 = c1;
      c1 = c1->next;
      free_clash_nd(c2);
    }
    l1 = nuc_lits;
    while (l1 != NULL) {
      l2 = l1;
      l1 = l1->next_lit;
      free_literal(l2);
    }
    free_context(nuc_subst);
    CLOCK_STOP(HYPER_TIME);
    return;
  }
  else {  /* given clause is satellite (positive) */
    if(Flags[LAMBDA_FLAG].val)
      { giv_subst = get_context2(giv_cl,0); /* Beeson 6.13.03 */ 
        nuc_subst = get_context2(giv_cl,1);  /* Beeson 6.13.03 */
      }
    else
      { giv_subst = get_context(); 
        giv_subst->multiplier = 0;
        nuc_subst = get_context();  /* substitution for nucleus */
        nuc_subst->multiplier = 1;
      }
    l3 = giv_cl->first_lit;
    l2 = NULL;  c2 = NULL;
    while (l3 != NULL) {  /* for each literal in given satellite */
      if (!Flags[ORDER_HYPER].val || maximal_lit(l3)) {
	      /* collect non-clashed lits (including answers) of given sat*/
	      giv_lits = NULL;
	      lit = giv_cl->first_lit;
	      while (lit != NULL) {
	      if (lit != l3) {
	         l1 = get_literal();
	         if (giv_lits == NULL)
	            giv_lits = l1;
	         else
	            l2->next_lit = l1;
	         l2 = l1;
	         l1->sign = lit->sign;
	         l1->atom = lit->atom;
	      }
	      lit = lit->next_lit;
	      }
	      ut = build_tree(l3->atom, UNIFY,
			      Parms[FPA_LITERALS].val, Fpa_clash_neg_lits);
	      f_atom = next_term(ut, 0);
	      while (f_atom != NULL) {  /* for each potential nucleus */
	         tr = NULL;
	         nuc = f_atom->occ.lit->container;
	         // Next ensure that giv_subst->next_var exceeds all var_nums in giv_cl as well as in 
            // the clause containing f_atom.
            giv_subst->next_var = max_vars(giv_cl, f_atom);       // Beeson 6.13.03
            nuc_subst->next_var = giv_subst->next_var;            // Beeson 7.22.03
            memset(nuc_subst->bound,0,MAX_VARS*sizeof(char));     // Beeson 7.17.03
            memset(nuc_subst->forbidden,0,MAX_VARS*sizeof(restrictdata)); // Beeson 7.18.03
            forbid_bound(nuc_subst,f_atom);                       // Beeson 7.17.03
	         if (!pos_clause(nuc) &&
	               unify(l3->atom, giv_subst, f_atom, nuc_subst, &tr)) {
	            /* we have a nucleus */

	            /* there are three kinds of literal in the nucleus:    */
	            /*    1. the clashed literal -> do nothing             */
	            /*    2. positive or answer literals -> collect them   */
	            /*    3. negative literals -> put into clash structure */

	            nuc_lits = NULL;
	            clash_list = NULL;
	            m = 2;  /* multipliers for found sats start with 2 */
	            lit = nuc->first_lit;
	            i = 1;  /* find index of clausable lit that sat clashes with. */
	            nuc_pos = 0;
	            while (lit != NULL) {
	               if (lit->atom == f_atom)  /* save position */
		               nuc_pos = i;
	                  /* positive || answer */
	               else if (lit->sign || lit->atom->varnum == ANSWER) {
		               l1 = get_literal();
		               if (nuc_lits == NULL)
		                  nuc_lits = l1;
		               else
		                  l2->next_lit = l1;
		               l2 = l1;
		               l1->sign = lit->sign;
		               l1->atom = lit->atom;
	               }
	               else {  /* put literal into clash structure */
		               i++;
		               c1 = get_clash_nd();
		               if (clash_list == NULL)
		                  clash_list = c1;
		               else {
		                  c2->next = c1;
		                  c1->prev = c2;
		               }
		               c2 = c1;
		               c2->db = Fpa_clash_pos_lits;
		               if(Flags[LAMBDA_FLAG].val)  // Beeson 6.17.03
	                     c2->subst = get_context2(giv_cl,m++);    // Beeson 6.17.03
	                  else                              // Beeson 6.17.03 
	                     { c2->subst = get_context();
		                  c2->subst->multiplier = m++;
		                  }
		               c2->nuc_atom = lit->atom;
		               c2->evaluable = (lit->atom->varnum == EVALUABLE);
	               }
	               lit = lit->next_lit;
	            }

	            clash(clash_list, nuc_subst, nuc_lits, nuc,
		               giv_subst, giv_lits, giv_cl,
		               pos_clause, HYPER_TIME, nuc_pos, 0);

	            /* now deallocate the clash structure and literal nodes */
	            c1 = clash_list;
	            while (c1 != NULL) {
	               free_context(c1->subst);
	               c2 = c1;
	               c1 = c1->next;
	               free_clash_nd(c2);
	            }
	            l1 = nuc_lits;
	            while (l1 != NULL) {
	               l2 = l1;
	               l1 = l1->next_lit;
	               free_literal(l2);
	            }
	            clear_subst_1(tr);
	         }
	      f_atom = next_term(ut, 0);
	      }
	      l1 = giv_lits;
	      while (l1 != NULL) {
	      l2 = l1;
	      l1 = l1->next_lit;
	      free_literal(l2);
	      }
      }
      l3 = l3->next_lit;
    }    
    free_context(giv_subst);
    free_context(nuc_subst);
    CLOCK_STOP(HYPER_TIME);
    return;
  }
}  /* hyper_res */

/*************
 *
 *    neg_hyper_res(c) -- negative hyperresolution
 *
 *    Append kept resolvents to Sos.  Each kept
 *    clause has already passed the pre_process filter (forward
 *    subsumption, etc.), been integrated, and inserted into
 *    appropriate indexes.
 *
 *************/

void neg_hyper_res(struct clause *giv_cl)
{
  struct literal *lit, *nuc_lits, *giv_lits, *l1, *l2, *l3;
  struct context *nuc_subst, *giv_subst;
  struct clash_nd *clash_list, *c1, *c2;
  struct clause *nuc;
  int m, i, nuc_pos;
  struct term *f_atom;
  struct fpa_tree *ut;
  struct trail *tr;

  /* This code should have been combined with the pos hyper code. */

  CLOCK_START(NEG_HYPER_TIME);
  if (num_literals(giv_cl) == 0) {
    CLOCK_STOP(NEG_HYPER_TIME);
    return;
  }
  else if (!neg_clause(giv_cl)) {  /* given clause is nucleus */
    clash_list = NULL;
    nuc_lits = NULL;
    nuc_subst = get_context();
    nuc_subst->multiplier = 0;
    m = 1;
    lit = giv_cl->first_lit;
    l2 = NULL; c2 = NULL;  /* to quiet lint */
    while (lit != NULL) {
      /* negative literal || answer literal */
      if (!lit->sign || lit->atom->varnum == ANSWER) {
	l1 = get_literal();
	if (nuc_lits == NULL)
	  nuc_lits = l1;
	else
	  l2->next_lit = l1;
	l2 = l1;
	l1->sign = lit->sign;
	l1->atom = lit->atom;
      }
      else {            /* put positive literal into clash structure */
	c1 = get_clash_nd();
	if (clash_list == NULL)
	  clash_list = c1;
	else {
	  c2->next = c1;
	  c1->prev = c2;
	}
	c2 = c1;
	c2->db = Fpa_clash_neg_lits;
	c2->subst = get_context();
	c2->subst->multiplier = m++;
	c2->nuc_atom = lit->atom;
	c2->evaluable = (lit->atom->varnum == EVALUABLE);
      }
      lit = lit->next_lit;
    }
    clash(clash_list, nuc_subst, nuc_lits, giv_cl,
	  (struct context *) NULL, (struct literal *) NULL,
	  (struct clause *) NULL,
	  neg_clause, NEG_HYPER_TIME, 0, 0);
    c1 = clash_list;
    while (c1 != NULL) {
      free_context(c1->subst);
      c2 = c1;
      c1 = c1->next;
      free_clash_nd(c2);
    }
    l1 = nuc_lits;
    while (l1 != NULL) {
      l2 = l1;
      l1 = l1->next_lit;
      free_literal(l2);
    }
    free_context(nuc_subst);
    CLOCK_STOP(NEG_HYPER_TIME);
    return;
  }
  else {  /* given clause is satellite (negative) */
    giv_subst = get_context();  /* substitution for given satellite */
    giv_subst->multiplier = 0;
    nuc_subst = get_context();  /* substitution for nucleus */
    nuc_subst->multiplier = 1;
    l3 = giv_cl->first_lit;
    l2 = NULL; c2 = NULL;
    while (l3 != NULL) {  /* for each literal in given satellite */
      if (!Flags[ORDER_HYPER].val || maximal_lit(l3)) {
	/* collect non-clashed lits (including answers) of given sat*/
	giv_lits = NULL;
	lit = giv_cl->first_lit;
	while (lit != NULL) {
	  if (lit != l3) {
	    l1 = get_literal();
	    if (giv_lits == NULL)
	      giv_lits = l1;
	    else
	      l2->next_lit = l1;
	    l2 = l1;
	    l1->sign = lit->sign;
	    l1->atom = lit->atom;
	  }
	  lit = lit->next_lit;
	}
	ut = build_tree(l3->atom, UNIFY,
			Parms[FPA_LITERALS].val, Fpa_clash_pos_lits);
	f_atom = next_term(ut, 0);
	while (f_atom != NULL) {  /* for each potential nucleus */
	  tr = NULL;
	  nuc = f_atom->occ.lit->container;
	  if (!neg_clause(nuc) &&
	      unify(l3->atom, giv_subst, f_atom, nuc_subst, &tr)) {
	    /* we have a nucleus */

	    /* there are three kinds of literal in the nucleus:    */
	    /*    1. the clashed literal -> do nothing             */
	    /*    2. negative or answer literals -> collect them   */
	    /*    3. positive literals -> put into clash structure */

	    nuc_lits = NULL;
	    clash_list = NULL;
	    m = 2;  /* multipliers for found sats start with 2 */
	    lit = nuc->first_lit;
	    i = 1;  /* find index of clahsable lit that sat clashes with. */
	    nuc_pos = 0;
	    while (lit != NULL) {
	      if (lit->atom == f_atom)  /* save position */
		nuc_pos = i;
	      /* negative || answer */
	      else if (!lit->sign || lit->atom->varnum == ANSWER) {
		l1 = get_literal();
		if (nuc_lits == NULL)
		  nuc_lits = l1;
		else
		  l2->next_lit = l1;
		l2 = l1;
		l1->sign = lit->sign;
		l1->atom = lit->atom;
	      }
	      else {  /* put literal into clash structure */
		i++;
		c1 = get_clash_nd();
		if (clash_list == NULL)
		  clash_list = c1;
		else {
		  c2->next = c1;
		  c1->prev = c2;
		}
		c2 = c1;
		c2->db = Fpa_clash_neg_lits;
		c2->subst = get_context();
		c2->subst->multiplier = m++;
		c2->nuc_atom = lit->atom;
		c2->evaluable = (lit->atom->varnum == EVALUABLE);
	      }
	      lit = lit->next_lit;
	    }

	    clash(clash_list, nuc_subst, nuc_lits, nuc,
		  giv_subst, giv_lits, giv_cl,
		  neg_clause, NEG_HYPER_TIME, nuc_pos, 0);

	    /* now deallocate the clash structure and literal nodes */
	    c1 = clash_list;
	    while (c1 != NULL) {
	      free_context(c1->subst);
	      c2 = c1;
	      c1 = c1->next;
	      free_clash_nd(c2);
	    }
	    l1 = nuc_lits;
	    while (l1 != NULL) {
	      l2 = l1;
	      l1 = l1->next_lit;
	      free_literal(l2);
	    }
	    clear_subst_1(tr);
	  }
	  f_atom = next_term(ut, 0);
	}
	l1 = giv_lits;
	while (l1 != NULL) {
	  l2 = l1;
	  l1 = l1->next_lit;
	  free_literal(l2);
	}
      }
      l3 = l3->next_lit;
    }
    free_context(giv_subst);
    free_context(nuc_subst);
    CLOCK_STOP(NEG_HYPER_TIME);
    return;
  }
}  /* neg_hyper_res */

/*************
 *
 *    ur_res(c) -- unit resulting (UR) resolution
 *
 *    Append kept resolvents to Sos.  Each kept
 *    clause has already passed the pre_process filter (forward
 *    subsumption, etc.), been integrated, and inserted into
 *    appropriate indexes.
 *
 *************/

void ur_res(struct clause *giv_cl)
{
  struct literal *lit, *nuc_lits, *giv_lits;
  struct literal *l1, *l2, *l3, *box, *f_lit;
  struct context *nuc_subst, *giv_subst;
  struct clash_nd *clash_list, *c1, *c2;
  struct clause *nuc;
  int m, i, nlits, j, nuc_pos;
  struct term *f_atom;
  struct fpa_tree *ut;
  struct trail *tr;

  CLOCK_START(UR_TIME);
  nlits = num_literals(giv_cl);
  if (nlits == 0) {
    CLOCK_STOP(UR_TIME);
    return;
  }
  if (nlits > 1) {  /* given clause is nucleus (non-unit) */
    clash_list = NULL;
    if(Flags[LAMBDA_FLAG].val)                // Beeson 5.10.04
       nuc_subst = get_context2(giv_cl,0);    // Beeson 5.10.04
    else                                      // Beeson 5.10.04
      { nuc_subst = get_context();  
        nuc_subst->multiplier = 0;
      }
    m = 1;
    nuc_lits = get_literal();  /* for boxed literal */
    l2 = nuc_lits;
    lit = giv_cl->first_lit;
    while (lit != NULL) {
      if (lit->atom->varnum == ANSWER) {  /* if answer literal */
	      l1 = get_literal();
	      l2->next_lit = l1;
	      l2 = l1;
	      l1->sign = lit->sign;
	      l1->atom = lit->atom;
      }
      lit = lit->next_lit;
    }
    c2 = NULL;  /* to quiet lint */
    for (i = 1; i < nlits; i++) {  /* set up nlits-1 empty clash nodes */
       c1 = get_clash_nd();
       if (clash_list == NULL)
	       clash_list = c1;
       else {
	       c2->next = c1;
	       c1->prev = c2;
       }
    c2 = c1;
    if(Flags[LAMBDA_FLAG].val)                // Beeson 5.10.04
       c2->subst = get_context2(giv_cl,m++);  // Beeson 5.10.04
    else                                      // Beeson 5.10.04
       { c2->subst = get_context();
         c2->subst->multiplier = m++;
       }
    }
    box = giv_cl->first_lit;
    if (Flags[UR_LAST].val) {
      /* boxed literal must be the last literal */
      while (box->next_lit)
      	box = box->next_lit;
    }
    i = 1;
    while (box != NULL) {
      if (box->atom->varnum != ANSWER) {  /* if not answer literal */
	      c1 = clash_list;
	      nuc_lits->sign = box->sign;
	      nuc_lits->atom = box->atom;
	      lit = giv_cl->first_lit;
	      while (lit != NULL) {
	         /* if not boxed or answer literal */
	         if (lit != box && lit->atom->varnum != ANSWER) {
	         c1->nuc_atom = lit->atom;
	         c1->db = (lit->sign ? Fpa_clash_neg_lits : Fpa_clash_pos_lits);
	         c1 = c1->next;
	      }
	      lit = lit->next_lit;
	   }
	   if (c1 != NULL) {
	     abend("ur_res: too many clash nodes (nuc).");
	}
	clash(clash_list, nuc_subst, nuc_lits, giv_cl,
	      (struct context *) NULL, (struct literal *) NULL,
	      (struct clause *) NULL,
	      unit_clause, UR_TIME, 0, i);
      }
      box = box->next_lit;
      i++;
    }
    c1 = clash_list;
    while (c1 != NULL) {
      free_context(c1->subst);
      c2 = c1;
      c1 = c1->next;
      free_clash_nd(c2);
    }
    l1 = nuc_lits;
    while (l1 != NULL) {
      l2 = l1;
      l1 = l1->next_lit;
      free_literal(l2);
    }
    free_context(nuc_subst);
    CLOCK_STOP(UR_TIME);
    return;
  }
  else {  /* given clause is satellite (unit) */
    if(Flags[LAMBDA_FLAG].val)                // Beeson 5.10.04
      { giv_subst = get_context2(giv_cl,0);    // Beeson 5.10.04
        nuc_subst = get_context2(giv_cl,1);  /* substitution for nucleus */
      }
    else                                      // Beeson 5.10.04
      { giv_subst = get_context();  /* substitution for given satellite */
        giv_subst->multiplier = 0;
        nuc_subst = get_context();  /* substitution for nucleus */
        nuc_subst->multiplier = 1;
      }
    /* collect any answer literals from given satellite */
    /* and get clashable literal (l3) */
    giv_lits = NULL;
    lit = giv_cl->first_lit;
    l2 = NULL; l3 = NULL; c2 = NULL; 
    while (lit != NULL) {
      if (lit->atom->varnum != ANSWER)  /* if not answer lit */
	      l3 = lit;  /* the only non-answer literal */
      else {
	      l1 = get_literal();
	      if (giv_lits == NULL)
	      giv_lits = l1;
	      else
	      l2->next_lit = l1;
	      l2 = l1;
	      l1->sign = lit->sign;
	      l1->atom = lit->atom;
      }
      lit = lit->next_lit;
    }

    ut = build_tree(l3->atom, UNIFY, Parms[FPA_LITERALS].val,
		    l3->sign ? Fpa_clash_neg_lits : Fpa_clash_pos_lits);
    f_atom = next_term(ut, 0);
    if(f_atom && Flags[LAMBDA_FLAG].val)                        // Beeson 5.10.04
         { // ensure that fs->next_var exceeds all var_nums in giv_cl as well as in 
           // the clause containing f_atom.
           nuc_subst->next_var = max_vars(giv_cl, f_atom);      // Beeson 5.10.04
           memset(nuc_subst->bound,0,MAX_VARS*sizeof(char));    // Beeson 5.10.04
           forbid_bound(nuc_subst,f_atom);                      // Beeson 5.10.04
         }
         
    
    while (f_atom != NULL) {  /* for each potential nucleus */
      tr = NULL;
      f_lit = f_atom->occ.lit;
      nuc = f_lit->container;
      nlits = num_literals(nuc);
      if (nlits > 1 &&
	      (!Flags[UR_LAST].val || f_lit->next_lit) &&
	       unify(l3->atom, giv_subst, f_atom, nuc_subst, &tr)) {
	      /* we have a nucleus */
	      m = 2;
	      nuc_lits = get_literal();  /* for boxed literal */
	      /* now append any answer literals to nuc_lits */
	      l2 = nuc_lits;
	      lit = nuc->first_lit;
	      while (lit != NULL) {
	         if (lit->atom->varnum == ANSWER) {  /* if answer literal */
	         l1 = get_literal();
	         l2->next_lit = l1;
	         l2 = l1;
	         l1->sign = lit->sign;
	         l1->atom = lit->atom;
	      }
	      lit = lit->next_lit;
	   }
	   /* build clash structure for this nucleus */
	   clash_list = NULL;
	   for (i = 2; i < nlits; i++) {  /* nlits-2 empty clash nodes */
	     c1 = get_clash_nd();
	     if (clash_list == NULL)
	       clash_list = c1;
	     else {
	       c2->next = c1;
	       c1->prev = c2;
	     }
	   c2 = c1;
	   if(Flags[LAMBDA_FLAG].val)            // Beeson 5.18.04
	      c2->subst = get_context2(nuc,m++);  // Beeson 5.18.04
	   else
	      { c2->subst = get_context();
	        c2->subst->multiplier = m++;
	      }
	}
	box = nuc->first_lit;
	if (Flags[UR_LAST].val) {
	  /* boxed literal must be the last literal */
	  while (box->next_lit)
	    box = box->next_lit;
	}
	i = 1;
	while (box != NULL) {
	  /* if not clashed or answer literal */
	  if (box != f_lit && box->atom->varnum != ANSWER) {
	    c1 = clash_list;
	    nuc_lits->sign = box->sign;
	    nuc_lits->atom = box->atom;
	    lit = nuc->first_lit;
	    j = 1;
	    nuc_pos = 0;
	    while (lit != NULL) {
	      /* if not boxed or clashed or answer literal */
	      if (lit != box && lit != f_lit && lit->atom->varnum != ANSWER) {
		      c1->nuc_atom = lit->atom;
		      c1->db = (lit->sign ? Fpa_clash_neg_lits :
			      Fpa_clash_pos_lits);
		      c1 = c1->next;
		      j++;
	      }
	      if (lit == f_lit)
		nuc_pos = j;  /* For ordered history option */
	      lit = lit->next_lit;
	    }
	    if ( c1 != NULL)  {
	      abend("ur_res: too many clash nodes (sat).");
	    }
	    clash(clash_list, nuc_subst, nuc_lits, nuc,
		  giv_subst, giv_lits, giv_cl,
		  unit_clause, UR_TIME, nuc_pos, i);
	  }
	  box = box->next_lit;
	  i++;
	}
	c1 = clash_list;
	while (c1 != NULL) {
	  free_context(c1->subst);
	  c2 = c1;
	  c1 = c1->next;
	  free_clash_nd(c2);
	}
	l1 = nuc_lits;
	while (l1 != NULL) {
	  l2 = l1;
	  l1 = l1->next_lit;
	  free_literal(l2);
	}

	clear_subst_1(tr);
      }
      f_atom = next_term(ut, 0);
      if(f_atom && Flags[LAMBDA_FLAG].val)                       // Beeson 6.14.04
         { nuc_subst->next_var = max_vars(giv_cl, f_atom);      // Beeson 6.14.04
           memset(nuc_subst->bound,0,MAX_VARS*sizeof(char));    // Beeson 6.14.04
           forbid_bound(nuc_subst,f_atom);                      // Beeson 6.14.04
         }
    }

    /* free answer literals from given satellite */
    l1 = giv_lits;
    while (l1 != NULL) {
      l2 = l1;
      l1 = l1->next_lit;
      free_literal(l2);
    }

    free_context(giv_subst);
    free_context(nuc_subst);
    CLOCK_STOP(UR_TIME);
    return;
  }
}  /* ur_res */

/*************
 *
 *    int one_unary_answer(c)
 *
 *************/

int one_unary_answer(struct clause *c)
{
  struct literal *l;

  for (l = c->first_lit; l != NULL && l->atom->varnum != ANSWER; l = l->next_lit);  /* empty body */
  if (l == NULL)
    return(0);
  else if (sn_to_arity(l->atom->sym_num) != 1)
    return(0);
  else {
    for (l = l->next_lit; l != NULL && l->atom->varnum != ANSWER; l = l->next_lit);  /* empty body */
    return(l == NULL);
  }
}  /* one_unary_answer */

/*************
 *
 *    struct term *build_term(sn, arg1, arg2, arg3)
 *
 *************/

struct term *build_term(int sn,
			struct term *arg1,
			struct term *arg2,
			struct term *arg3)
{
  int arity;
  struct rel *r1, *r2, *r3;
  struct term *t;

  arity = sn_to_arity(sn);
  if (arity != 3) {
    abend("build_term, bad arity.");
  }
  t = get_term();
  t->sym_num = sn;
  t->type = COMPLEX;
  r1 = get_rel();
  r2 = get_rel();
  r3 = get_rel();
  t->farg = r1;
  r1->narg = r2;
  r2->narg = r3;
  r1->argval = arg1;
  r2->argval = arg2;
  r3->argval = arg3;
  return(t);
}  /* build_term */


/*************
 *
 *    void combine_answers(res, a1, s1, a2, s2)
 *
 *************/

void combine_answers(struct clause *res,
		     struct term *a1,
		     struct context *s1,
		     struct term *a2,
		     struct context *s2)
{
  struct clause *par1, *par2;
  int condition_par1;
  struct term *condition, *then_part, *else_part;
  struct literal *lit1, *lit2, *prev_lit;

  par1 = a1->occ.lit->container;
  par2 = a2->occ.lit->container;

  if (one_unary_answer(par1) && one_unary_answer(par2)) {

    condition_par1 = a2->occ.lit->sign;

    if (condition_par1)
      condition = apply(a1, s1);
    else
      condition = apply(a2, s2);

    for (lit1 = res->first_lit, prev_lit = NULL;
	 lit1->atom->varnum != ANSWER;
	 prev_lit = lit1, lit1 = lit1->next_lit);
    /* empty body */
    for (lit2 = lit1->next_lit; lit2->atom->varnum != ANSWER; lit2 = lit2->next_lit);
    /* empty body */

    if (condition_par1) {
      then_part = lit1->atom->farg->argval;
      else_part = lit2->atom->farg->argval;
    }
    else {
      then_part = lit2->atom->farg->argval;
      else_part = lit1->atom->farg->argval;
    }

    if (prev_lit == NULL)
      res->first_lit = lit1->next_lit;
    else
      prev_lit->next_lit = lit1->next_lit;

    free_rel(lit1->atom->farg);
    free_term(lit1->atom);
    free_literal(lit1);

    lit2->atom->farg->argval = build_term(str_to_sn("if",3),condition,then_part,else_part);
  }

}  /* combine_answers */

/*************
 *
 *    struct clause *build_bin_res(a1, s1, a2, s2)
 *
 *    Build a binary resolvent.  a1 and a2 are the clashed literals,
 *    and s1 and s2 are the respective unifying substitutions.
 *
 *************/

struct clause *build_bin_res(struct term *a1,
			     struct context *s1,
			     struct term *a2,
			     struct context *s2)
{
  struct clause *res;
  struct literal *lit, *new, *prev;
  struct int_ptr *ip0, *ip1, *ip2;

  res = get_clause();
  prev = NULL;
  if(a1->occ.lit == NULL)  // Beeson 10.12.02;  this happens when a1 is $T or $F being resolved with Ap(X,b)
     lit = NULL;           // Beeson 10.12.02
  else                     // Beeson 10.12.02
     lit = a1->occ.lit->container->first_lit;
  while (lit != NULL) {
    if (lit->atom != a1) {
      new = get_literal();
      new->container = res;
      if (prev == NULL)
      	res->first_lit = new;
      else
       	prev->next_lit = new;
      prev = new;
      new->sign = lit->sign;
      new->atom = apply(lit->atom, s1);
      new->atom->occ.lit = new;
      new->atom->varnum = lit->atom->varnum;  /* copy type of atom */
    }
    lit = lit->next_lit;
  }
  if(prev != NULL && 
     (a2->occ.lit == NULL   ||   // Beeson 10.12.02
      a2->occ.lit->container == NULL   // Beeson 10.13.02
     )
    )
     { prev->next_lit = NULL;   // Beeson 10.12.02  This marks the end of the new clause, it won't get any literals from a2.
     }
  if(a2->occ.lit != NULL &&     // Beeson 10.6.02.  Prevent duplicates if a1 or a2 is $T or $F   
     a2->occ.lit->container != NULL &&
     !isFalse(a1) && !isTrue(a1) && !isFalse(a2) && !isTrue(a2)
    )
     lit = a2->occ.lit->container->first_lit; 
  else
     lit = NULL;   
  while (lit != NULL) {
    if (lit->atom != a2) {
      new = get_literal();
      new->container = res;
      if (res->first_lit == NULL)
         res->first_lit = new;
      else
	      prev->next_lit = new;
      prev = new;
      new->sign = lit->sign;
      new->atom = apply(lit->atom, s2);
      new->atom->occ.lit = new;
      new->atom->varnum = lit->atom->varnum;  /* copy type of atom */
    }
    lit = lit->next_lit;
  }

  ip0 = get_int_ptr();
  ip1 = get_int_ptr();
  ip2 = get_int_ptr();
  ip0->i = BINARY_RES_RULE;
  if(a1->occ.lit)    // Beeson 10.12.02
     ip1->i = a1->occ.lit->container->id;
  else                // Beeson 10.12.02
     ip1->i = RESOLVE_WITH_TRUE;    // Beeson 10.12.02
  if(a2->occ.lit && a2->occ.lit->container)        // Beeson 10.13.02
      ip2->i = a2->occ.lit->container->id;
  else                 // Beeson 10.12.02
      ip2->i = RESOLVE_WITH_TRUE;   // Beeson 10.12.02
  ip0->next = ip1;
  ip1->next = ip2;
  res->parents = ip0;

  if (Flags[DETAILED_HISTORY].val) {
    ip0 = get_int_ptr();
    ip1 = get_int_ptr();
    ip0->next = ip1;
    ip1->next = res->parents->next->next->next;
    res->parents->next->next->next = ip0;
    ip0->i = LIST_RULE - 1;
    ip1->i = literal_number(a2->occ.lit);

    ip0 = get_int_ptr();
    ip1 = get_int_ptr();
    ip0->next = ip1;
    ip1->next = res->parents->next->next;
    res->parents->next->next = ip0;
    ip0->i = LIST_RULE - 1;
    ip1->i = literal_number(a1->occ.lit);
	
  }

  if (Flags[PROG_SYNTHESIS].val)
    combine_answers(res, a1, s1, a2, s2);
  return(res);
}  /* build_bin_res */

/*************
 *
 *    struct clause *apply_clause(c, s)
 *
 *************/

struct clause *apply_clause(struct clause *c,
			    struct context *s)
{
  struct clause *d;
  struct literal *lit, *new, *prev;

  d = get_clause();
  prev = NULL;
  for (lit = c->first_lit; lit; lit = lit->next_lit) {
    new = get_literal();
    new->container = d;
    if (!prev)
      d->first_lit = new;
    else
      prev->next_lit = new;
    prev = new;
    new->sign = lit->sign;
    new->atom = apply(lit->atom, s);
    new->atom->occ.lit = new;
    new->atom->varnum = lit->atom->varnum;  /* copy type of atom */
  }
  return(d);
}  /* apply_clause */

/*************
 *
 *    bin_res(giv_cl) -- binary resolution
 *
 *************/

void bin_res(struct clause *giv_cl)
{
  struct literal *g_lit;
  struct term *g_atom, *f_atom;
  struct context *gs, *fs;
  struct trail *tr;
  struct fpa_tree *ut;
  struct fpa_index *db;
  struct clause *resolvent;
  int given_unit = unit_clause(giv_cl);

  CLOCK_START(BINARY_TIME);
  if(Flags[LAMBDA_FLAG].val)    // Beeson 6.26.03
     { gs = get_context2(giv_cl,0);   // Beeson changed from get_context 10.6.02
       fs = get_context2(giv_cl,1);   // Beeson changed from get_context 10.6.02
       memset(fs->bound,0,MAX_VARS*sizeof(char));  // Beeson 7.16.03
       free_forbidden(fs);           // Beeson 1.29.04
     }
  else     
     { gs = get_context();
       gs->multiplier = 0;
       fs = get_context();  
       fs->multiplier = 1;
     }
  g_lit = giv_cl->first_lit;
  while (g_lit != NULL) {
    g_atom = g_lit->atom;
    if (g_atom->varnum != ANSWER)  {  /* if not answer literal */
      if (g_lit->sign)  
	     db = Fpa_clash_neg_lits;
      else
	     db = Fpa_clash_pos_lits;
      ut = build_tree(g_lit->atom, UNIFY,
		      Parms[FPA_LITERALS].val, db);
      f_atom = next_term(ut, 0);
      if(f_atom)                                        // Beeson 2.13.03
         { // ensure that fs->next_var exceeds all var_nums in giv_cl as well as in 
           // the clause containing f_atom.
           fs->next_var = max_vars(giv_cl, f_atom);       // Beeson
           memset(fs->bound,0,MAX_VARS*sizeof(char));    // Beeson 1.29.04
           forbid_bound(fs,f_atom);                      // Beeson 7.16.03
           fs->next = NULL;                              // Beeson 12.19.05
         }
      if(f_atom == NULL && 
         g_atom->sym_num == AP &&
         g_atom->farg->argval->type == VARIABLE
        ){  // Beeson 10.6.02
         /* unify Ap(X,a) with $F or $T  according to g_lit->sign  */
         if(!g_lit->sign)          // Beeson 10.10.02
            f_atom = True(NULL);   // Beeson 10.10.02
         else                      // Beeson 10.10.02
            f_atom = False(NULL);  // Beeson 10.10.02
         ++f_atom->fpa_id;         // Beeson 10.13.02;  now there's a reference to f_atom
         f_atom->occ.lit = get_literal();   // so it will count as an atom
      }                            // Beeson 10.10.02
      while (f_atom != NULL) {
	     tr = NULL;
	     if(Flags[LAMBDA_FLAG].val)
	        {  free_forbidden(gs);                           // Beeson 1.29.04
	           free_context(gs);                             // Beeson 1.29.04
	           gs = get_context2(giv_cl,0);                  // Beeson 1.29.04
	           fs->next_var = gs->next_var = max_vars(giv_cl, f_atom);  // Beeson 7.22.03  
	           fs->next = NULL;                              // Beeson 12.19.05
	           memset(fs->bound,0,MAX_VARS*sizeof(char));    // Beeson 1.29.04
               forbid_bound(fs,f_atom);                      // Beeson 1.29.04
           }
	     if (!Flags[UNIT_RES].val ||
	         given_unit ||
	         f_atom->occ.lit->container == NULL  ||  // $T or $F  // Beeson 10.13.02
	         unit_clause(f_atom->occ.lit->container)
	        )
	        {  if (unify(g_atom, gs, f_atom, fs, &tr)) 
	             { struct context *m1,*m2;
	               for(m1=gs,m2=fs; m1; m1=m1->next,m2=m2->next)  // Beeson 12.18.05 for multiple unifiers
	                 { resolvent = build_bin_res(g_atom, m1, f_atom, m2);
	                   Stats[CL_GENERATED]++;
	                   Stats[BINARY_RES_GEN]++;
	                   if (heat_is_on())
	                      resolvent->heat_level = giv_cl->heat_level + 1;
	                   CLOCK_STOP(BINARY_TIME);
	                   pre_process(resolvent, 0, Sos);
	                   CLOCK_START(BINARY_TIME);
	                 }     
	               clear_subst_1(tr);
	             }  
	        }
	     f_atom = next_term(ut, 0);
      }
    }
    g_lit = g_lit->next_lit;
  }
  free_context(gs);
  free_context(fs);
  CLOCK_STOP(BINARY_TIME);
}  /* bin_res */

/*************
 *
 *   first_or_next_factor(c, l1p, l2p)
 *
 *   Generate the first (*l1p == NULL) or next (*l1p and *l2p are the
 *   previously factored literals) factor from c.
 *
 *************/

struct clause *first_or_next_factor(struct clause *c,
				    struct literal **l1p,
				    struct literal **l2p)
{
  int factored = 0;
  struct literal *l1 = *l1p;
  struct literal *l2 = *l2p;
  struct context *subst;
  struct trail *tr;
  struct clause *factor;
  struct literal *l3, *l4, *l5;
  if(Flags[LAMBDA_FLAG].val)
     subst = get_context2(c,0);  // Beeson changed to get_context2,  10.6.02
  else
     subst = get_context();
  if (!l1)
    l1 = l2 = c->first_lit;

  while (l1 && !factored) {
    l2 = l2->next_lit;
    while (l2 && !factored) {
      tr = NULL;
      if (l1->sign == l2->sign &&
          unify(l1->atom, subst, l2->atom, subst, &tr)
         ) {
	     factored = 1;
      }
      else
        l2 = l2->next_lit;
    }
  if (!factored)
      l1 = l2 = l1->next_lit;
  }

  if (factored) {
    subst->multiplier = 0;
    factor = get_clause();
    /* do not fill in parents */
    l3 = NULL;
    l5 = c->first_lit;
    while (l5 != NULL) {  /* l2 is the literal to exclude */
      if (l5 != l2) {
	      l4 = get_literal();
	      l4->sign = l5->sign;
	      l4->container = factor;
	      if (l3 == NULL)
	         factor->first_lit = l4;
	      else
	         l3->next_lit = l4;
	      l4->atom = apply(l5->atom, subst);
	      /* Following is for factor_simp; shouldn't hurt otherwise. */
	      if (TP_BIT(l5->atom->bits, ORIENTED_EQ_BIT))
	      SET_BIT(l4->atom->bits, ORIENTED_EQ_BIT);
	      l4->atom->occ.lit = l4;
	      l4->atom->varnum = l5->atom->varnum;  /* copy type */
	      l3 = l4;
         }
      l5 = l5->next_lit;
   }
   clear_subst_1(tr);
   *l2p = l2; *l1p = l1;
  }
  else
    factor = NULL;

  free_context(subst);
  return(factor);
}  /* first_or_next_factor */

/*************
 *
 *    all_factors(c, lst) -- generate and pre_process all binary factors c.
 *
 *    Indirect recursive calls will get factors of factors, etc.
 *
 *************/

void all_factors(struct clause *c,
		 struct list *lst)
{
  struct literal *l1, *l2;
  struct clause *factor;
  struct int_ptr *ip0, *ip1;

  l1 = NULL;
  factor = first_or_next_factor(c, &l1, &l2);
  while (factor) {
    ip0 = get_int_ptr(); ip0->i = FACTOR_RULE;
    ip1 = get_int_ptr(); ip1->i = c->id;
    factor->parents = ip0; ip0->next = ip1;
    if (Flags[DETAILED_HISTORY].val) {
      /* append list of indexes of factored literals */
      struct int_ptr *ip3, *ip4, *ip5;
      ip3 = get_int_ptr(); ip3->i = LIST_RULE-2;
      ip4 = get_int_ptr(); ip4->i = literal_number(l1);
      ip5 = get_int_ptr(); ip5->i = literal_number(l2);
      ip1->next = ip3; ip3->next = ip4; ip4->next = ip5;
    }

    Stats[CL_GENERATED]++;
    Stats[FACTOR_GEN]++;
    CLOCK_STOP(FACTOR_TIME);
    CLOCK_STOP(POST_PROC_TIME);
    pre_process(factor, 0, lst);
    CLOCK_START(POST_PROC_TIME);
    CLOCK_START(FACTOR_TIME);
    factor = first_or_next_factor(c, &l1, &l2);
  }
}  /* all_factors */

/*************
 *
 *   factor_simpify(c)
 *
 *   Return the number of literals removed.
 *
 *************/

int factor_simplify(struct clause *c)
{
  struct literal *l1, *l2;
  struct clause *f;
  struct int_ptr *p0, *p1;
  int n = 0;

  l1 = NULL;
  f = first_or_next_factor(c, &l1, &l2);
  while (f) {
    if (subsume(f, c)) {
      n++;
      /* Swap list of literals. */
      l1 = c->first_lit;
      c->first_lit = f->first_lit;
      f->first_lit = l1;
      for (l1 = c->first_lit; l1; l1 = l1->next_lit)
	      l1->container = c;
      for (l1 = f->first_lit; l1; l1 = l1->next_lit)
	      l1->container = f;
      cl_del_non(f);

      if (Flags[DETAILED_HISTORY].val) {
	      for (p1 = c->parents, p0 = NULL; p1; p1 = p1->next)
	         p0 = p1;
	      p1 = get_int_ptr();
	      p1->i = FACTOR_SIMP_RULE;
	      if (p0)
	      p0->next = p1;
	      else
	      c->parents = p1;
      }

      l1 = NULL;
      f = first_or_next_factor(c, &l1, &l2);
    }
    else {
      cl_del_non(f);
      f = first_or_next_factor(c, &l1, &l2);
    }
  }
  return(n);
}  /* factor_simplify */

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists