ord_RESULT rpos_GreaterEqual(TERM T1, TERM T2, BOOL VarIsConst) /************************************************************** 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! If <VarIsConst> is set then variables are interpreted as constants with lowest precedence. They are ranked to each other using their variable index. ***************************************************************/ { LIST scan; if (term_IsVariable(T1)) { if (term_EqualTopSymbols(T1, T2)) return ord_Equal(); /* T2 is the same variable */ else if(VarIsConst && term_IsVariable(T2)) { if(term_TopSymbol(T1) > term_TopSymbol(T2)) return ord_GreaterThan(); else return ord_Uncomparable(); } else /* A variable can't be greater than another term */ return ord_Uncomparable(); } else if (!VarIsConst && term_IsVariable(T2)) { /* T1 isn't a variable */ if (term_ContainsSymbol(T1, term_TopSymbol(T2))) return ord_GreaterThan(); else return ord_Uncomparable(); } else if(VarIsConst && term_IsVariable(T2)){ return ord_GreaterThan(); } else if (term_EqualTopSymbols(T1, T2)) { if (symbol_HasProperty(term_TopSymbol(T1), ORDMUL)) return rpos_MulGreaterEqual(T1, T2, VarIsConst); else return rpos_LexGreaterEqual(T1, T2, VarIsConst); } 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), VarIsConst)) 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, VarIsConst))) return ord_GreaterThan(); /* Argument of T1 >= T2 */ return ord_Uncomparable(); } } }
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(); } } }
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 */ } } }
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 */ } } }
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_TermEqual(CONTEXT GlobalContext1, CONTEXT TermContext1, TERM Term1, CONTEXT GlobalContext2, CONTEXT TermContext2, TERM Term2) /********************************************************* INPUT: Two terms and two local contexts for the terms and two global contexts RETURNS: TRUE iff the two terms are equal, where variables are interpreted with respect to the bindings in the contexts. CAUTION: Variables of <Term1> and <Term2> are bound in <TermContext1> and <TermContext2> respectively and the index variables are bound in <GlobalContext1> and <GlobalContext2> respectively. ********************************************************/ { #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(GlobalContext1,&TermContext1,Term1); Term2 = cont_Deref(GlobalContext2,&TermContext2,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(GlobalContext1, TermContext1,list_Car(Scan1), GlobalContext2, TermContext2,list_Car(Scan2))) return FALSE; return (list_Empty(Scan1) ? list_Empty(Scan2) : FALSE); } else return TRUE; }
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; }
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; }
ord_RESULT rpos_ContGreaterEqual(CONTEXT GlobalC1, CONTEXT TermC1, TERM T1, CONTEXT GlobalC2, CONTEXT TermC2, TERM T2, BOOL VarIsConst) /************************************************************** 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! If <VarIsConst> is set then variables are interpreted as constants with lowest precedence. They are ranked to each other using their variable index. ASSUMPTION: All index variables of <T1> and <T2> are bound in <GlobalC1> and <GlobalCt2>, respectively ***************************************************************/ { LIST scan; T1 = cont_Deref(GlobalC1, &TermC1, T1); T2 = cont_Deref(GlobalC2, &TermC2, 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(GlobalC1, TermC1, 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(GlobalC1, TermC1, T1, GlobalC2, TermC2, T2, VarIsConst); else return rpos_ContLexGreaterEqual(GlobalC1, TermC1, T1, GlobalC2, TermC2, T2, VarIsConst); } 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_ContGreaterAux(GlobalC1, TermC1, T1, GlobalC2, TermC2, list_Car(scan), VarIsConst)) 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(GlobalC1, TermC1,list_Car(scan), GlobalC2, TermC2,T2, VarIsConst))) return ord_GreaterThan(); /* Argument of T1 >= T2 */ return ord_Uncomparable(); } } }