Example #1
0
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))));
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
  int       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_SetFlagIntValue(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;
}