/**************************************************************/ /* ********************************************************** */ /* * * */ /* * FIRST ORDER LOGIC SYMBOLS * */ /* * * */ /* * $Module: FOL DFG * */ /* * * */ /* * 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: 21527 $ * */ /* $State$ * */ /* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */ /* $Author: duraid $ * */ /* * * */ /* * Contact: * */ /* * Christoph Weidenbach * */ /* * MPI fuer Informatik * */ /* * Stuhlsatzenhausweg 85 * */ /* * 66123 Saarbruecken * */ /* * Email: weidenb@mpi-sb.mpg.de * */ /* * Germany * */ /* * * */ /* ********************************************************** */ /**************************************************************/ /* $RCSfile$ */ #include "foldfg.h" #include "flags.h" SYMBOL fol_ALL; SYMBOL fol_EXIST; SYMBOL fol_AND; SYMBOL fol_OR; SYMBOL fol_NOT; SYMBOL fol_IMPLIES; SYMBOL fol_IMPLIED; SYMBOL fol_EQUIV; SYMBOL fol_VARLIST; SYMBOL fol_EQUALITY; SYMBOL fol_TRUE; SYMBOL fol_FALSE; LIST fol_SYMBOLS; /**************************************************************/ /* ********************************************************** */ /* * * */ /* * FUNCTIONS * */ /* * * */ /* ********************************************************** */ /**************************************************************/ void fol_Init(BOOL All, PRECEDENCE Precedence) /************************************************************** INPUT: A boolean value determining whether only 'equality' or all fol symbols are created, and a precedence. RETURNS: Nothing. SUMMARY: Initializes the Fol Module. EFFECTS: If then all fol-symbols are created, only 'equality' otherwise. The precedence of the first order logic symbols is set in . CAUTION: MUST BE CALLED BEFORE ANY OTHER fol-FUNCTION. ***************************************************************/ { if (All) { fol_ALL = symbol_CreateJunctor("forall", 2, symbol_STATLEX, Precedence); fol_EXIST = symbol_CreateJunctor("exists", 2, symbol_STATLEX, Precedence); fol_AND = symbol_CreateJunctor("and", symbol_ArbitraryArity(), symbol_STATLEX, Precedence); fol_OR = symbol_CreateJunctor("or", symbol_ArbitraryArity(), symbol_STATLEX, Precedence); fol_NOT = symbol_CreateJunctor("not", 1, symbol_STATLEX, Precedence); fol_IMPLIES = symbol_CreateJunctor("implies", 2, symbol_STATLEX, Precedence); fol_IMPLIED = symbol_CreateJunctor("implied", 2, symbol_STATLEX, Precedence); fol_EQUIV = symbol_CreateJunctor("equiv", 2, symbol_STATLEX, Precedence); fol_VARLIST = symbol_CreateJunctor("", symbol_ArbitraryArity(), symbol_STATLEX, Precedence); fol_EQUALITY = symbol_CreatePredicate("equal", 2, symbol_STATLEX, Precedence); fol_TRUE = symbol_CreatePredicate("true", 0, symbol_STATLEX, Precedence); fol_FALSE = symbol_CreatePredicate("false", 0, symbol_STATLEX, Precedence); fol_SYMBOLS = list_Cons((POINTER)fol_ALL, list_Cons((POINTER)fol_EXIST, list_Cons((POINTER)fol_AND, list_Cons((POINTER)fol_OR, list_Cons((POINTER)fol_NOT, list_Cons((POINTER)fol_IMPLIES, list_Cons((POINTER)fol_IMPLIED, list_Cons((POINTER)fol_EQUIV, list_Cons((POINTER)fol_VARLIST, list_Cons((POINTER)fol_EQUALITY, list_Cons((POINTER)fol_TRUE, list_List((POINTER)fol_FALSE)))))))))))); } else { fol_EQUALITY = symbol_CreatePredicate("equal", 2, symbol_STATLEX, Precedence); fol_NOT = symbol_CreateJunctor("not", 1, symbol_STATLEX, Precedence); fol_SYMBOLS = list_Cons((POINTER)fol_NOT, list_List((POINTER)fol_EQUALITY)); } } SYMBOL fol_IsStringPredefined(const char* String) /************************************************************** INPUT: A string. RETURNS: The symbol iff String is a predefined fol string, symbol NULL otherwise ***************************************************************/ { LIST Scan; for (Scan=fol_SYMBOLS; !list_Empty(Scan); Scan=list_Cdr(Scan)) if (string_Equal(String, symbol_Name((SYMBOL)list_Car(Scan)))) return (SYMBOL)list_Car(Scan); return symbol_Null(); } TERM fol_CreateQuantifier(SYMBOL Quantifier, LIST VarList, LIST Arguments) /************************************************************** INPUT: A symbol (which MUST be a fol quantifier), a list of variables that will be bound, and a list of arguments. RETURNS: A quantified term. ***************************************************************/ { #ifdef CHECK if (!fol_IsQuantifier(Quantifier)) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_CreateQuantifier: Symbol isn't FOL quantifier.\n"); misc_FinishErrorReport(); } #endif return term_Create(Quantifier, list_Cons(term_Create(fol_Varlist(), VarList), Arguments)); } TERM fol_CreateQuantifierAddFather(SYMBOL Quantifier, LIST VarList, LIST Arguments) /************************************************************** INPUT: A symbol (which MUST be a fol quantifier), a list of variables that will be bound, and a list of arguments. In contrast to fol_CreateQuantifier the superterm members are set for the arguments. RETURNS: A quantified term. ***************************************************************/ { return term_CreateAddFather(Quantifier, list_Cons(term_CreateAddFather(fol_Varlist(), VarList), Arguments)); } TERM fol_ComplementaryTerm(TERM Term) /************************************************************** INPUT: A formula. RETURNS: The (copied) complementary (in sign) formula of ***************************************************************/ { if (symbol_Equal(term_TopSymbol(Term), fol_Not())) return term_Copy((TERM)list_First(term_ArgumentList(Term))); else return term_Create(fol_Not(), list_List(term_Copy(Term))); } LIST fol_GetNonFOLPredicates(void) /************************************************************** INPUT: None. RETURNS: The list of all predicate symbols except the predefined FOL symbols. ***************************************************************/ { LIST Result; Result = symbol_GetAllPredicates(); Result = list_DeleteElementIf(Result, (BOOL (*)(POINTER))fol_IsPredefinedPred); return Result; } LIST fol_GetAssignments(TERM Term) /************************************************************** INPUT: A formula. RETURNS: All assignemnts that occur inside the formula, i.e., equations of the form "x=t" where "x" does not occur in "t". ***************************************************************/ { if (term_IsAtom(Term)) { if (fol_IsAssignment(Term)) return list_List(Term); } else if (term_IsComplex(Term)) { LIST Scan,Result; Result = list_Nil(); for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) Result = list_Nconc(fol_GetAssignments(list_Car(Scan)),Result); return Result; } return list_Nil(); } static void fol_NormalizeVarsIntern(TERM Formula) /************************************************************** INPUT: A sentence. RETURNS: void. EFFECT: The quantifier variables of the formula are normalized, i.e., no two different quantifiers bind the same variable. CAUTION: Desctructive. ***************************************************************/ { SYMBOL Top; LIST Scan1; #ifdef CHECK if (!term_IsTerm(Formula)) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_NormalizeVarsIntern: Formula is corrupted.\n"); misc_FinishErrorReport(); } #endif Top = term_TopSymbol(Formula); if (term_IsComplex(Formula)) { if (fol_IsQuantifier(Top)) { SYMBOL Var; LIST OldVars,Scan2; OldVars = list_Nil(); for (Scan1=fol_QuantifierVariables(Formula);!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) { Var = term_TopSymbol(list_Car(Scan1)); OldVars = list_Nconc(OldVars,list_List((POINTER)term_BindingValue(Var))); term_CreateValueBinding(Var, term_OldMark(), (POINTER)symbol_CreateStandardVariable()); } fol_NormalizeVarsIntern(term_SecondArgument(Formula)); for (Scan1=fol_QuantifierVariables(Formula),Scan2=OldVars; !list_Empty(Scan1); Scan1=list_Cdr(Scan1),Scan2=list_Cdr(Scan2)) { Var = term_TopSymbol(list_Car(Scan1)); term_RplacTop(list_Car(Scan1),(SYMBOL)term_BindingValue(Var)); term_CreateValueBinding(Var, term_OldMark(), list_Car(Scan2)); } list_Delete(OldVars); } else for (Scan1=term_ArgumentList(Formula);!list_Empty(Scan1);Scan1=list_Cdr(Scan1)) fol_NormalizeVarsIntern(list_Car(Scan1)); } else if (symbol_IsVariable(Top)) term_RplacTop(Formula,(SYMBOL)term_BindingValue(Top)); return; } void fol_NormalizeVars(TERM Formula) /************************************************************** INPUT: A sentence. RETURNS: void. EFFECT: The quantifier variables of the formula are normalized, i.e., no two different quantifiers bind the same variable. CAUTION: Destructive. ***************************************************************/ { symbol_ResetStandardVarCounter(); term_NewMark(); fol_NormalizeVarsIntern(Formula); } void fol_NormalizeVarsStartingAt(TERM Formula, SYMBOL S) /************************************************************** INPUT: A sentence. RETURNS: void. EFFECT: The quantifier variables of the formula are normalized, i.e., no two different quantifiers bind the same variable. CAUTION: Destructive. ***************************************************************/ { SYMBOL old = symbol_STANDARDVARCOUNTER; symbol_SetStandardVarCounter(S); term_NewMark(); fol_NormalizeVarsIntern(Formula); symbol_SetStandardVarCounter(old); } void fol_RemoveImplied(TERM Formula) /********************************************************* INPUT: A formula. RETURNS: void. EFFECT: All occurrences of "implied" are replaced by "implies" CAUTION: Destructive. *******************************************************/ { if (!fol_IsLiteral(Formula)) { if (fol_IsQuantifier(term_TopSymbol(Formula))) fol_RemoveImplied(term_SecondArgument(Formula)); else { LIST Scan; if (symbol_Equal(term_TopSymbol(Formula),fol_Implied())) { term_RplacTop(Formula,fol_Implies()); term_RplacArgumentList(Formula,list_NReverse(term_ArgumentList(Formula))); } for (Scan=term_ArgumentList(Formula);!list_Empty(Scan);Scan=list_Cdr(Scan)) fol_RemoveImplied(list_Car(Scan)); } } } BOOL fol_VarOccursFreely(TERM Var,TERM Term) /************************************************************** INPUT: A variable and a term. RETURNS: TRUE iff occurs freely in ***************************************************************/ { LIST Scan; int Stack; SYMBOL Top; BOOL Hit; #ifdef CHECK if (!term_IsTerm(Term) || !term_IsVariable(Var)) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_VarOccursFreely: Illegal input.\n"); misc_FinishErrorReport(); } #endif Stack = stack_Bottom(); do { Top = term_TopSymbol(Term); if (term_IsComplex(Term)) { if (fol_IsQuantifier(Top)) { Hit = TRUE; for (Scan=fol_QuantifierVariables(Term);!list_Empty(Scan)&&Hit;Scan=list_Cdr(Scan)) if (symbol_Equal(term_TopSymbol(list_Car(Scan)),term_TopSymbol(Var))) Hit = FALSE; if (Hit) stack_Push(list_Cdr(term_ArgumentList(Term))); } else stack_Push(term_ArgumentList(Term)); } else { if (symbol_IsVariable(Top) && symbol_Equal(Top,term_TopSymbol(Var))) { stack_SetBottom(Stack); return TRUE; } } while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { Term = (TERM)list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); return FALSE; } LIST fol_FreeVariables(TERM Term) /************************************************************** INPUT: A term where we assume that no variable is bound by more than one quantifier in !!!!! RETURNS: The list of variables occurring in the term. Variables are not (!) copied. Note that there may be many terms with same variable symbol. All Variable terms are newly created. ***************************************************************/ { LIST Variables,Scan; int Stack; SYMBOL Top; NAT BoundMark,FreeMark; #ifdef CHECK if (!term_IsTerm(Term) || term_InBindingPhase()) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_FreeVariables: Illegal input or context.\n"); misc_FinishErrorReport(); } #endif term_StartBinding(); Variables = list_Nil(); Stack = stack_Bottom(); BoundMark = term_ActMark(); FreeMark = term_ActMark(); do { Top = term_TopSymbol(Term); if (term_IsComplex(Term)) { if (fol_IsQuantifier(Top)) { for (Scan=fol_QuantifierVariables(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) if (!term_VarIsMarked(term_TopSymbol(list_Car(Scan)), FreeMark)) term_CreateBinding(term_TopSymbol(list_Car(Scan)), BoundMark); stack_Push(term_ArgumentList(Term)); /* Mark has to be removed ! */ stack_Push(list_Cdr(term_ArgumentList(Term))); } else if (symbol_Equal(Top,fol_Varlist())) { for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) if (!term_VarIsMarked(term_TopSymbol(list_Car(Scan)), FreeMark)) term_CreateBinding(term_TopSymbol(list_Car(Scan)), 0); /* Mark has to be removed ! */ stack_RplacTop(list_Cdr(stack_Top())); /* Second Argument is Quantifier Arg */ } else stack_Push(term_ArgumentList(Term)); } else { if (symbol_IsVariable(Top) && !term_VarIsMarked(Top, FreeMark) && !term_VarIsMarked(Top, BoundMark)) { Variables = list_Cons(Term, Variables); term_CreateBinding(Top, FreeMark); } } while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { Term = (TERM)list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); term_StopBinding(); return Variables; } LIST fol_BoundVariables(TERM Term) /************************************************************** INPUT: A term RETURNS: The list of bound variables occurring in the term. ***************************************************************/ { int stack; LIST result; stack = stack_Bottom(); result = list_Nil(); do { if (fol_IsQuantifier(term_TopSymbol(Term))) { result = list_Nconc(result, list_Copy(fol_QuantifierVariables(Term))); stack_Push(list_Cdr(term_ArgumentList(Term))); } else if (term_IsComplex(Term)) stack_Push(term_ArgumentList(Term)); while (!stack_Empty(stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(stack)) { Term = list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(stack)); result = term_DeleteDuplicatesFromList(result); return result; } void fol_Free(void) /************************************************************** INPUT: None. RETURNS: void. EFFECT: The memory used by the fol modul is freed. ***************************************************************/ { list_Delete(fol_SYMBOLS); } BOOL fol_FormulaIsClause(TERM Formula) /************************************************************** INPUT: A formula. RETURNS: TRUE, if is a clause, FALSE otherwise. ***************************************************************/ { LIST LitList; if (term_TopSymbol(Formula) == fol_ALL) Formula = term_SecondArgument(Formula); if (term_TopSymbol(Formula) != fol_OR) return FALSE; LitList = term_ArgumentList(Formula); while (!list_Empty(LitList)) { if (!fol_IsLiteral(list_Car(LitList))) return FALSE; LitList = list_Cdr(LitList); } return TRUE; } void fol_FPrintOtterOptions(FILE* File, BOOL Equality, FLAG_TDFG2OTTEROPTIONSTYPE Options) /************************************************************** INPUT: A file, a boolean flag and an Flag determining printed options. RETURNS: Nothing. SUMMARY: Prints Otter Options to . If then appropriate paramodulation options are possibly added. ***************************************************************/ { switch (Options) { case flag_TDFG2OTTEROPTIONSPROOFCHECK: fputs("\nset(process_input).", File); fputs("\nset(binary_res).", File); fputs("\nset(factor).", File); /*fputs("\nassign(pick_given_ratio, 4).", File);*/ fputs("\nclear(print_kept).", File); fputs("\nassign(max_seconds, 20).", File); if (Equality) { fputs("\nclear(print_new_demod).", File); fputs("\nclear(print_back_demod).", File); fputs("\nclear(print_back_sub).", File); /*fputs("\nset(knuth_bendix).", File);*/ fputs("\nset(para_from).", File); fputs("\nset(para_into).", File); fputs("\nset(para_from_vars).", File); fputs("\nset(back_demod).", File); } /* No break: add auto */ case flag_TDFG2OTTEROPTIONSAUTO: fputs("\nset(auto).", File); break; case flag_TDFG2OTTEROPTIONSAUTO2: fputs("\nset(auto2).", File); break; case flag_TDFG2OTTEROPTIONSOFF: /* print nothing */ break; default: misc_StartErrorReport(); misc_ErrorReport("\n In fol_FPrintOtterOptions: Illegal parameter value %d.", Options); misc_FinishErrorReport(); } fputs("\n\n",File); } static void fol_FPrintOtterFormula(FILE* File, TERM Formula) /************************************************************** INPUT: A file and a formula. RETURNS: Nothing. SUMMARY: Prints the formula in Otter format to . ***************************************************************/ { SYMBOL Top; Top = term_TopSymbol(Formula); if (symbol_IsPredicate(Top)) { if (symbol_Equal(Top, fol_Equality())) { term_FPrintOtterPrefix(File,term_FirstArgument(Formula)); fputs(" = ", File); term_FPrintOtterPrefix(File,term_SecondArgument(Formula)); } else term_FPrintOtterPrefix(File,Formula); } else { if (fol_IsQuantifier(Top)) { LIST Scan; for (Scan=fol_QuantifierVariables(Formula);!list_Empty(Scan);Scan=list_Cdr(Scan)) { if (symbol_Equal(Top,fol_All())) fputs("all ", File); else fputs("exists ", File); term_FPrintOtterPrefix(File, list_Car(Scan)); fputs(" (", File); } fol_FPrintOtterFormula(File, term_SecondArgument(Formula)); for (Scan=fol_QuantifierVariables(Formula);!list_Empty(Scan);Scan=list_Cdr(Scan)) fputs(")", File); } else if (symbol_Equal(Top,fol_Not())) { fputs("- (", File); fol_FPrintOtterFormula(File, term_FirstArgument(Formula)); fputs(")", File); } else if (symbol_Equal(Top, fol_And()) || symbol_Equal(Top, fol_Or()) || symbol_Equal(Top, fol_Equiv()) || symbol_Equal(Top, fol_Implies()) ) { LIST Scan; fputs("(", File); for (Scan=term_ArgumentList(Formula);!list_Empty(Scan);Scan=list_Cdr(Scan)) { if (fol_IsLiteral(list_Car(Scan))) fol_FPrintOtterFormula(File, list_Car(Scan)); else { fputs("(", File); fol_FPrintOtterFormula(File, list_Car(Scan)); fputs(")", File); } if (!list_Empty(list_Cdr(Scan))) { if (symbol_Equal(Top, fol_And())) fputs(" & ", File); if (symbol_Equal(Top, fol_Or())) fputs(" | ", File); if (symbol_Equal(Top, fol_Equiv())) fputs(" <-> ", File); if (symbol_Equal(Top, fol_Implies())) fputs(" -> ", File); } } fputs(")", File); } } } void fol_FPrintOtter(FILE* File, LIST Formulae, FLAG_TDFG2OTTEROPTIONSTYPE Option) /************************************************************** INPUT: A file, a list of pairs (label.formula) and an option flag. RETURNS: Nothing. SUMMARY: Prints a the respective formulae in Otter format to . ***************************************************************/ { LIST Scan; BOOL Equality; TERM Formula; Equality = FALSE; for (Scan=Formulae;!list_Empty(Scan) && !Equality; Scan=list_Cdr(Scan)) { Formula = (TERM)list_PairSecond(list_Car(Scan)); Equality = term_ContainsSymbol(Formula, fol_Equality()); } fol_FPrintOtterOptions(File, Equality, Option); if (!list_Empty(Formulae)) { fputs("formula_list(usable).\n", File); if (Equality) fputs("all x (x=x).\n", File); for (Scan=Formulae;!list_Empty(Scan);Scan=list_Cdr(Scan)) { if (list_PairFirst(list_Car(Scan)) != NULL) fprintf(File,"\n%% %s \n",(char *)list_PairFirst(list_Car(Scan))); fol_FPrintOtterFormula(File,list_PairSecond(list_Car(Scan))); fputs(".\n\n", File); } fputs("end_of_list.\n\n", File); } } void fol_FPrintDFGSignature(FILE* File) /************************************************************** INPUT: A file stream. RETURNS: Nothing. SUMMARY: Prints all signature symbols in DFG format to the file stream. ***************************************************************/ { NAT i; SYMBOL symbol; LIST functions, predicates; functions = symbol_GetAllFunctions(); predicates = fol_GetNonFOLPredicates(); /* First print the function symbols */ if (!list_Empty(functions)) { fputs(" functions[", File); i = 0; do { symbol = (SYMBOL) list_Top(functions); fprintf(File, "(%s, %d)", symbol_Name(symbol), symbol_Arity(symbol)); functions = list_Pop(functions); if (!list_Empty(functions)) fputs(", ", File); if (i < 15) i++; else { i = 0; fputs("\n\t", File); } } while (!list_Empty(functions)); fputs("].\n", File); } /* Now print the predicate symbols */ if (!list_Empty(predicates)) { i = 0; fputs(" predicates[", File); do { symbol = (SYMBOL) list_Top(predicates); fprintf(File, "(%s, %d)", symbol_Name(symbol), symbol_Arity(symbol)); predicates = list_Pop(predicates); if (!list_Empty(predicates)) fputs(", ", File); if (i < 15) i++; else { i = 0; fputs("\n\t", File); } } while (!list_Empty(predicates)); fputs("].\n", File); } list_Delete(predicates); list_Delete(functions); } static void fol_TermListFPrintDFG(FILE* File, LIST List) /************************************************************** INPUT: A list of terms. RETURNS: Nothing. ***************************************************************/ { for (; !list_Empty(List); List=list_Cdr(List)) { fol_FPrintDFG(File,list_Car(List)); if (!list_Empty(list_Cdr(List))) putc(',', File); } } void fol_FPrintDFG(FILE* File, TERM Term) /************************************************************** INPUT: A file and a term. RETURNS: none. SUMMARY: Prints the term in prefix notation to the file. CAUTION: Uses the other fol_Output functions. ***************************************************************/ { if (term_IsComplex(Term)) { if (fol_IsQuantifier(term_TopSymbol(Term))) { symbol_FPrint(File,term_TopSymbol(Term)); fputs("([", File); fol_TermListFPrintDFG(File,fol_QuantifierVariables(Term)); fputs("],", File); fol_FPrintDFG(File, term_SecondArgument(Term)); putc(')', File); } else { symbol_FPrint(File,term_TopSymbol(Term)); putc('(', File); fol_TermListFPrintDFG(File,term_ArgumentList(Term)); putc(')', File); } } else symbol_FPrint(File,term_TopSymbol(Term)); } void fol_PrintDFG(TERM Term) { fol_FPrintDFG(stdout,Term); } void fol_PrintPrecedence(PRECEDENCE Precedence) /************************************************************** INPUT: A precedence. RETURNS: void EFFECT: Prints the current precedence to stdout, fol symbols are excluded. ***************************************************************/ { if (symbol_SignatureExists()) { LIST Symbols, Scan; SYMBOL Symbol; int Index; SIGNATURE S; Symbols = list_Nil(); for (Index = 1; Index < symbol_ACTINDEX; Index++) { S = symbol_Signature(Index); if (S != NULL) { Symbol = S->info; if ((symbol_IsPredicate(Symbol) || symbol_IsFunction(Symbol)) && !fol_IsPredefinedPred(Symbol)) Symbols = list_Cons((POINTER)Symbol, Symbols); } } Symbols = symbol_SortByPrecedence(Symbols, Precedence); for (Scan = Symbols; !list_Empty(Scan); Scan = list_Cdr(Scan)) { S = symbol_Signature(symbol_Index((SYMBOL)list_Car(Scan))); fputs(S->name, stdout); if (!list_Empty(list_Cdr(Scan))) fputs(" > ", stdout); } list_Delete(Symbols); } } void fol_FPrintPrecedence(FILE *File, PRECEDENCE Precedence) /************************************************************** INPUT: A file to print to, and a precedence. RETURNS: Nothing. EFFECT: Prints the current precedence as a setting command in DFG syntax to . fol symbols are excluded. ***************************************************************/ { if (symbol_SignatureExists()) { LIST Symbols, Scan; SYMBOL Symbol; int Index; SIGNATURE S; Symbols = list_Nil(); for (Index = 1; Index < symbol_ACTINDEX; Index++) { S = symbol_Signature(Index); if (S != NULL) { Symbol = S->info; if ((symbol_IsPredicate(Symbol) || symbol_IsFunction(Symbol)) && !fol_IsPredefinedPred(Symbol)) Symbols = list_Cons((POINTER)Symbol, Symbols); } } Symbols = symbol_SortByPrecedence(Symbols, Precedence); Index = 0; fputs("set_precedence(", File); for (Scan = Symbols; !list_Empty(Scan); Scan = list_Cdr(Scan)) { S = symbol_Signature(symbol_Index((SYMBOL)list_Car(Scan))); putc('(', File); fputs(S->name, File); putc(',', File); fprintf(File, "%d", S->weight); putc(',', File); putc((symbol_HasProperty((SYMBOL)list_Car(Scan),ORDRIGHT) ? 'r' : (symbol_HasProperty((SYMBOL)list_Car(Scan),ORDMUL) ? 'm' : 'l')), File); putc(')', File); if (!list_Empty(list_Cdr(Scan))) putc(',', File); if (Index > 15) { Index = 0; fputs("\n\t", File); } else Index++; } fputs(").", File); list_Delete(Symbols); } } static void fol_FPrintFormulaList(FILE* File, LIST Formulas, const char* Name) /************************************************************** INPUT: A file, a list of formulas, a name. EFFECTS: Print a list formulas in DFG format, with given list name. **************************************************************/ { LIST scan; fputs("list_of_formulae(", File); fputs(Name, File); fputs(").\n", File); for (scan = Formulas; !list_Empty(scan); scan= list_Cdr(scan)) { fputs("\tformula(", File); fol_FPrintDFG(File, list_Car(scan)); fputs(").\n", File); } fputs("end_of_list.\n\n", File); } void fol_FPrintDFGProblem(FILE* File, const char* Name, const char* Author, const char* Status, const char* Description, LIST Axioms, LIST Conjectures) /************************************************************** INPUT: A file, two lists of formulas, ??? EK EFFECTS: Prints a complete DFG file containing these lists. **************************************************************/ { fputs("begin_problem(Unknown).\n\n", File); fputs("list_of_descriptions.\n", File); fprintf(File,"name(%s).\n",Name); fprintf(File,"author(%s).\n",Author); fprintf(File,"status(%s).\n",Status); fprintf(File,"description(%s).\n",Description); fputs("end_of_list.\n\n", File); fputs("list_of_symbols.\n", File); fol_FPrintDFGSignature(File); fputs("end_of_list.\n\n", File); fol_FPrintFormulaList(File, Axioms, "axioms"); fol_FPrintFormulaList(File, Conjectures, "conjectures"); fputs("end_problem.\n", File); } BOOL fol_AssocEquation(TERM Term, SYMBOL *Result) /************************************************************** INPUT: A term. RETURNS: TRUE if the term is an equation defining associativity for some function symbol. EFFECT: If the is an assoc equation, then <*Result> is assigned the assoc symbol. ***************************************************************/ { if (fol_IsEquality(Term)) { SYMBOL Top; TERM Left,Right; Left = term_FirstArgument(Term); Right= term_SecondArgument(Term); Top = term_TopSymbol(Left); if (symbol_IsFunction(Top) && symbol_Arity(Top) == 2 && symbol_Equal(Top,term_TopSymbol(Right))) { SYMBOL v1,v2,v3; if (term_IsVariable(term_FirstArgument(Left))) v1 = term_TopSymbol(term_FirstArgument(Left)); else if (term_IsVariable(term_FirstArgument(Right))) { Term = Right; Right = Left; Left = Term; v1 = term_TopSymbol(term_FirstArgument(Left)); } else return FALSE; if (symbol_Equal(term_TopSymbol(term_SecondArgument(Left)),Top) && symbol_IsVariable((v2=term_TopSymbol(term_FirstArgument(term_SecondArgument(Left)))))&& symbol_IsVariable((v3=term_TopSymbol(term_SecondArgument(term_SecondArgument(Left)))))&& symbol_Equal(term_TopSymbol(term_FirstArgument(Right)),Top) && symbol_Equal(v1,term_TopSymbol(term_FirstArgument(term_FirstArgument(Right)))) && symbol_Equal(v2,term_TopSymbol(term_SecondArgument(term_FirstArgument(Right)))) && symbol_Equal(v3,term_TopSymbol(term_SecondArgument(Right)))) { *Result = Top; return TRUE; } } } return FALSE; } BOOL fol_DistributiveEquation(TERM Term, SYMBOL* Addition, SYMBOL* Multiplication) /************************************************************** INPUT: A term. RETURNS: TRUE if the term is an equation defining distributivity for two function symbols, FALSE otherwise. EFFECT: If the function returns TRUE, < Addition> and return the respective symbols. ***************************************************************/ { TERM left, right, help, v1, v2, v3; if (!fol_IsEquality(Term)) return FALSE; left = term_FirstArgument(Term); right = term_SecondArgument(Term); if (term_EqualTopSymbols(left, right) || !symbol_IsFunction(term_TopSymbol(left)) || !symbol_IsFunction(term_TopSymbol(right)) || symbol_Arity(term_TopSymbol(left)) != 2 || symbol_Arity(term_TopSymbol(right)) != 2) return FALSE; if (term_IsVariable(term_FirstArgument(left))) v1 = term_FirstArgument(left); else if (term_IsVariable(term_FirstArgument(right))) { help = right; /* Exchange left and right terms */ right = left; left = help; v1 = term_FirstArgument(left); } else return FALSE; if (!term_EqualTopSymbols(left, term_FirstArgument(right)) || !term_EqualTopSymbols(left, term_SecondArgument(right)) || !term_EqualTopSymbols(term_SecondArgument(left), right)) return FALSE; v2 = term_FirstArgument(term_SecondArgument(left)); v3 = term_SecondArgument(term_SecondArgument(left)); if (term_IsVariable(v2) && term_IsVariable(v3) && term_EqualTopSymbols(term_FirstArgument(term_FirstArgument(right)), v1) && term_EqualTopSymbols(term_SecondArgument(term_FirstArgument(right)), v2) && term_EqualTopSymbols(term_FirstArgument(term_SecondArgument(right)), v1) && term_EqualTopSymbols(term_SecondArgument(term_SecondArgument(right)), v3)) { *Addition = term_TopSymbol(right); *Multiplication = term_TopSymbol(left); return TRUE; } return FALSE; } static LIST fol_InstancesIntern(TERM Formula, TERM ToMatch, NAT Symbols) /************************************************************** INPUT: A formula in which all instances of are searched. The number of symbols of . RETURNS: The list of found instances. CAUTION: Bound variables must be different, for otherwise the used matching produces wrong results!! ***************************************************************/ { NAT HitSymbols; LIST Result; int Stack; Stack = stack_Bottom(); Result = list_Nil(); do { HitSymbols = term_Size(Formula); /* First check number of symbols of current formula */ if (HitSymbols >= Symbols && (Formula != ToMatch)) { cont_StartBinding(); if (unify_MatchFlexible(cont_LeftContext(), ToMatch, Formula)) Result = list_Cons(Formula, Result); else if (!symbol_IsPredicate(term_TopSymbol(Formula))) { if (fol_IsQuantifier(term_TopSymbol(Formula))) stack_Push(list_Cdr(term_ArgumentList(Formula))); else stack_Push(term_ArgumentList(Formula)); } cont_BackTrack(); } while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { Formula = (TERM)list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); return Result; } LIST fol_Instances(TERM Formula, TERM ToMatch) /************************************************************** INPUT: A formula in which all instances of are searched. RETURNS: The list of found occurrences matched by . The formula is not included! ***************************************************************/ { NAT Symbols; Symbols = term_ComputeSize(ToMatch); /* We use the number of symbols as a filter */ term_InstallSize(Formula); return fol_InstancesIntern(Formula, ToMatch, Symbols); } static LIST fol_GeneralizationsIntern(TERM Formula, TERM MatchedBy, NAT Symbols) /************************************************************** INPUT: A formula in which all instances of are searched. The number of symbols of . RETURNS: The list of found instances. CAUTION: Bound variables must be different, for otherwise the used matching produces wrong results!! ***************************************************************/ { NAT HitSymbols; LIST Result; int Stack; Stack = stack_Bottom(); Result = list_Nil(); do { if (Formula != MatchedBy) { HitSymbols = term_Size(Formula); /* First check number of symbols of current formula */ if (HitSymbols <= Symbols) { cont_StartBinding(); if (unify_MatchFlexible(cont_LeftContext(), Formula, MatchedBy)) Result = list_Cons(Formula, Result); else if (!symbol_IsPredicate(term_TopSymbol(Formula))) { if (fol_IsQuantifier(term_TopSymbol(Formula))) stack_Push(list_Cdr(term_ArgumentList(Formula))); else stack_Push(term_ArgumentList(Formula)); } cont_BackTrack(); } else if (!symbol_IsPredicate(term_TopSymbol(Formula))) { if (fol_IsQuantifier(term_TopSymbol(Formula))) stack_Push(list_Cdr(term_ArgumentList(Formula))); else stack_Push(term_ArgumentList(Formula)); } } while (!stack_Empty(Stack) && list_Empty(stack_Top())) stack_Pop(); if (!stack_Empty(Stack)) { Formula = (TERM)list_Car(stack_Top()); stack_RplacTop(list_Cdr(stack_Top())); } } while (!stack_Empty(Stack)); return Result; } LIST fol_Generalizations(TERM Formula, TERM MatchedBy) /************************************************************** INPUT: A formula in which all first-order generalizations of are searched. RETURNS: The list of found occurrences that are more general than . The formula is not included! ***************************************************************/ { NAT Symbols; Symbols = term_ComputeSize(MatchedBy); /* We use the number of symbols as a filter */ term_InstallSize(Formula); return fol_GeneralizationsIntern(Formula, MatchedBy, Symbols); } TERM fol_MostGeneralFormula(LIST Formulas) /************************************************************** INPUT: A list of formulas. RETURNS: A most general formula out of the list, i.e., if some formula is returned, there is no formula in the list that is more general than that formula. ***************************************************************/ { TERM Result, Candidate; LIST Scan; #ifdef CHECK if (list_Empty(Formulas)) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_MostGeneralFormula: Called with empty list.\n"); misc_FinishErrorReport(); } #endif Result = list_Car(Formulas); for (Scan=list_Cdr(Formulas);!list_Empty(Scan);Scan=list_Cdr(Scan)) { Candidate = (TERM)list_Car(Scan); cont_StartBinding(); if (unify_MatchFlexible(cont_LeftContext(), Candidate, Result)) Result = Candidate; cont_BackTrack(); } return Result; } void fol_ReplaceVariable(TERM Term, SYMBOL Symbol, TERM Repl) /************************************************************** INPUT: A term, a variable symbol and a replacement term. RETURNS: void EFFECT: All free variables with in are replaced with copies of CAUTION: Destructive ***************************************************************/ { LIST Scan; #ifdef CHECK if (!(term_IsTerm(Term) && term_IsTerm(Repl) && symbol_IsVariable(Symbol))) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_ReplaceVariable: Illegal input.\n"); misc_FinishErrorReport(); } #endif if (fol_IsQuantifier(term_TopSymbol(Term))) { for (Scan=term_ArgumentList(term_FirstArgument(Term)); !list_Empty(Scan); Scan=list_Cdr(Scan)) if (symbol_Equal(term_TopSymbol(list_Car(Scan)), Symbol)) /* var is bound */ return; fol_ReplaceVariable(term_SecondArgument(Term), Symbol, Repl); } if (symbol_Equal(term_TopSymbol(Term), Symbol)) { term_RplacTop(Term,term_TopSymbol(Repl)); term_RplacArgumentList(Term,term_CopyTermList(term_ArgumentList(Repl))); } else for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) fol_ReplaceVariable(list_Car(Scan),Symbol,Repl); } static void fol_PrettyPrintInternDFG(TERM Term, int Depth) /************************************************************** INPUT: A term and a depth parameter for indentation. RETURNS: none. SUMMARY: Prints the term hopefully more pretty to stdout. ***************************************************************/ { int i; LIST scan; SYMBOL Top; Top = term_TopSymbol(Term); if (!symbol_Equal(Top,fol_Varlist())) { for (i = 0; i < Depth; i++) fputs(" ", stdout); if (fol_IsLiteral(Term)) term_PrintPrefix(Term); else { if (symbol_IsJunctor(Top)) { if (term_IsComplex(Term)) { symbol_Print(Top); putchar('('); if (!fol_IsQuantifier(Top)) putchar('\n'); for (scan=term_ArgumentList(Term); !list_Empty(scan); scan= list_Cdr(scan)) { fol_PrettyPrintInternDFG((TERM) list_Car(scan), Depth+1); if (!list_Empty(list_Cdr(scan))) fputs(",\n", stdout); } putchar(')'); } else { if (term_IsVariable(Term)) { symbol_Print(Top); } else { putchar('('); symbol_Print(Top); putchar(')'); } } } else { term_PrintPrefix(Term); } } } else { putchar('['); term_TermListPrintPrefix(term_ArgumentList(Term)); putchar(']'); } } void fol_PrettyPrintDFG(TERM Term) /************************************************************** INPUT: A term. RETURNS: none. SUMMARY: Prints the term hopefully more pretty to stdout. ***************************************************************/ { fol_PrettyPrintInternDFG(Term, 0); } TERM fol_CheckFatherLinksIntern(TERM Term) /************************************************************** INPUT: A term. RETURNS: A subterm whose superterm pointer is not set correctly, else NULL. SUMMARY: Checks if all superterm links except of those from quantifier variables are set correctly. ***************************************************************/ { LIST l; if (fol_IsQuantifier(term_TopSymbol(Term))) return fol_CheckFatherLinksIntern(term_SecondArgument(Term)); if (term_IsComplex(Term)) { for (l=term_ArgumentList(Term); !list_Empty(l); l=list_Cdr(l)) { TERM result; if (term_Superterm((TERM) list_Car(l)) != Term) return (TERM) list_Car(l); result = fol_CheckFatherLinksIntern((TERM) list_Car(l)); if (result != NULL) return result; } } return NULL; } void fol_CheckFatherLinks(TERM Term) /************************************************************** INPUT: A term. RETURNS: none. SUMMARY: Checks if all superterm links except of those from quantifier variables are set correctly. ***************************************************************/ { TERM Result; Result = fol_CheckFatherLinksIntern(Term); #ifdef CHECK if (Result != NULL || term_Superterm(Term) != NULL) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_CheckFatherLinks:"); misc_ErrorReport(" Found a term where the father links"); misc_ErrorReport(" are not correctly set."); misc_FinishErrorReport(); } #endif } static void fol_PrettyPrintIntern(TERM Term, int Depth) /************************************************************** INPUT: A term and a depth parameter for indentation. RETURNS: none. SUMMARY: Prints the term hopefully more pretty to stdout. ***************************************************************/ { int i; LIST scan; for (i = 0; i < Depth; i++) fputs(" ", stdout); if (symbol_IsJunctor(term_TopSymbol(Term))) { if (term_IsComplex(Term)) { if (fol_IsQuantifier(term_TopSymbol(Term))) { symbol_Print(term_TopSymbol(Term)); fputs("([", stdout); for (scan=fol_QuantifierVariables(Term); !list_Empty(scan); scan=list_Cdr(scan)) { symbol_Print(term_TopSymbol((TERM) list_Car(scan))); if (!list_Empty(list_Cdr(scan))) putchar(','); } fputs("],\n", stdout); fol_PrettyPrintIntern(term_SecondArgument(Term), Depth+1); } else { symbol_Print(term_TopSymbol(Term)); fputs("(\n", stdout); for (scan=term_ArgumentList(Term); !list_Empty(scan); scan= list_Cdr(scan)) { fol_PrettyPrintIntern((TERM) list_Car(scan), Depth+1); if (!list_Empty(list_Cdr(scan))) fputs(",\n", stdout); } putchar(')'); } } else { if (term_IsVariable(Term)) { symbol_Print(term_TopSymbol(Term)); } else { putchar('('); symbol_Print(term_TopSymbol(Term)); putchar(')'); } } } else { term_PrintPrefix(Term); } } void fol_PrettyPrint(TERM Term) /************************************************************** INPUT: A term. RETURNS: none. SUMMARY: Prints the term hopefully more pretty to stdout. ***************************************************************/ { fol_PrettyPrintIntern(Term, 0); } LIST fol_GetSubstEquations(TERM Term) /************************************************************** INPUT: A Term. RETURNS: The list of all equations of the form x=t or t=x in where x is a variable and t is a term not containing x. ***************************************************************/ { LIST Result; LIST Scan; Result = list_Nil(); if (fol_IsQuantifier(term_TopSymbol(Term))) return fol_GetSubstEquations(term_SecondArgument(Term)); if (fol_IsEquality(Term)) { if (term_IsVariable(term_SecondArgument(Term))) { if (!term_ContainsSymbol(term_FirstArgument(Term), term_TopSymbol(term_SecondArgument(Term)))) Result = list_Cons(Term, Result); } else { if (term_IsVariable(term_FirstArgument(Term))) if (!term_ContainsSymbol(term_SecondArgument(Term), term_TopSymbol(term_FirstArgument(Term)))) Result = list_Cons(Term, Result); } } if (symbol_IsPredicate(term_TopSymbol(Term))) return Result; else for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) Result = list_Nconc(Result, fol_GetSubstEquations(list_Car(Scan))); return Result; } TERM fol_GetBindingQuantifier(TERM Term, SYMBOL Symbol) /************************************************************** INPUT: A symbol and a term containing the symbol. RETURNS: The Quantifier binding the symbol. ***************************************************************/ { LIST Scan; #ifdef CHECK if (!term_IsTerm(Term) || !symbol_IsSymbol(Symbol)) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_GetBindingQuantifier: Illegal input.\n"); misc_FinishErrorReport(); } #endif if (fol_IsQuantifier(term_TopSymbol(Term))) { for ( Scan = fol_QuantifierVariables(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) if (symbol_Equal(Symbol, term_TopSymbol(list_Car(Scan)))) { return Term; } } return fol_GetBindingQuantifier(term_Superterm(Term), Symbol); } int fol_TermPolarity(TERM SubTerm, TERM Term) /************************************************************** INPUT: Two terms, SubTerm subterm of Term. It is assumed that the superterm links in are established. RETURNS: The polarity of SubTerm in Term. ***************************************************************/ { TERM SuperTerm; #ifdef CHECK if (!term_IsTerm(SubTerm) || !term_IsTerm(Term) || !term_FatherLinksEstablished(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_TermPolarity: Illegal input.\n"); misc_FinishErrorReport(); } #endif if (SubTerm == Term) return 1; SuperTerm = term_Superterm(SubTerm); if (SuperTerm) { SYMBOL Top; Top = term_TopSymbol(SuperTerm); if (symbol_Equal(Top,fol_AND) || symbol_Equal(Top,fol_OR) || fol_IsQuantifier(Top)) return fol_TermPolarity(SuperTerm, Term); if (symbol_Equal(Top,fol_NOT)) return (-fol_TermPolarity(SuperTerm, Term)); if (symbol_Equal(Top,fol_EQUIV)) return 0; if (symbol_Equal(Top, fol_IMPLIES)) { if (SubTerm == term_FirstArgument(SuperTerm)) return (-fol_TermPolarity(SuperTerm, Term)); else return fol_TermPolarity(SuperTerm, Term); } if (symbol_Equal(Top, fol_IMPLIED)) { if (SubTerm == term_SecondArgument(SuperTerm)) return (-fol_TermPolarity(SuperTerm, Term)); else return fol_TermPolarity(SuperTerm, Term); } misc_StartErrorReport(); misc_ErrorReport("\n In fol_TermPolarity: Unknown first-order operator.\n"); misc_FinishErrorReport(); } return 1; } static int fol_PolarCheckCount(TERM Nowterm, TERM SuperTerm, int Nowpolar) /************************************************************** INPUT: Two terms, Nowterm and its superterm, and the polarity of Nowterm. RETURNS: The polarity of SuperTerm according to Nowterm. COMMENT: Helpfunction for fol_PolarCheck. ***************************************************************/ { SYMBOL Top; Top = term_TopSymbol(SuperTerm); if (Nowterm == SuperTerm) return Nowpolar; if (symbol_Equal(Top, fol_OR) || symbol_Equal(Top, fol_AND) || fol_IsQuantifier(Top) || (symbol_Equal(Top, fol_IMPLIES) && Nowterm == term_SecondArgument(SuperTerm)) || (symbol_Equal(Top, fol_IMPLIED) && Nowterm == term_FirstArgument(SuperTerm))) return Nowpolar; if (symbol_Equal(term_TopSymbol(SuperTerm), fol_EQUIV)) return 0; return -Nowpolar; } static BOOL fol_PolarCheckAllquantor(TERM Subterm, TERM Term, int SubtermPolar) /************************************************************** INPUT: Two terms, Subterm subterm of Term, and polarity of Subterm. RETURNS: TRUE iff Subterm occurs in Term disjunctively. COMMENT: Help function for fol_PolarCheck. Dual case to Exist quantor. ***************************************************************/ { TERM SuperTerm; SYMBOL Top; int SubPolar; if (Subterm == Term) return TRUE; SuperTerm = term_Superterm(Subterm); if (SuperTerm == Term) /* Ugly, but it does not make sense to introduce a further function */ return TRUE; Top = term_TopSymbol(SuperTerm); SubPolar = fol_PolarCheckCount(Subterm, SuperTerm, SubtermPolar); /* To be clarified: can the below condition generalized to universal quantifiers? */ if (symbol_Equal(Top,fol_NOT) || (symbol_Equal(Top, fol_OR) && SubPolar == 1) || (symbol_Equal(Top, fol_AND) && SubPolar == -1) || (symbol_Equal(Top,fol_IMPLIES) && SubPolar == 1) || (symbol_Equal(Top,fol_IMPLIED) && SubPolar == 1)) return fol_PolarCheckAllquantor(SuperTerm, Term, SubPolar); return FALSE; } static BOOL fol_PolarCheckExquantor(TERM Subterm, TERM Term, int SubtermPolar) /************************************************************** INPUT: Two terms, Subterm subterm of Term, and polarity of Subterm. RETURNS: TRUE iff Subterm occurs in Term conjunctively. COMMENT: Help function for fol_PolarCheck. Dual case to Allquantor. ***************************************************************/ { TERM SuperTerm; SYMBOL Top; int SubPolar; if (Subterm == Term) return TRUE; SuperTerm = term_Superterm(Subterm); if (SuperTerm == Term) /* Ugly, but it does not make sense to introduce a further function */ return TRUE; Top = term_TopSymbol(SuperTerm); SubPolar = fol_PolarCheckCount(Subterm, SuperTerm, SubtermPolar); /* To be clarified: can the below condition generalized to existential quantifiers? */ if (symbol_Equal(Top,fol_NOT) || (symbol_Equal(Top, fol_OR) && SubPolar == -1) || (symbol_Equal(Top, fol_AND) && SubPolar == 1) || (symbol_Equal(Top,fol_IMPLIES) && SubPolar == -1) || (symbol_Equal(Top,fol_IMPLIED) && SubPolar == -1)) return fol_PolarCheckExquantor(SuperTerm, Term, SubPolar); return FALSE; } BOOL fol_PolarCheck(TERM Subterm, TERM Term) /************************************************************** INPUT: Two terms, is of the form x=t, where x or t variable. is a subterm of and the top symbol of must be the binding quantifier of x or t. RETURNS: BOOL if check is ok. ***************************************************************/ { int SubtermPolar; SYMBOL Top; SubtermPolar = fol_TermPolarity(Subterm, Term); Top = term_TopSymbol(Term); if (SubtermPolar == -1 && symbol_Equal(Top, fol_ALL)) return fol_PolarCheckAllquantor(Subterm, Term, SubtermPolar); if (SubtermPolar == 1 && symbol_Equal(Top, fol_EXIST)) return fol_PolarCheckExquantor(Subterm, Term, SubtermPolar); return FALSE; } void fol_PopQuantifier(TERM Term) /************************************************************** INPUT: A term whose top symbol is a quantifier. RETURNS: Nothing. EFFECT: Removes the quantifier. If supertermlinks were set, they are updated. ***************************************************************/ { TERM SubTerm; LIST Scan; #ifdef CHECK if (!fol_IsQuantifier(term_TopSymbol(Term))) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_PopQuantifier: Top symbol of term isn't a quantifier.\n"); misc_FinishErrorReport(); } #endif term_Delete(term_FirstArgument(Term)); SubTerm = term_SecondArgument(Term); list_Delete(term_ArgumentList(Term)); term_RplacTop(Term,term_TopSymbol(SubTerm)); term_RplacArgumentList(Term,term_ArgumentList(SubTerm)); for (Scan=term_ArgumentList(Term);!list_Empty(Scan);Scan=list_Cdr(Scan)) if (term_Superterm(list_Car(Scan))) term_RplacSuperterm(list_Car(Scan),Term); term_Free(SubTerm); } void fol_DeleteQuantifierVariable(TERM Quant,SYMBOL Var) /**************************************************************** INPUT: A term starting with a quantifier and a variable symbol. RETURNS: Nothing. EFFECT: The variable is deleted from the list of variables bound by the quantor of *****************************************************************/ { LIST Scan; for (Scan=fol_QuantifierVariables(Quant);!list_Empty(Scan);Scan=list_Cdr(Scan)) if (symbol_Equal(term_TopSymbol(list_Car(Scan)), Var)) { term_Delete((TERM)list_Car(Scan)); list_Rplaca(Scan, (POINTER)NULL); } term_RplacArgumentList(term_FirstArgument(Quant), list_PointerDeleteElement(fol_QuantifierVariables(Quant),(POINTER)NULL)); if (list_Empty(fol_QuantifierVariables(Quant))) fol_PopQuantifier(Quant); } void fol_SetTrue(TERM Term) /************************************************************** INPUT: A term. RETURNS: Nothing. EFFECT: Replaces Term destructively by fol_True(). ***************************************************************/ { term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term, list_Nil()); term_RplacTop(Term, fol_True()); } void fol_SetFalse(TERM Term) /************************************************************** INPUT: A term. RETURNS: Nothing. EFFECT: Replaces Term destructively by fol_False(). ***************************************************************/ { term_DeleteTermList(term_ArgumentList(Term)); term_RplacArgumentList(Term, list_Nil()); term_RplacTop(Term, fol_False()); } static void fol_ReplaceByArgCon(TERM Term) /************************************************************** INPUT: A term of the form f(...)=f(...), where f is a function. RETURNS: True. EFFECT: Substitutes Term by , where ti and si are the arguments of both f's in Term. ***************************************************************/ { LIST Scan, Bscan, List, Hlist; TERM Func1, Func2, NewTerm; Func1 = term_FirstArgument(Term); Func2 = term_SecondArgument(Term); List = term_ArgumentList(Term); Scan = list_Nil(); term_RplacArgumentList(Term, list_Nil()); term_RplacTop(Term, fol_And()); for (Scan = term_ArgumentList(Func1),Bscan = term_ArgumentList(Func2); !list_Empty(Scan); Scan = list_Cdr(Scan)) { Hlist = list_Nil(); Hlist = list_Cons(list_Car(Bscan), Hlist); Hlist = list_Cons(list_Car(Scan), Hlist); NewTerm = term_Create(fol_Equality(), Hlist); term_RplacArgumentList(Term, list_Cons(NewTerm, term_ArgumentList(Term))); Bscan = list_Cdr(Bscan); } list_Delete(term_ArgumentList(Func1)); list_Delete(term_ArgumentList(Func2)); term_RplacArgumentList(Func1, list_Nil()); term_RplacArgumentList(Func2, list_Nil()); term_Delete(Func1); term_Delete(Func2); list_Delete(List); } BOOL fol_PropagateFreeness(TERM Term) /************************************************************** INPUT: A term and a list of functions. RETURNS: True iff a subterm of the form f(...)=f(...) occurs in the term, where f has property FREELY and GENERATED. EFFECT: Substitutes all occurences of f=f by ,where ti and si are the arguments of each f in f=f. ***************************************************************/ { BOOL Free; LIST Scan; TERM Argum1, Argum2; Free = FALSE; if (fol_IsQuantifier(term_TopSymbol(Term))) return fol_PropagateFreeness(term_SecondArgument(Term)); if (!term_IsAtom(Term)) { for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) if (fol_PropagateFreeness(list_Car(Scan))) Free = TRUE; } else if (fol_IsEquality(Term)) { Argum1 = term_FirstArgument(Term); Argum2 = term_SecondArgument(Term); if (symbol_Equal(term_TopSymbol(Argum1), term_TopSymbol(Argum2)) && symbol_HasProperty(term_TopSymbol(Argum1), FREELY) && symbol_HasProperty(term_TopSymbol(Argum1), GENERATED)) { fol_ReplaceByArgCon(Term); return TRUE; } } return Free; } static BOOL fol_PropagateWitnessIntern(TERM Equation, SYMBOL Variable) /************************************************************** INPUT: A Term which is an equation where is one of the equation's arguments that does not occur in the other argument. Father links must exist. RETURNS: True in case of witness propagation. EFFECT: Checks whether subterm the equation is part of is of the form described in fol_PropagateWitness and substitutes in case of a hit. ***************************************************************/ { TERM SuperTerm, BindQuantor, Predicat; SYMBOL SuperTop; SuperTerm = term_Superterm(Equation); if (SuperTerm == term_Null()) return FALSE; SuperTop = term_TopSymbol(SuperTerm); BindQuantor = term_Superterm(SuperTerm); if (BindQuantor == term_Null()) return FALSE; if (!fol_IsQuantifier(term_TopSymbol(BindQuantor)) || list_Length(term_ArgumentList(SuperTerm)) != 2) return FALSE; if (Equation == term_SecondArgument(SuperTerm)) Predicat = term_FirstArgument(SuperTerm); else Predicat = term_SecondArgument(SuperTerm); if (symbol_Equal(term_TopSymbol(BindQuantor), fol_All()) && symbol_Equal(SuperTop, fol_Or()) && symbol_Equal(term_TopSymbol(Predicat), fol_Not()) && symbol_HasProperty(term_TopSymbol(term_FirstArgument(Predicat)), FREELY) && symbol_HasProperty(term_TopSymbol(term_FirstArgument(Predicat)), GENERATED) && symbol_Equal(term_TopSymbol(term_FirstArgument(term_FirstArgument(Predicat))), Variable)) { fol_SetFalse(BindQuantor); return TRUE; } if (!symbol_HasProperty(term_TopSymbol(Predicat), FREELY) || !symbol_HasProperty(term_TopSymbol(Predicat), GENERATED) || !symbol_Equal(Variable, term_TopSymbol(term_FirstArgument(Predicat)))) return FALSE; if (symbol_Equal(term_TopSymbol(BindQuantor), fol_All())) { if (symbol_Equal(SuperTop, fol_Implies()) && term_SecondArgument(SuperTerm) == Equation) { fol_SetFalse(BindQuantor); return TRUE; } if (symbol_Equal(SuperTop, fol_Implied()) && term_FirstArgument(SuperTerm) == Equation) { fol_SetFalse(BindQuantor); return TRUE; } } else /* Exquantor */ if (symbol_Equal(SuperTop, fol_And())) { fol_SetTrue(BindQuantor); return TRUE; } return FALSE; } BOOL fol_PropagateWitness(TERM Term) /************************************************************** INPUT: A Term. RETURNS: True in case of witness propagation. EFFECT: Substitutes any subterm of Term of the form forall([x],implies(P(x),x=t)) forall([x],implied(x=t,P(x))) forall([x],or(notP(x),x=t)) by FALSE and exists([x],and(P(x),x=t)) by TRUE, where P has property FREELY and GENERATED, x doesn't occur in t. ***************************************************************/ { BOOL Hit; LIST Scan; Hit = FALSE; if (fol_IsQuantifier(term_TopSymbol(Term))) return fol_PropagateWitness(term_SecondArgument(Term)); if (fol_IsEquality(Term)) { if (term_IsVariable(term_SecondArgument(Term))) { if (!term_ContainsSymbol(term_FirstArgument(Term), term_TopSymbol(term_SecondArgument(Term)))) Hit = fol_PropagateWitnessIntern(Term,term_TopSymbol(term_SecondArgument(Term))); } else { if (term_IsVariable(term_FirstArgument(Term))) if (!term_ContainsSymbol(term_SecondArgument(Term), term_TopSymbol(term_FirstArgument(Term)))) Hit = fol_PropagateWitnessIntern(Term,term_TopSymbol(term_FirstArgument(Term))); } } if (symbol_IsPredicate(term_TopSymbol(Term))) return FALSE; for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) if (fol_PropagateWitness(list_Car(Scan))) Hit = TRUE; return Hit; } BOOL fol_PropagateTautologies(TERM Term) /************************************************************** INPUT: A term. RETURNS: True iff function replaced a subterm. EFFECT: Replaces all occurences of t=t, or(A,not(A)) by TRUE and and(A,not(A)) by FALSE. ***************************************************************/ { BOOL Hit; LIST Scan, Bscan, ArgumentList; SYMBOL Top; Top = term_TopSymbol(Term); Hit = FALSE; ArgumentList = term_ArgumentList(Term); if (fol_IsQuantifier(Top)) return fol_PropagateTautologies(term_SecondArgument(Term)); if (fol_IsEquality(Term)) { if (term_Equal(term_FirstArgument(Term), term_SecondArgument(Term))) { fol_SetTrue(Term); return TRUE; } } if (symbol_Equal(Top, fol_Or()) || symbol_Equal(Top, fol_And())) { for (Scan = ArgumentList; !list_Empty(Scan); Scan = list_Cdr(Scan)) if (symbol_Equal(term_TopSymbol(list_Car(Scan)), fol_Not())) { for (Bscan = ArgumentList; !list_Empty(Bscan); Bscan = list_Cdr(Bscan)) { if (list_Car(Scan) != list_Car(Bscan) && fol_AlphaEqual(term_FirstArgument(list_Car(Scan)), list_Car(Bscan))) { if (symbol_Equal(Top, fol_Or())) fol_SetTrue(Term); else fol_SetFalse(Term); return TRUE; } } } } if (!term_IsAtom(Term)) for (Scan = ArgumentList; !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (fol_PropagateTautologies(list_Car(Scan))) Hit = TRUE; } return Hit; } static BOOL fol_AlphaEqualIntern(TERM Term1, TERM Term2, NAT Mark) /************************************************************** INPUT: Two terms which represent formulae and a binding mark. RETURNS: True iff Term2 is equal to Term1 with respect to the renaming of bound variables. ***************************************************************/ { LIST Scan, Bscan; SYMBOL Top1, Top2; Top1 = term_TopSymbol(Term1); Top2 = term_TopSymbol(Term2); if (symbol_IsVariable(Top1) && symbol_IsVariable(Top2)) { if (term_VarIsMarked(Top2, Mark)) return symbol_Equal(Top1, (SYMBOL)term_BindingValue(Top2)); else return symbol_Equal(Top1, Top2); } if (!symbol_Equal(Top1, Top2)) return FALSE; if (fol_IsQuantifier(Top1)) { if (list_Length(fol_QuantifierVariables(Term1)) != list_Length(fol_QuantifierVariables(Term2))) return FALSE; for (Scan = fol_QuantifierVariables(Term1), Bscan = fol_QuantifierVariables(Term2); !list_Empty(Scan); Scan = list_Cdr(Scan), Bscan = list_Cdr(Bscan)) term_CreateValueBinding(term_TopSymbol(list_Car(Bscan)), Mark, (POINTER)term_TopSymbol(list_Car(Scan))); if (!fol_AlphaEqualIntern(term_SecondArgument(Term1), term_SecondArgument(Term2), Mark)) return FALSE; for (Scan = fol_QuantifierVariables(Term1), Bscan = fol_QuantifierVariables(Term2); !list_Empty(Scan); Scan = list_Cdr(Scan), Bscan = list_Cdr(Bscan)) term_SetBindingMark(term_TopSymbol(list_Car(Bscan)), term_NullMark()); } else { if (list_Length(term_ArgumentList(Term1)) != list_Length(term_ArgumentList(Term2))) return FALSE; for (Scan = term_ArgumentList(Term1), Bscan = term_ArgumentList(Term2); !list_Empty(Scan); Scan = list_Cdr(Scan), Bscan = list_Cdr(Bscan)) if (!fol_AlphaEqualIntern(list_Car(Scan), list_Car(Bscan), Mark)) return FALSE; } return TRUE; } BOOL fol_AlphaEqual(TERM Term1, TERM Term2) /************************************************************** INPUT: Two terms of the form Qx(). All variables that occur in Term1 and Term2 must be bound by only one quantifier! RETURNS: TRUE iff Term2 is bound renaming of Term1. ***************************************************************/ { BOOL Hit; #ifdef CHECK if (Term1 == term_Null() || Term2 == term_Null()) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_AlphaEqual: Corrupted term as parameter.\n"); misc_FinishErrorReport(); } if (fol_VarBoundTwice(Term1) || fol_VarBoundTwice(Term2)) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_AlphaEqual: Variables are bound more than once.\n"); misc_FinishErrorReport(); } if (term_InBindingPhase()) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_AlphaEqual: Term context is in binding phase.\n"); misc_FinishErrorReport(); } #endif term_StartBinding(); Hit = fol_AlphaEqualIntern(Term1, Term2, term_ActMark()); term_StopBinding(); return Hit; } static BOOL fol_VarBoundTwiceIntern(TERM Term, NAT Mark) /************************************************************** INPUT: A term, possibly a NULL Term and a valid binding mark. RETURNS: TRUE iff a variable in is bound by more than one quantifier. ***************************************************************/ { LIST Scan; if (Term == term_Null()) return FALSE; if (term_IsAtom(Term)) return FALSE; if (!fol_IsQuantifier(term_TopSymbol(Term))) { for (Scan = term_ArgumentList(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) if (fol_VarBoundTwiceIntern(list_Car(Scan), Mark)) return TRUE; } else { for (Scan = fol_QuantifierVariables(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) { if (!term_VarIsMarked(term_TopSymbol(list_Car(Scan)), Mark)) term_SetBindingMark(term_TopSymbol(list_Car(Scan)), Mark); else return TRUE; } if (fol_VarBoundTwiceIntern(term_SecondArgument(Term), Mark)) return TRUE; for (Scan = fol_QuantifierVariables(Term); !list_Empty(Scan); Scan = list_Cdr(Scan)) term_SetBindingMark(term_TopSymbol(list_Car(Scan)), term_NullMark()); } return FALSE; } BOOL fol_VarBoundTwice(TERM Term) /************************************************************** INPUT: A term. RETURNS: TRUE iff a variable in term is bound by more than one quantifier. ***************************************************************/ { BOOL Hit; #ifdef CHECK if (term_InBindingPhase()) { misc_StartErrorReport(); misc_ErrorReport("\n\n Context in fol_VarBoundTwice: term in binding phase\n"); misc_FinishErrorReport(); } #endif term_StartBinding(); Hit = fol_VarBoundTwiceIntern(Term, (NAT)term_ActMark()); term_StopBinding(); return Hit; } NAT fol_Depth(TERM Term) /************************************************************** INPUT: A formula. RETURNS: The depth of the formula up to predicate level. ***************************************************************/ { NAT Depth,Help; LIST Scan; #ifdef CHECK if (!term_IsTerm(Term)) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_Depth: Illegal input.\n"); misc_FinishErrorReport(); } #endif Depth = 0; if (symbol_IsPredicate(term_TopSymbol(Term))) return 1; if (fol_IsQuantifier(term_TopSymbol(Term))) return (fol_Depth(term_SecondArgument(Term)) + 1); for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) { Help = fol_Depth(list_Car(Scan)); if (Help > Depth) Depth = Help; } return (Depth+1); } static void fol_ApplyContextToTermIntern(CONTEXT Context, TERM Term) /******************************************************************** INPUT: A context (Context) and a term (Term). RETURN: void. EFFECT: Term is destructively changed modulo Context. *********************************************************************/ { LIST Scan; if (fol_IsQuantifier(term_TopSymbol(Term))) { fol_ApplyContextToTermIntern(Context, term_SecondArgument(Term)); } else if (symbol_IsVariable(term_TopSymbol(Term))) { if (cont_VarIsBound(Context, term_TopSymbol(Term))) Term = cont_ApplyBindingsModuloMatching(Context, Term, TRUE); } else { for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) fol_ApplyContextToTermIntern(Context, list_Car(Scan)); } } static BOOL fol_CheckApplyContextToTerm(CONTEXT Context, TERM Term) /************************************************************* INPUT: A Context and a term. RETURN: TRUE iff Context can be applied to Term. COMMENT: Intern funktion of fol_ApplyContextToTerm. **************************************************************/ { LIST Scan; BOOL Apply; Apply = TRUE; if (fol_IsQuantifier(term_TopSymbol(Term))) { for (Scan=fol_QuantifierVariables(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) if (cont_VarIsBound(Context, term_TopSymbol(list_Car(Scan)))) return FALSE; for (Scan=term_ArgumentList(term_SecondArgument(Term)); !list_Empty(Scan); Scan=list_Cdr(Scan)) { if (!fol_CheckApplyContextToTerm(Context, list_Car(Scan))) Apply = FALSE; } } else { for (Scan=term_ArgumentList(Term); !list_Empty(Scan); Scan=list_Cdr(Scan)) if (!fol_CheckApplyContextToTerm(Context, list_Car(Scan))) Apply = FALSE; } return Apply; } BOOL fol_ApplyContextToTerm(CONTEXT Context, TERM Term) /*************************************************************** INPUT: A context (Context) and a term (Term). RETURN: TRUE iff context could be applied on Term. EFFECT: Term is destructively changed modulo Context iff possible. ****************************************************************/ { if (fol_CheckApplyContextToTerm(Context, Term)) { fol_ApplyContextToTermIntern(Context, Term); return TRUE; } return FALSE; } BOOL fol_SignatureMatchFormula(TERM Formula, TERM Instance, BOOL Variant) /******************************************************************** INPUT : Two formulas and a flag. It is assumed that the symbol context is clean. RETURN: TRUE iff can be matched to by matching variables as well as signature symbols. If is TRUE variables must be matched to variables. EFFECT: The symbol matches are stored in the symbol context. *********************************************************************/ { int Stack; SYMBOL FormulaTop, InstanceTop; NAT ActMark; TERM ActFormula, ActInstance; #ifdef CHECK if (!term_IsTerm(Formula) || term_InBindingPhase() || !term_IsTerm(Instance) || !symbol_ContextIsClean()) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_SignatureMatchFormula: Illegal input or context."); misc_FinishErrorReport(); } #endif term_StartBinding(); Stack = stack_Bottom(); term_NewMark(); ActMark = term_OldMark(); ActFormula = Formula; ActInstance = Instance; do { FormulaTop = term_TopSymbol(ActFormula); InstanceTop = term_TopSymbol(ActInstance); if (!symbol_IsVariable(FormulaTop)) { if (!symbol_ContextIsBound(FormulaTop)) { if (!symbol_IsJunctor(FormulaTop) && !symbol_IsJunctor(InstanceTop) && !fol_IsPredefinedPred(FormulaTop) && !fol_IsPredefinedPred(InstanceTop)) symbol_ContextSetValue(FormulaTop, InstanceTop); /* Symbols are ALWAYS bound !*/ else { if (!symbol_Equal(FormulaTop, InstanceTop)) { term_StopBinding(); return FALSE; } } } else { if (symbol_ContextIsBound(FormulaTop) && !symbol_Equal(symbol_ContextGetValue(FormulaTop),InstanceTop)) { term_StopBinding(); return FALSE; } } } if (list_Length(term_ArgumentList(ActFormula)) != list_Length(term_ArgumentList(ActInstance))) { term_StopBinding(); return FALSE; } if (term_IsComplex(ActFormula)) { stack_Push(term_ArgumentList(ActInstance)); stack_Push(term_ArgumentList(ActFormula)); } else { if (symbol_IsVariable(FormulaTop)) { if (!term_VarIsMarked(FormulaTop, ActMark)) { if (!Variant || symbol_IsVariable(InstanceTop)) term_CreateValueBinding(FormulaTop, ActMark, (POINTER)InstanceTop); else { term_StopBinding(); return FALSE; } } else { if (!symbol_Equal((SYMBOL)term_BindingValue(FormulaTop), InstanceTop)) { term_StopBinding(); return FALSE; } } } } while (!stack_Empty(Stack) && list_Empty(stack_Top())) { stack_Pop(); stack_Pop(); } if (!stack_Empty(Stack)) { ActFormula = (TERM)list_Car(stack_Top()); ActInstance = (TERM)list_Car(stack_NthTop(1)); stack_RplacTop(list_Cdr(stack_Top())); stack_RplacNthTop(1,list_Cdr(stack_NthTop(1))); } } while (!stack_Empty(Stack)); term_StopBinding(); return TRUE; } BOOL fol_SignatureMatch(TERM Term, TERM Instance, LIST* Bindings, BOOL Variant) /***************************************************************** INPUT : Two formulas, a binding list and a boolean flag. RETURN: TRUE iff can be matched to by matching variables as well as signature symbols. If is TRUE variables must be matched to variables. Signature symbol matchings have to be injective. EFFECT: The symbol matches are stored in the symbol context. ******************************************************************/ { int Stack; SYMBOL TermTop, InstanceTop; NAT ActMark; TERM ActTerm, ActInstance; #ifdef CHECK if (!term_IsTerm(Term) || !term_IsTerm(Instance)) { misc_StartErrorReport(); misc_ErrorReport("\n In fol_SignatureMatch: Illegal input."); misc_FinishErrorReport(); } #endif Stack = stack_Bottom(); ActMark = term_OldMark(); ActTerm = Term; ActInstance = Instance; do { TermTop = term_TopSymbol(ActTerm); InstanceTop = term_TopSymbol(ActInstance); if (!symbol_IsVariable(TermTop)) { if (!symbol_ContextIsBound(TermTop)) { if (!symbol_IsJunctor(TermTop) && !symbol_IsJunctor(InstanceTop) && !fol_IsPredefinedPred(TermTop) && !fol_IsPredefinedPred(InstanceTop) && !symbol_ContextIsMapped(InstanceTop)) { symbol_ContextSetValue(TermTop, InstanceTop); /* Symbols are ALWAYS bound !*/ *Bindings = list_Cons((POINTER)TermTop,*Bindings); } else { if (!symbol_Equal(TermTop, InstanceTop)) { return FALSE; } } } else { if (symbol_ContextIsBound(TermTop) && !symbol_Equal(symbol_ContextGetValue(TermTop),InstanceTop)) { return FALSE; } } } if (list_Length(term_ArgumentList(ActTerm)) != list_Length(term_ArgumentList(ActInstance))) { return FALSE; } if (term_IsComplex(ActTerm)) { stack_Push(term_ArgumentList(ActInstance)); stack_Push(term_ArgumentList(ActTerm)); } else { if (symbol_IsVariable(TermTop)) { if (!term_VarIsMarked(TermTop, ActMark)) { if (!Variant || symbol_IsVariable(InstanceTop)) { term_CreateValueBinding(TermTop, ActMark, (POINTER)InstanceTop); *Bindings = list_Cons((POINTER)TermTop,*Bindings); } else return FALSE; } else { if (!symbol_Equal((SYMBOL)term_BindingValue(TermTop), InstanceTop)) { return FALSE; } } } } while (!stack_Empty(Stack) && list_Empty(stack_Top())) { stack_Pop(); stack_Pop(); } if (!stack_Empty(Stack)) { ActTerm = (TERM)list_Car(stack_Top()); ActInstance = (TERM)list_Car(stack_NthTop(1)); stack_RplacTop(list_Cdr(stack_Top())); stack_RplacNthTop(1,list_Cdr(stack_NthTop(1))); } } while (!stack_Empty(Stack)); return TRUE; } BOOL fol_CheckFormula(TERM Formula) /******************************************************************* INPUT : A term Formula. RETURN: TRUE iff no free variables occure in Formula and father links are properly set and argument list lengths match arities ********************************************************************/ { LIST FreeVars; FreeVars = fol_FreeVariables(Formula); if (!list_Empty(FreeVars)) { list_Delete(FreeVars); return FALSE; } return term_CheckTerm(Formula); }