| /**************************************************************/ |
| /* ********************************************************** */ |
| /* * * */ |
| /* * 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$ * */ |
| /* $State$ * */ |
| /* $Date$ * */ |
| /* $Author$ * */ |
| /* * * */ |
| /* * 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; |
| } |